[PYTHON] J'ai essayé d'héberger le modèle d'apprentissage en profondeur de Pytorch avec TorchServe sur Amazon SageMaker

introduction

SageMaker est un service qui fournit un ensemble complet de charges de travail d'apprentissage automatique. En utilisant les données stockées dans S3 etc., il fournit toutes les fonctions nécessaires aux projets d'apprentissage automatique tels que le développement de modèles avec le notebook Jupyter, la gestion de code avec le référentiel Git, la création de tâches de formation, l'hébergement de points de terminaison d'inférence. Je vais.

J'ai lu «Deploying a PyTorch Model for Large-Scale Inference Using TorchServe» sur le blog Amazon Web Services et j'ai essayé d'héberger le modèle à l'aide d'Amazon SageMaker. Ci-dessous, nous présenterons la procédure et l'histoire qui l'entoure.

Veuillez consulter cet article pour la partie conversion du modèle.

procédure

Créer un compartiment S3

Tout d'abord, créez un compartiment dans S3. Cette fois, j'ai créé un bucket nommé torchserve-model. La région est «Asie Pacifique (Tokyo)» et tout sauf le nom est la valeur par défaut.

Création d'instances de notebook

Lorsque vous ouvrez la console Amazon SageMaker, un menu s'affiche dans le volet gauche.

スクリーンショット 2020-07-16 13.58.16.png

Sélectionnez Instance de bloc-notes dans le menu du bloc-notes et cliquez sur Créer une instance de bloc-notes. Définissez les éléments suivants pour les paramètres d'instance et définissez les autres par défaut.

--Paramètres d'instance de notebook --Nom de l'instance de l'ordinateur portable: sagemaker-sample --Permissions et cryptage --IAM Role: Créer un nouveau rôle

Sur l'écran de création de rôle IAM, spécifiez le compartiment S3 que vous avez créé précédemment. スクリーンショット 2020-07-16 14.02.50.png

Après avoir entré les paramètres, cliquez sur Créer une instance de notebook. Vous serez renvoyé à l'écran d'instance de notebook, cliquez donc sur le nom de l'instance créée pour accéder à l'écran de détails. À partir du lien ARN du rôle IAM, ouvrez l'écran IAM, cliquez sur «Joindre la stratégie» et attachez la stratégie «Amazon EC2ContainerRegistryFullAccess». C'est la politique dont vous aurez besoin pour travailler avec ECR plus tard.

Lorsque le statut devient En service, démarrez JupyterLab avec "Open JupyterLab".

スクリーンショット 2020-07-16 14.38.06.png

Tout d'abord, démarrez Terminal depuis Autre de Laucher.

sh-4.2$ ls
anaconda3  Nvidia_Cloud_EULA.pdf  sample-notebooks             tools
examples   README                 sample-notebooks-1594876987  tutorials
LICENSE    SageMaker              src
sh-4.2$ ls SageMaker/
lost+found

L'explorateur sur le côté gauche de l'écran affiche les fichiers sous SageMaker /.

スクリーンショット 2020-07-16 14.41.47.png

git est également installé.

sh-4.2$ git --version
git version 2.14.5

Dans ce qui suit, nous allons créer un bloc-notes et héberger le modèle, mais vous pouvez faire de même avec le bloc-notes du didacticiel. Vous pouvez cloner l'exemple de code avec SageMaker /.

sh-4.2$ cd SageMaker
sh-4.2$ git clone https://github.com/shashankprasanna/torchserve-examples.git

Toutes les étapes sont décrites dans deploy_torchserve.ipynb. Lorsque vous ouvrez le notebook, il vous sera demandé quel noyau Python utiliser, alors sélectionnez conda_pytorch_p36.

Hôte modèle

Tout d'abord, créez un nouveau dossier à partir du bouton de dossier dans le volet gauche et double-cliquez pour entrer dans le dossier créé. Créez ensuite un cahier.

スクリーンショット 2020-07-16 19.17.15.png

Sélectionnez le notebook avec conda_pytorch_p36. Renommez le notebook en deploy_torchserve.ipynb.

Effectue une installation de bibliothèque qui transforme le modèle Pytorch pour le déploiement dans la cellule.

deploy_torchserve.ipynb


!git clone https://github.com/pytorch/serve.git
!pip install serve/model-archiver/

