<jupyter_start><jupyter_text>Amazon SageMaker Multi-Model Endpoints using your own algorithm container*이 노트북은 [Amazon SageMaker Multi-Model Endpoints using your own algorithm container (영문 원본)](https://github.com/awslabs/amazon-sagemaker-examples/blob/master/advanced_functionality/multi_model_bring_your_own/multi_model_endpoint_bring_your_own.ipynb) 의 한국어 번역입니다.*고객들은 [Amazon SageMaker 멀티 모델 엔드포인트(multi-model endpoints)](https://docs.aws.amazon.com/sagemaker/latest/dg/multi-model-endpoints.html)를 사용하여 최대 수천 개의 모델을 완벽하게 호스팅하는 엔드포인트를 생성할 수 있습니다. 이러한 엔드포인트는 공통 추론 컨테이너(common inference container)에서 제공할 수 있는 많은 모델 중 하나를 온디맨드(on demand)로 호출할 수 있어야 하고 자주 호출되지 않는 모델이 약간의 추가 대기 시간(latency) 허용이 가능한 사례들에 적합합니다. 지속적으로 낮은 추론 대기 시간이 필요한 애플리케이션의 경우 기존의 엔드포인트가 여전히 최선의 선택입니다.High level에서 Amazon SageMaker는 필요에 따라 멀티 모델 엔드포인트에 대한 모델 로딩 및 언로딩을 관리합니다. 특정 모델에 대한 호출 요청이 발생하면 Amazon SageMaker는 해당 모델에 할당된 인스턴스로 요청을 라우팅하고 S3에서 모델 아티팩트(model artifacts)를 해당 인스턴스로 다운로드한 다음 컨테이너의 메모리에 모델 로드를 시작합니다. 로딩이 완료되면 Amazon SageMaker는 요청된 호출을 수행하고 결과를 반환합니다. 모델이 선택된 인스턴스의 메모리에 이미 로드되어 있으면 다운로드 및 로딩 단계들을 건너 뛰고 즉시 호출이 수행됩니다.추론 컨테이너가 멀티 모델 엔드 포인트에서 여러 모델을 제공하려면 특정 모델의 로드(load), 나열(list), 가져오기(get), 언로드(unload) 및 호출(invoke)을 위한 [추가 API](https://docs.aws.amazon.com/sagemaker/latest/dg/build-multi-model-build-container.html)를 구현해야 합니다. 이 노트북은 이러한 API를 구현하는 자체 추론 컨테이너를 작성하는 방법을 보여줍니다.--- Contents1. [Introduction to Multi Model Server (MMS)](Introduction-to-Multi-Model-Server-(MMS))  1. [Handling Out Of Memory conditions](Handling-Out-Of-Memory-conditions)  1. [SageMaker Inference Toolkit](SageMaker-Inference-Toolkit)1. [Building and registering a container using MMS](Building-and-registering-a-container-using-MMS)1. [Set up the environment](Set-up-the-environment)1. [Upload model artifacts to S3](Upload-model-artifacts-to-S3)1. [Create a multi-model endpoint](Create-a-multi-model-endpoint)  1. [Import models into hosting](Import-models-into-hosting)  1. [Create endpoint configuration](Create-endpoint-configuration)  1. [Create endpoint](Create-endpoint)1. [Invoke models](Invoke-models)  1. [Add models to the endpoint](Add-models-to-the-endpoint)  1. [Updating a model](Updating-a-model)1. [(Optional) Delete the hosting resources]((Optional)-Delete-the-hosting-resources)  Introduction to Multi Model Server (MMS)[Multi Model Server](https://github.com/awslabs/multi-model-server)는 머신 러닝 모델을 제공하기 위한 오픈 소스 프레임워크입니다. 단일 모델 내에서 여러 모델을 호스팅하고, 모델을 컨테이너에 동적으로 로드 및 언로드하고, 지정된 로드된 모델에 대한 추론을 수행하기 위해 다중 모델 엔드 포인트에 필요한 HTTP 프런트 엔드 및 모델 관리 기능을 제공합니다.MMS는 자체 알고리즘을 구현할 수 있는 플러그 가능한 커스텀 백엔드 핸들러(pluggable custom backend handler)를 지원합니다. 이 예제는 MXNet 모델의 로딩 및 추론을 지원하는 핸들러를 사용합니다.<jupyter_code>!pygmentize container/model_handler.py<jupyter_output>[33m"""[39;49;00m
[33mModelHandler defines an example model handler for load and inference requests for MXNet CPU models[39;49;00m
[33m"""[39;49;00m
[34mfrom[39;49;00m [04m[36mcollections[39;49;00m [34mimport[39;49;00m namedtuple
[34mimport[39;49;00m [04m[36mglob[39;49;00m
[34mimport[39;49;00m [04m[36mjson[39;49;00m
[34mimport[39;49;00m [04m[36mlogging[39;49;00m
[34mimport[39;49;00m [04m[36mos[39;49;00m
[34mimport[39;49;00m [04m[36mre[39;49;00m

[34mimport[39;49;00m [04m[36mmxnet[39;49;00m [34mas[39;49;00m [04m[36mmx[39;49;00m
[34mimport[39;49;00m [04m[36mnumpy[39;49;00m [34mas[39;49;00m [04m[36mnp[39;49;00m

[34mclass[39;49;00m [04m[32mModelHandler[39;49;00m([36mobject[39;49;00m):
    [33m"""[39;49;00m
[33m    A sample Model handler implementation.[39;49;00m
[33m    """[39;49;00m

    [34mdef[39;49;00m [32m__init__[39;49;00m([36mself[39;49;00m):
        [36mself[39;49;00m.initialized = [[...]<jupyter_text>`handle(data, context)` 및 `initialize(self, context)` 메소드가 중요합니다.모델이 메모리에 로드될 때 `initialize` 메소드가 호출됩니다. 이 예제에서는 `model_dir`의 모델 아티팩트를 MXNet에 로드합니다.모델을 호출할 때 `handle` 메소드가 호출됩니다. 이 예제에서는 입력 페이로드의 유효성을 검사한 다음, 입력값을 MXNet에 전달하여 출력값을 반환합니다.이 핸들러 클래스는 컨테이너에 로드된 모든 모델에 대해 인스턴스화되므로, 핸들러의 상태가 모델 간에 공유되지 않습니다. Handling Out Of Memory conditions메모리 부족으로 MXNet이 모델을 로드하지 못하면 `MemoryError`가 발생합니다. 메모리 부족이나 다른 리소스 제약으로 인해 모델을 로드할 수 없는 경우에는 항상 `MemoryError`를 발생시켜야 합니다. MMS는 `MemoryError`를 해석하고 507 HTTP 상태 코드를 SageMaker에 반환합니다. 여기서 SageMaker는 사용되지 않은 모델 언로딩을 시작(initiate)하여 리소스를 회수(reclaim)하여 요청된 모델을 로드할 수 있습니다. SageMaker Inference ToolkitMMS 시작 시 프론트엔드 서버에 대한 [다양한 설정들](https://github.com/awslabs/multi-model-server/blob/master/docker/advanced_settings.mddescription-of-config-file-settings)을 지원합니다.[SageMaker Inference Toolkit](https://github.com/aws/sagemaker-inference-toolkit)은 SageMaker 멀티 모델 엔드포인트와 호환되는 방식으로 MMS를 부트스트랩하는 라이브러리로 중요한 성능 파라메터들을 조정할 수 있습니다. 모델 당 worker 수와 같은 이 예제의 추론 컨테이너는 추론 툴킷(Inference Toolkit)을 사용하여 MMS를 시작합니다. MMS 시작에 관한 스크립트는 __`container/dockerd-entrypoint.py`__ 파일에서 확인할 수 있습니다.  Building and registering a container using MMS아래 쉘 스크립트는 MMS를 프론트엔드(SageMaker Inference Toolkit을 통해 설정)로 사용하는 Docker 이미지(image)와 위에서 백엔드 핸들러로 확인한 `container/model_handler.py` 를 빌드합니다. 그런 다음, 이미지를 계정의 ECR 저장소에 업로드합니다.<jupyter_code>%%sh

# The name of our algorithm
algorithm_name=demo-sagemaker-multimodel

cd container

account=$(aws sts get-caller-identity --query Account --output text)

# Get the region defined in the current configuration (default to us-west-2 if none defined)
region=$(aws configure get region)
region=${region:-us-west-2}

fullname="${account}.dkr.ecr.${region}.amazonaws.com/${algorithm_name}:latest"

# If the repository doesn't exist in ECR, create it.
aws ecr describe-repositories --repository-names "${algorithm_name}" > /dev/null 2>&1

if [ $? -ne 0 ]
then
    aws ecr create-repository --repository-name "${algorithm_name}" > /dev/null
fi

# Get the login command from ECR and execute it directly
$(aws ecr get-login --region ${region} --no-include-email)

# Build the docker image locally with the image name and then push it to ECR
# with the full name.

docker build -q -t ${algorithm_name} .
docker tag ${algorithm_name} ${fullname}

docker push ${fullname}<jupyter_output>Login Succeeded
sha256:060139c29046dbaebeb7287af528b8267a243e121f8805f4856075cd34310051
The push refers to repository [143656149352.dkr.ecr.ap-northeast-2.amazonaws.com/demo-sagemaker-multimodel]
7d956ab809ad: Preparing
6678f392964e: Preparing
84176b0a0a11: Preparing
10bca8733be2: Preparing
aa9339a0976b: Preparing
c227ec35d60e: Preparing
ddf4568454c0: Preparing
cd19ebef0b86: Preparing
aa7f8c8d5f39: Preparing
48817fbd6c92: Preparing
1b039d138968: Preparing
7082d7d696f8: Preparing
c227ec35d60e: Waiting
ddf4568454c0: Waiting
cd19ebef0b86: Waiting
aa7f8c8d5f39: Waiting
48817fbd6c92: Waiting
1b039d138968: Waiting
7082d7d696f8: Waiting
84176b0a0a11: Pushed
10bca8733be2: Pushed
7d956ab809ad: Pushed
6678f392964e: Pushed
aa7f8c8d5f39: Pushed
c227ec35d60e: Pushed
ddf4568454c0: Pushed
48817fbd6c92: Pushed
1b039d138968: Pushed
7082d7d696f8: Pushed
aa9339a0976b: Pushed
cd19ebef0b86: Pushed
latest: digest: sha256:7e4754b3d6b9c60cf25b412d0768503d7f1889e2470bac0b1159728bc2d3c3bc size: 2820<jupyter_text>Set up the environment멀티 모델 엔드포인트에서 호출할 수 있는 모델 아티팩트가 있는 S3 버킷 및 접두부(prefix)를 정의합니다.또한 SageMaker가 위에서 생성한 모델 아티팩트 및 ECR 이미지에 액세스할 수 있도록 IAM 역할을 정의합니다.<jupyter_code>!pip install -qU awscli boto3 sagemaker
import boto3
from sagemaker import get_execution_role

sm_client = boto3.client(service_name='sagemaker')
runtime_sm_client = boto3.client(service_name='sagemaker-runtime')

account_id = boto3.client('sts').get_caller_identity()['Account']
region = boto3.Session().region_name

bucket = 'sagemaker-{}-{}'.format(region, account_id)
prefix = 'demo-multimodel-endpoint'

role = get_execution_role()<jupyter_output><empty_output><jupyter_text>Upload model artifacts to S3이 예시에서 ImageNet datset에 대해 사전 학습된 ResNet 18 및 ResNet 152 모델을 사용합니다. 먼저 MXNet model zoo에서 모델을 다운로드한 다음 모델을 S3에 업로드합니다.<jupyter_code>import mxnet as mx
import os
import tarfile

model_path = 'http://data.mxnet.io/models/imagenet/'

mx.test_utils.download(model_path+'resnet/18-layers/resnet-18-0000.params', None, 'data/resnet_18')
mx.test_utils.download(model_path+'resnet/18-layers/resnet-18-symbol.json', None, 'data/resnet_18')
mx.test_utils.download(model_path+'synset.txt', None, 'data/resnet_18')

with open('data/resnet_18/resnet-18-shapes.json', 'w') as file:
    file.write('[{"shape": [1, 3, 224, 224], "name": "data"}]')
    
with tarfile.open('data/resnet_18.tar.gz', 'w:gz') as tar:
    tar.add('data/resnet_18', arcname='.')
mx.test_utils.download(model_path+'resnet/152-layers/resnet-152-0000.params', None, 'data/resnet_152')
mx.test_utils.download(model_path+'resnet/152-layers/resnet-152-symbol.json', None, 'data/resnet_152')
mx.test_utils.download(model_path+'synset.txt', None, 'data/resnet_152')

with open('data/resnet_152/resnet-152-shapes.json', 'w') as file:
    file.write('[{"shape": [1, 3, 224, 224], "name": "data"}]')
    
with tarfile.open('data/resnet_152.tar.gz', 'w:gz') as tar:
    tar.add('data/resnet_152', arcname='.')
model_path
from botocore.client import ClientError
import os

s3 = boto3.resource('s3')
try:
    s3.meta.client.head_bucket(Bucket=bucket)
except ClientError:
    s3.create_bucket(Bucket=bucket,
                     CreateBucketConfiguration={
                         'LocationConstraint': region
                     })

models = {'resnet_18.tar.gz', 'resnet_152.tar.gz'}

for model in models:
    key = os.path.join(prefix, model)
    with open('data/'+model, 'rb') as file_obj:
        s3.Bucket(bucket).Object(key).upload_fileobj(file_obj)<jupyter_output><empty_output><jupyter_text>Create a multi-model endpoint Import models into hosting멀티 모델 엔드포인트에 대한 모델 엔티티를 작성할 때 컨테이너의 `ModelDataUrl`은 엔드포인트에서 호출 할 수 있는 모델 아티팩트가 있는 S3 접두부(prefix)입니다. 나머지 S3 경로는 모델을 호출할 때 지정됩니다.컨테이너 모드(`Mode`)는 컨테이너가 여러 모델들을 호스팅함을 나타내기 위해 `MultiModel`로 지정됩니다.<jupyter_code>from time import gmtime, strftime

model_name = 'DEMO-MultiModelModel' + strftime("%Y-%m-%d-%H-%M-%S", gmtime())
model_url = 'https://s3-{}.amazonaws.com/{}/{}/'.format(region, bucket, prefix)
container = '{}.dkr.ecr.{}.amazonaws.com/{}:latest'.format(account_id, region, 'demo-sagemaker-multimodel')

print('Model name: ' + model_name)
print('Model data Url: ' + model_url)
print('Container image: ' + container)

container = {
    'Image': container,
    'ModelDataUrl': model_url,
    'Mode': 'MultiModel'
}

create_model_response = sm_client.create_model(
    ModelName = model_name,
    ExecutionRoleArn = role,
    Containers = [container])

print("Model Arn: " + create_model_response['ModelArn'])<jupyter_output>Model name: DEMO-MultiModelModel2019-11-27-08-29-01
Model data Url: https://s3-ap-northeast-2.amazonaws.com/sagemaker-ap-northeast-2-143656149352/demo-multimodel-endpoint/
Container image: 143656149352.dkr.ecr.ap-northeast-2.amazonaws.com/demo-sagemaker-multimodel:latest
Model Arn: arn:aws:sagemaker:ap-northeast-2:143656149352:model/demo-multimodelmodel2019-11-27-08-29-01<jupyter_text>Create endpoint configuration엔드포인트 설정 생성은 단일 모델 엔드포인트와 동일한 방식으로 작동합니다.<jupyter_code>endpoint_config_name = 'DEMO-MultiModelEndpointConfig-' + strftime("%Y-%m-%d-%H-%M-%S", gmtime())
print('Endpoint config name: ' + endpoint_config_name)

create_endpoint_config_response = sm_client.create_endpoint_config(
    EndpointConfigName = endpoint_config_name,
    ProductionVariants=[{
        'InstanceType': 'ml.m5.xlarge',
        'InitialInstanceCount': 2,
        'InitialVariantWeight': 1,
        'ModelName': model_name,
        'VariantName': 'AllTraffic'}])

print("Endpoint config Arn: " + create_endpoint_config_response['EndpointConfigArn'])<jupyter_output>Endpoint config name: DEMO-MultiModelEndpointConfig-2019-11-27-08-29-12
Endpoint config Arn: arn:aws:sagemaker:ap-northeast-2:143656149352:endpoint-config/demo-multimodelendpointconfig-2019-11-27-08-29-12<jupyter_text>Create endpoint마찬가지로, 엔드포인트 생성은 단일 모델 엔드포인트와 동일한 방식으로 작동합니다.<jupyter_code>import time

endpoint_name = 'DEMO-MultiModelEndpoint-' + strftime("%Y-%m-%d-%H-%M-%S", gmtime())
print('Endpoint name: ' + endpoint_name)

create_endpoint_response = sm_client.create_endpoint(
    EndpointName=endpoint_name,
    EndpointConfigName=endpoint_config_name)
print('Endpoint Arn: ' + create_endpoint_response['EndpointArn'])

resp = sm_client.describe_endpoint(EndpointName=endpoint_name)
status = resp['EndpointStatus']
print("Endpoint Status: " + status)

print('Waiting for {} endpoint to be in service...'.format(endpoint_name))
waiter = sm_client.get_waiter('endpoint_in_service')
waiter.wait(EndpointName=endpoint_name)<jupyter_output>Endpoint name: DEMO-MultiModelEndpoint-2019-11-27-08-29-16
Endpoint Arn: arn:aws:sagemaker:ap-northeast-2:143656149352:endpoint/demo-multimodelendpoint-2019-11-27-08-29-16
Endpoint Status: Creating
Waiting for DEMO-MultiModelEndpoint-2019-11-27-08-29-16 endpoint to be in service...<jupyter_text>Invoke models이제 이전에 S3에 업로드한 모델을 호출해 보겠습니다. SageMaker가 모델 아티팩트를 S3에서 인스턴스로 다운로드하여 컨테이너에 로드하므로 모델의 첫번째 호출이 느려질 수 있습니다.먼저 고양이 이미지를 페이로드로 다운로드하여 모델을 호출한 다음 `InvokeEndpoint`를 호출하여 ResNet 18 모델을 호출합니다. `TargetModel` 필드는 모델 작성시 `ModelDataUrl`에 지정된 S3 접두부와 연결되어 S3에서 모델의 위치를 생성합니다.<jupyter_code>fname = mx.test_utils.download('https://github.com/dmlc/web-data/blob/master/mxnet/doc/tutorials/python/predict_image/cat.jpg?raw=true', 'cat.jpg')

with open(fname, 'rb') as f:
    payload = f.read()
%%time

import json

response = runtime_sm_client.invoke_endpoint(
    EndpointName=endpoint_name,
    ContentType='application/x-image',
    TargetModel='resnet_18.tar.gz', # this is the rest of the S3 path where the model artifacts are located
    Body=payload)

print(*json.loads(response['Body'].read()), sep = '\n')<jupyter_output>probability=0.244390, class=n02119022 red fox, Vulpes vulpes
probability=0.170341, class=n02119789 kit fox, Vulpes macrotis
probability=0.145019, class=n02113023 Pembroke, Pembroke Welsh corgi
probability=0.059833, class=n02356798 fox squirrel, eastern fox squirrel, Sciurus niger
probability=0.051555, class=n02123159 tiger cat
CPU times: user 13.5 ms, sys: 0 ns, total: 13.5 ms
Wall time: 2.71 s<jupyter_text>동일한 ResNet 18 모델을 두번째로 호출하면, 이미 인스턴스에 다운로드되어 컨테이너에 로드되므로 추론이 더 빠르게 수행됩니다.<jupyter_code>%%time

response = runtime_sm_client.invoke_endpoint(
    EndpointName=endpoint_name,
    ContentType='application/x-image',
    TargetModel='resnet_18.tar.gz',
    Body=payload)

print(*json.loads(response['Body'].read()), sep = '\n')<jupyter_output>probability=0.244390, class=n02119022 red fox, Vulpes vulpes
probability=0.170341, class=n02119789 kit fox, Vulpes macrotis
probability=0.145019, class=n02113023 Pembroke, Pembroke Welsh corgi
probability=0.059833, class=n02356798 fox squirrel, eastern fox squirrel, Sciurus niger
probability=0.051555, class=n02123159 tiger cat
CPU times: user 6.03 ms, sys: 0 ns, total: 6.03 ms
Wall time: 156 ms<jupyter_text>Invoke another model멀티 모델 엔드 포인트의 성능을 발휘하기 위해 다른 모델(`resnet_152.tar.gz`)을 `TargetModel`로 지정하고 동일한 엔드포인트를 사용하여 추론을 수행 할 수 있습니다.<jupyter_code>%%time

response = runtime_sm_client.invoke_endpoint(
    EndpointName=endpoint_name,
    ContentType='application/x-image',
    TargetModel='resnet_152.tar.gz',
    Body=payload)

print(*json.loads(response['Body'].read()), sep = '\n')<jupyter_output>probability=0.386026, class=n02119022 red fox, Vulpes vulpes
probability=0.300927, class=n02119789 kit fox, Vulpes macrotis
probability=0.029575, class=n02123045 tabby, tabby cat
probability=0.026005, class=n02123159 tiger cat
probability=0.023201, class=n02113023 Pembroke, Pembroke Welsh corgi
CPU times: user 15.5 ms, sys: 80 µs, total: 15.5 ms
Wall time: 7.2 s<jupyter_text>Add models to the endpoint엔드포인트를 업데이트하지 않고도 엔드포인트에 더 많은 모델을 추가할 수 있습니다. 아래에는 `squeezenet_v1.0`이라는 세번째 모델이 추가되었습니다. 엔드포인트 뒤에 여러 모델들을 호스팅하는 방법을 보여주기 위해, S3에서 이름들을 약간 다르게 하여 10번 복제합니다. 보다 현실적인 시나리오에서는 10개의 새로운 모델이 될 수 있습니다.<jupyter_code>mx.test_utils.download(model_path+'squeezenet/squeezenet_v1.0-0000.params', None, 'data/squeezenet_v1.0')
mx.test_utils.download(model_path+'squeezenet/squeezenet_v1.0-symbol.json', None, 'data/squeezenet_v1.0')
mx.test_utils.download(model_path+'synset.txt', None, 'data/squeezenet_v1.0')

with open('data/squeezenet_v1.0/squeezenet_v1.0-shapes.json', 'w') as file:
    file.write('[{"shape": [1, 3, 224, 224], "name": "data"}]')
    
with tarfile.open('data/squeezenet_v1.0.tar.gz', 'w:gz') as tar:
    tar.add('data/squeezenet_v1.0', arcname='.')
file = 'data/squeezenet_v1.0.tar.gz'

for x in range(0, 10):
    s3_file_name = 'demo-subfolder/squeezenet_v1.0_{}.tar.gz'.format(x)
    key = os.path.join(prefix, s3_file_name)
    with open(file, 'rb') as file_obj:
        s3.Bucket(bucket).Object(key).upload_fileobj(file_obj)
    models.add(s3_file_name)

print('Number of models: {}'.format(len(models)))
print('Models: {}'.format(models))<jupyter_output>Number of models: 12
Models: {'demo-subfolder/squeezenet_v1.0_0.tar.gz', 'demo-subfolder/squeezenet_v1.0_2.tar.gz', 'resnet_18.tar.gz', 'demo-subfolder/squeezenet_v1.0_1.tar.gz', 'demo-subfolder/squeezenet_v1.0_6.tar.gz', 'demo-subfolder/squeezenet_v1.0_5.tar.gz', 'demo-subfolder/squeezenet_v1.0_8.tar.gz', 'resnet_152.tar.gz', 'demo-subfolder/squeezenet_v1.0_9.tar.gz', 'demo-subfolder/squeezenet_v1.0_4.tar.gz', 'demo-subfolder/squeezenet_v1.0_7.tar.gz', 'demo-subfolder/squeezenet_v1.0_3.tar.gz'}<jupyter_text>SqueezeNet 모델을 S3에 업로드한 후 각 호출에 대해 S3 접두부(prefix) 뒤에 있는 12개 모델 중 하나를 임의로 선택하고, 각 호출 응답(invoke response)에서 가장 높은 확률을 출력하는 레이블 개수를 출력하기 위해 엔드포인트를 100번 호출해 보겠습니다.<jupyter_code>models
%%time

import random
from collections import defaultdict

results = defaultdict(int)

for x in range(0, 100):
    target_model = random.choice(tuple(models))
    response = runtime_sm_client.invoke_endpoint(
        EndpointName=endpoint_name,
        ContentType='application/x-image',
        TargetModel=target_model,
        Body=payload)

    results[json.loads(response['Body'].read())[0]] += 1
    
print(*results.items(), sep = '\n')<jupyter_output>('probability=0.386026, class=n02119022 red fox, Vulpes vulpes', 5)
('probability=0.294885, class=n02326432 hare', 86)
('probability=0.244390, class=n02119022 red fox, Vulpes vulpes', 9)
CPU times: user 380 ms, sys: 23.9 ms, total: 404 ms
Wall time: 30.9 s<jupyter_text>Updating a model모델을 업데이트하려면 위와 동일한 방법으로 새 모델로 추가하세요. 예를 들어, `resnet_18.tar.gz` 모델을 재학습했으며 호출을 시작하려는 경우, `resnet_18_v2.tar.gz`와 같은 새로운 이름으로 S3 접두사 뒤에 업데이트된 모델 아티팩트를 업로드한 다음 `TargetModel` 필드를 변경합니다. 그러면, `resnet_18.tar.gz` 대신 `resnet_18_v2.tar.gz`를 호출합니다. 모델의 이전 버전이 여전히 컨테이너 또는 엔드포인트 인스턴스의 스토리지 볼륨에 로드 될 수 있으므로 Amazon S3에서 모델 아티팩트를 덮어 쓰지 않으려고 합니다. 새 모델을 호출하면 이전 버전의 모델을 호출할 수 있습니다.  (Optional) Delete the hosting resources<jupyter_code>sm_client.delete_endpoint(EndpointName=endpoint_name)
sm_client.delete_endpoint_config(EndpointConfigName=endpoint_config_name)
sm_client.delete_model(ModelName=model_name)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.12291865521264185, 'fraction_numerical': 0.07381482659879096, 'mean_word_length': 5.527864312911042, 'pattern_counts': {'":': 6, '<': 43, '<?xml version=': 0, '>': 46, 'https://': 9, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 10, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '13', 'dir': 'jupyter-structured-clean-dedup', 'id': '641128', 'license': 'MIT-0', 'n_tokens_mistral': 9953, 'n_tokens_neox': 10329, 'n_words': 1660, 'path': 'multi-model-endpoint/multi_model_endpoint_bring_your_own.ipynb', 'repo_name': 'tweety0201/sagemaker-studio-workshop-kr-ctc', 'size': '18858'}