Cette fois, nous hébergerons le modèle densenet161. Téléchargez le fichier de poids entraîné. De plus, étant donné que la classe de modèle d'exemple est incluse dans la bibliothèque clonée précédemment, utilisez le fichier de poids et la classe pour la convertir au format hébergé.

deploy_torchserve.ipynb


!wget -q https://download.pytorch.org/models/densenet161-8d451a50.pth

deploy_torchserve.ipynb


model_file_name = 'densenet161'
!torch-model-archiver --model-name {model_file_name} \
--version 1.0 --model-file serve/examples/image_classifier/densenet_161/model.py \
--serialized-file densenet161-8d451a50.pth \
--extra-files serve/examples/image_classifier/index_to_name.json \
--handler image_classifier

Une fois exécuté, densenet161.mar sera affiché dans le répertoire courant.

Stockez le fichier créé dans S3.

deploy_torchserve.ipynb


#Créez une session boto3 pour obtenir des informations sur la région et le compte
import boto3, time, json
sess    = boto3.Session()
sm      = sess.client('sagemaker')
region  = sess.region_name
account = boto3.client('sts').get_caller_identity().get('Account')

import sagemaker
role = sagemaker.get_execution_role()
sagemaker_session = sagemaker.Session(boto_session=sess)

#À propos, le contenu est le suivant.
# print(region, account, role)
# ap-northeast-1
# xxxxxxxxxxxx 
# arn:aws:iam::xxxxxxxxxxxx:role/service-role/AmazonSageMaker-ExecutionRole-20200716T140377

deploy_torchserve.ipynb


#Spécifiez le nom du compartiment Amazon SageMaker S3
bucket_name = 'torchserve-model'
prefix = 'torchserve'

# print(bucket_name, prefix)
# sagemaker-ap-northeast-1-xxxxxxxxxxxx torchserve

deploy_torchserve.ipynb


#Amazon SageMaker a un modèle tar.Puisqu'il est supposé être dans le fichier gz, densenet161.Tar compressé à partir du fichier mar.Créez un fichier gz.
!tar cvfz {model_file_name}.tar.gz densenet161.mar

deploy_torchserve.ipynb


#Téléchargez le modèle dans le compartiment S3 sous le répertoire du modèle.
!aws s3 cp {model_file_name}.tar.gz s3://{bucket_name}/{prefix}/models/

Ensuite, créez un registre de conteneurs avec ECR.

deploy_torchserve.ipynb


registry_name = 'torchserve'
!aws ecr create-repository --repository-name torchserve

# {
#     "repository": {
#         "repositoryArn": "arn:aws:ecr:ap-northeast-1:xxxxxxxxxxxx:repository/torchserve",
#         "registryId": "xxxxxxxxxxxx:repository",
#         "repositoryName": "torchserve",
#         "repositoryUri": "xxxxxxxxxxxx:repository.dkr.ecr.ap-northeast-1.amazonaws.com/torchserve",
#         "createdAt": 1594893256.0,
#         "imageTagMutability": "MUTABLE",
#         "imageScanningConfiguration": {
#             "scanOnPush": false
#         }
#     }
# }

Une fois loin du cahier, cliquez sur le bouton "+" dans le volet gauche et sélectionnez "Fichier texte" dans Launcher pour créer un Dockerfile.

Dockerfile


FROM ubuntu:18.04

ENV PYTHONUNBUFFERED TRUE

RUN apt-get update && \
    DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y \
    fakeroot \
    ca-certificates \
    dpkg-dev \
    g++ \
    python3-dev \
    openjdk-11-jdk \
    curl \
    vim \
    && rm -rf /var/lib/apt/lists/* \
    && cd /tmp \
    && curl -O https://bootstrap.pypa.io/get-pip.py \
    && python3 get-pip.py

RUN update-alternatives --install /usr/bin/python python /usr/bin/python3 1
RUN update-alternatives --install /usr/local/bin/pip pip /usr/local/bin/pip3 1

RUN pip install --no-cache-dir psutil \
                --no-cache-dir torch \
                --no-cache-dir torchvision
                
ADD serve serve
RUN pip install ../serve/

COPY dockerd-entrypoint.sh /usr/local/bin/dockerd-entrypoint.sh
RUN chmod +x /usr/local/bin/dockerd-entrypoint.sh

RUN mkdir -p /home/model-server/ && mkdir -p /home/model-server/tmp
COPY config.properties /home/model-server/config.properties

WORKDIR /home/model-server
ENV TEMP=/home/model-server/tmp
ENTRYPOINT ["/usr/local/bin/dockerd-entrypoint.sh"]
CMD ["serve"]

Le contenu de Dockerfike est défini comme suit.

--PYTHONUNBUFFERED TRUE empêche stdout et stderr de mettre en mémoire tampon. --Si vous définissez DEBIAN_FRONTEND = noninteractive, Pas de paramètres interactifs. -- - no-install-recommend n'est pas requis, n'installez pas les packages recommandés. --ʻUpdate-alternatives` [priorité des changements] pour Python et pip à utiliser (https://codechacha.com/en/change-python-version/).

Créez également dockerd-entrypoint.sh et config.properties.

dockerd-entrypoint.sh


#!/bin/bash
set -e

if [[ "$1" = "serve" ]]; then
    shift 1
    printenv
    ls /opt
    torchserve --start --ts-config /home/model-server/config.properties
else
    eval "$@"
fi

# prevent docker exit
tail -f /dev/null

Le code suivant est écrit pour le script shell.

--set -e: S'il y a une erreur, le script shell sera arrêté là. -- $ 1: C'est le premier argument. --shift 1: change l'ordre des arguments. Cela vous permet de passer des arguments à la commande suivante comme si elle avait été donnée depuis le début. --printenv: imprime le contenu des variables d'environnement. * Il sera généré dans les journaux Cloud Watch, qui seront introduits ultérieurement. --ʻEval "$ @" : Développez l'argument en tant que commande et exécutez cette commande. Utilisé lors de l'exécution de commandes autres que «serve». --tail -f / dev / null`: Commande factice pour maintenir le conteneur en marche.

config.properties


inference_address=http://0.0.0.0:8080
management_address=http://0.0.0.0:8081
number_of_netty_threads=32
job_queue_size=1000
model_store=/opt/ml/model
load_models=all

C'est un supplément sur le cadre. Voir ici pour plus de détails.

--number_of_netty_threads: Le nombre total de threads sur le front-end, par défaut le nombre de processeurs logiques disponibles dans la JVM. --job_queue_size: Le nombre de travaux d'inférence que le front-end met en file d'attente avant que le back-end ne serve, par défaut à 100. --model_store: L'emplacement de stockage du modèle. * Lors de l'utilisation de SageMaker, le modèle est stocké à partir de S3 dans / opt / ml / model /. --load_models: Même effet que –models au démarrage. Spécifiez le modèle à déployer. Lorsque ʻall, déployez tous les modèles stockés dans model_store`.

Créez une image de conteneur et stockez-la dans le registre. v1 est la balise d'image et ʻimageest le nom de l'image, y compris la balise. Lorsque vous utilisez ECR, donnez un nom d'image selon les règles de <nom du registre> / <nom de l'image>: <tag>. <Nom d'enregistrement> correspond à la valeur de retourrepositoryUri` lors de la création du registre.

La construction a pris environ 15 minutes.

deploy_torchserve.ipynb


image_label = 'v1'
image = f'{account}.dkr.ecr.{region}.amazonaws.com/{registry_name}:{image_label}'

# print(image_label, image)
# v1 xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/torchserve:v1

deploy_torchserve.ipynb


!docker build -t {registry_name}:{image_label} .
!$(aws ecr get-login --no-include-email --region {region})
!docker tag {registry_name}:{image_label} {image}
!docker push {image}

# Sending build context to Docker daemon  399.7MB
# Step 1/16 : FROM ubuntu:18.04
# 18.04: Pulling from library/ubuntu

# 5296b23d: Pulling fs layer 
# 2a4a0f38: Pulling fs layer 
# ...
# 9d6bc5ec: Preparing 
# 0faa4f76: Pushed   1.503GB/1.499GBv1: digest: 
# sha256:bb75ec50d8b0eaeea67f24ce072bce8b70262b99a826e808c35882619d093b4e size: 3247

Il est enfin temps d'héberger le point de terminaison d'inférence. Créez un modèle à déployer avec le code suivant.

deploy_torchserve.ipynb


import sagemaker
from sagemaker.model import Model
from sagemaker.predictor import RealTimePredictor
role = sagemaker.get_execution_role()

model_data = f's3://{bucket_name}/{prefix}/models/{model_file_name}.tar.gz'
sm_model_name = 'torchserve-densenet161'

torchserve_model = Model(model_data = model_data,
                        image = image,
                        role = role,
                        predictor_cls=RealTimePredictor,
                        name = sm_model_name)

Déployez le point de terminaison avec le code suivant. Le déploiement a pris environ 5 minutes.

deploy_torchserve.ipynb


endpoint_name = 'torchserve-endpoint-' + time.strftime("%Y-%m-%d-%H-%M-%S", time.gmtime())
predictor = torchserve_model.deploy(instance_type='ml.m4.xlarge',
 initial_instance_count=1,
 endpoint_name = endpoint_name)

Vous pouvez voir la progression du déploiement dans les journaux Cloud Watch. Vous pouvez afficher la liste des points de terminaison en ouvrant la console Cloud Watch, en cliquant sur Groupes de journaux dans le volet de gauche et en saisissant / aws / sagemaker / Endpoints dans la barre de recherche.

スクリーンショット 2020-07-16 22.33.13.png

Vous pouvez voir le journal de déploiement en cliquant pour ouvrir l'écran des détails et en vérifiant le journal dans Log Stream.

スクリーンショット 2020-07-16 22.35.02.png

Si le déploiement échoue, je pense qu'il génère une erreur. En passant, si une erreur se produit, il continuera à réessayer pendant environ une heure pour se redéployer, donc si vous pensez que quelque chose ne va pas, vous devriez vérifier le journal dès que possible.

スクリーンショット 2020-07-16 22.32.46.png

Faites une demande pour voir si cela fonctionne correctement.

deploy_torchserve.ipynb


!wget -q https://s3.amazonaws.com/model-server/inputs/kitten.jpg 
file_name = 'kitten.jpg'
with open(file_name, 'rb') as f:
    payload = f.read()
    payload = payload

response = predictor.predict(data=payload)
print(*json.loads(response), sep = '\n')

# {'tiger_cat': 0.4693359136581421}
# {'tabby': 0.4633873701095581}
# {'Egyptian_cat': 0.06456154584884644}
# {'lynx': 0.001282821292988956}
# {'plastic_bag': 0.00023323031200561672}

Si vous pouvez obtenir l'instance «prédicteur», vous pouvez faire une demande par la méthode ci-dessus, mais si vous faites une demande de l'extérieur, vous avez besoin d'un SDK. Ouvrez un shell interactif Python sur un PC externe et essayez de faire une requête en utilisant boto3.

$ !wget -q https://s3.amazonaws.com/model-server/inputs/kitten.jpg 
$ python

>>> import json
>>> import boto3
>>> endpoint_name = 'torchserve-endpoint-2020-07-16-13-16-12'
>>> file_name = 'kitten.jpg'
>>> with open(file_name, 'rb') as f:
...     payload = f.read()
...     payload = payload
>>> client = boto3.client('runtime.sagemaker',
        aws_access_key_id='XXXXXXXXXXXXXXXXXXXX',
        aws_secret_access_key='XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
        region_name='ap-northeast-1')
>>> response = client.invoke_endpoint(EndpointName=endpoint_name, 
...                                    ContentType='application/x-image', 
...                                    Body=payload)
>>> print(*json.loads(response['Body'].read()), sep = '\n')
{'tiger_cat': 0.4693359136581421}
{'tabby': 0.4633873701095581}
{'Egyptian_cat': 0.06456154584884644}
{'lynx': 0.001282821292988956}
{'plastic_bag': 0.00023323031200561672}

J'ai pu confirmer que la réponse a été renvoyée correctement.

Vous pouvez également vérifier le modèle déployé, les paramètres de déploiement et les informations de point de terminaison à partir de la console. スクリーンショット 2020-07-16 22.47.36.png スクリーンショット 2020-07-16 22.47.41.png スクリーンショット 2020-07-16 23.59.20.png

en conclusion

Comment c'était (rires)? SageMaker est très pratique. Ne serait-il pas beaucoup plus facile d'héberger un peu d'inférence sur le backend? Si vous souhaitez personnaliser l'interface, une personnalisation plus flexible semble possible, mais Étant donné que TorchServe peut être desservi par un service autre que SageMaker (article précédent), il semble préférable de le développer selon le format TorchServe pour le réutiliser sur AWS.

Recommended Posts

J'ai essayé d'héberger le modèle d'apprentissage en profondeur de Pytorch avec TorchServe sur Amazon SageMaker
J'ai essayé d'héberger un modèle d'apprentissage en profondeur de TensorFlow à l'aide de TensorFlow Serving
J'ai essayé d'héberger un exemple de modèle de Pytorch en utilisant TorchServe
J'ai essayé l'apprentissage en profondeur avec Theano
J'ai essayé le deep learning
J'ai essayé d'utiliser Amazon Glacier
J'ai essayé d'écrire dans un modèle de langage profondément appris
J'ai essayé l'apprentissage par renforcement avec PyBrain
J'ai essayé d'utiliser Amazon SQS avec django-celery
Modèle de reconnaissance d'image utilisant l'apprentissage profond en 2016
[Kaggle] J'ai essayé l'apprentissage d'ensemble avec LightGBM
J'ai essayé l'histoire courante de l'utilisation du Deep Learning pour prédire la moyenne Nikkei
J'ai essayé l'histoire courante de prédire la moyenne Nikkei à l'aide du Deep Learning (backtest)
J'ai essayé d'utiliser l'API à distance avec GAE / J
Un amateur a essayé le Deep Learning avec Caffe (Introduction)
Un amateur a essayé le Deep Learning en utilisant Caffe (Practice)
[Python] Deep Learning: J'ai essayé d'implémenter Deep Learning (DBN, SDA) sans utiliser de bibliothèque.
J'ai essayé d'exécuter Flask sur Raspberry Pi 3 Model B + en utilisant Nginx et uWSGI
[Pythonocc] J'ai essayé d'utiliser la CAO sur un notebook Jupyter
J'ai essayé d'exécuter le didacticiel de détection d'objets en utilisant le dernier algorithme d'apprentissage en profondeur
J'ai essayé d'implémenter diverses méthodes d'apprentissage automatique (modèle de prédiction) en utilisant scicit-learn
Un amateur a essayé le Deep Learning avec Caffe (Vue d'ensemble)
J'ai essayé de créer un modèle avec l'exemple d'Amazon SageMaker Autopilot
J'ai essayé d'apprendre mon propre ensemble de données en utilisant Chainer Trainer
J'ai essayé d'utiliser PySpark de Jupyter 4.x sur EMR
[Deep Learning from scratch] J'ai essayé d'expliquer le décrochage
J'ai essayé de compresser l'image en utilisant l'apprentissage automatique
J'ai essayé d'utiliser paramétré
J'ai essayé d'utiliser argparse
J'ai essayé d'utiliser la mimesis
J'ai essayé d'utiliser anytree
J'ai essayé d'utiliser aiomysql
J'ai essayé d'utiliser Summpy
J'ai essayé d'utiliser coturn
J'ai essayé d'utiliser Pipenv
J'ai essayé d'utiliser matplotlib
J'ai essayé d'utiliser "Anvil".
J'ai essayé d'utiliser Hubot
J'ai essayé d'utiliser ESPCN
J'ai essayé d'utiliser openpyxl
J'ai essayé d'utiliser Ipython
J'ai essayé d'utiliser PyCaret
J'ai essayé d'utiliser cron
J'ai essayé d'utiliser ngrok
J'ai essayé d'utiliser Jupyter
J'ai essayé d'utiliser doctest
J'ai essayé d'utiliser du folium
J'ai essayé d'utiliser jinja2
J'ai essayé d'utiliser du folium
J'ai essayé d'utiliser la fenêtre de temps
[Avec image] J'ai essayé d'utiliser neofetch sur différents OS!
J'ai essayé de refactoriser le modèle CNN de TensorFlow en utilisant TF-Slim
J'ai essayé d'utiliser "Syncthing" pour synchroniser des fichiers sur plusieurs PC
J'ai essayé d'utiliser Tensorboard, un outil de visualisation pour l'apprentissage automatique
J'ai fait un modèle VGG16 en utilisant TensorFlow (en chemin)