Création de scripts d’entrée avancés
S’APPLIQUE À : SDK Python azureml v1
Cet article explique comment écrire des scripts d’entrée pour des cas d’usage spécialisés.
Prérequis
Cet article suppose que vous disposez déjà d’un modèle Machine Learning formé que vous envisagez de déployer avec Azure Machine Learning. Pour en savoir plus sur le déploiement de modèles, consultez Déployer des modèles Machine Learning sur Azure.
Générer automatiquement un schéma Swagger
Si vous voulez générer automatiquement un schéma pour votre service web, spécifiez un exemple d’entrée et/ou de sortie dans le constructeur pour l’un des objets de type définis. Le type et l’exemple sont utilisés pour créer automatiquement le schéma. Azure Machine Learning crée ensuite une spécification OpenAPI (anciennement spécification Swagger) pour le service web pendant le déploiement.
Avertissement
Vous ne devez pas utiliser de données sensibles ou privées comme exemples d’entrée ou de sortie. La page Swagger pour l’inférence hébergée par AML expose les exemples de données.
Les types suivants sont pris en charge :
pandas
numpy
pyspark
- Objet Python standard
Pour utiliser la génération de schéma, incluez le package inference-schema
open source version 1.1.0 ou ultérieure dans votre fichier de dépendances. Pour plus d’informations sur ce package, consultez InferenceSchema sur GitHub. Pour générer un Swagger conforme pour une consommation de service web automatisé, la fonction run() du script de scoring doit avoir la forme d’API suivante :
- Un premier paramètre de type
StandardPythonParameterType
, nommé Inputs et imbriqué - Un deuxième paramètre facultatif de type
StandardPythonParameterType
, nommé GlobalParameters - Retourne un dictionnaire de type
StandardPythonParameterType
, nommé Results et imbriqué
Définissez les exemples de formats d’entrée et de sortie dans les variables input_sample
et output_sample
, qui représentent les formats de requête et de réponse pour le service web. Utilisez ces exemples dans les éléments décoratifs des fonctions d’entrée et de sortie sur la fonction run()
. L’exemple scikit-learn suivant utilise la génération de schéma.
Point de terminaison compatible Power BI
L’exemple suivant montre comment définir la forme d’API en fonction de l’instruction précédente. Cette méthode est prise en charge pour l’utilisation du service web déployé à partir de Power BI.
import json
import pickle
import numpy as np
import pandas as pd
import azureml.train.automl
from sklearn.externals import joblib
from sklearn.linear_model import Ridge
from inference_schema.schema_decorators import input_schema, output_schema
from inference_schema.parameter_types.standard_py_parameter_type import StandardPythonParameterType
from inference_schema.parameter_types.numpy_parameter_type import NumpyParameterType
from inference_schema.parameter_types.pandas_parameter_type import PandasParameterType
def init():
global model
# Replace filename if needed.
model_path = os.path.join(os.getenv('AZUREML_MODEL_DIR'), 'sklearn_regression_model.pkl')
# Deserialize the model file back into a sklearn model.
model = joblib.load(model_path)
# providing 3 sample inputs for schema generation
numpy_sample_input = NumpyParameterType(np.array([[1,2,3,4,5,6,7,8,9,10],[10,9,8,7,6,5,4,3,2,1]],dtype='float64'))
pandas_sample_input = PandasParameterType(pd.DataFrame({'name': ['Sarah', 'John'], 'age': [25, 26]}))
standard_sample_input = StandardPythonParameterType(0.0)
# This is a nested input sample, any item wrapped by `ParameterType` will be described by schema
sample_input = StandardPythonParameterType({'input1': numpy_sample_input,
'input2': pandas_sample_input,
'input3': standard_sample_input})
sample_global_parameters = StandardPythonParameterType(1.0) # this is optional
sample_output = StandardPythonParameterType([1.0, 1.0])
outputs = StandardPythonParameterType({'Results':sample_output}) # 'Results' is case sensitive
@input_schema('Inputs', sample_input)
# 'Inputs' is case sensitive
@input_schema('GlobalParameters', sample_global_parameters)
# this is optional, 'GlobalParameters' is case sensitive
@output_schema(outputs)
def run(Inputs, GlobalParameters):
# the parameters here have to match those in decorator, both 'Inputs' and
# 'GlobalParameters' here are case sensitive
try:
data = Inputs['input1']
# data will be convert to target format
assert isinstance(data, np.ndarray)
result = model.predict(data)
return result.tolist()
except Exception as e:
error = str(e)
return error
Conseil
La valeur de retour du script peut être n’importe quel objet Python sérialisable en JSON. Par exemple, si votre modèle retourne une tramedonnées Pandas contenant plusieurs colonnes, vous pouvez utiliser un élément décoratif de sortie similaire au code suivant :
output_sample = pd.DataFrame(data=[{"a1": 5, "a2": 6}])
@output_schema(PandasParameterType(output_sample))
...
result = model.predict(data)
return result
Données binaires (autrement dit, image)
Si votre modèle accepte des données binaires, comme une image, vous devez modifier le fichier score.py utilisé pour votre déploiement afin d’accepter les requêtes HTTP brutes. Pour accepter des données brutes, utilisez la classe AMLRequest
dans votre script d’entrée et ajoutez l’ élément décoratif @rawhttp
à la fonction run()
.
Voici l’exemple d’un score.py
qui accepte des données binaires :
from azureml.contrib.services.aml_request import AMLRequest, rawhttp
from azureml.contrib.services.aml_response import AMLResponse
from PIL import Image
import json
def init():
print("This is init()")
@rawhttp
def run(request):
print("This is run()")
if request.method == 'GET':
# For this example, just return the URL for GETs.
respBody = str.encode(request.full_path)
return AMLResponse(respBody, 200)
elif request.method == 'POST':
file_bytes = request.files["image"]
image = Image.open(file_bytes).convert('RGB')
# For a real-world solution, you would load the data from reqBody
# and send it to the model. Then return the response.
# For demonstration purposes, this example just returns the size of the image as the response.
return AMLResponse(json.dumps(image.size), 200)
else:
return AMLResponse("bad request", 500)
Important
La classe AMLRequest
se trouve dans l’espace de noms azureml.contrib
. Les entités dans cet espace de noms changent fréquemment car nous cherchons à améliorer le service. Tout ce qui est compris dans cet espace de noms doit être considéré comme une préversion et n’est pas entièrement pris en charge par Microsoft.
Si vous avez besoin d’effectuer un test dans votre environnement de développement local, vous pouvez installer les composants à l’aide de la commande suivante :
pip install azureml-contrib-services
Notes
500 n’est pas recommandé comme code d’état personnalisé, car côté azureml-fe, le code d’état sera réécrit en 502.
- Le code d’état est transmis via azureml-fe, puis envoyé au client.
- Azureml-fe réécrit uniquement le code 500 retourné côté modèle pour devenir 502, le client reçoit 502.
- Mais si azureml-fe lui-même retourne 500, le côté client reçoit toujours 500.
La classe AMLRequest
vous permet d’accéder uniquement aux données publiées brutes dans score.py. Il n’y a aucun composant côté client. À partir d’un client, vous publiez des données normalement. Par exemple, le code Python suivant lit un fichier image et publie les données :
import requests
uri = service.scoring_uri
image_path = 'test.jpg'
files = {'image': open(image_path, 'rb').read()}
response = requests.post(uri, files=files)
print(response.json)
Partage des ressources cross-origin (CORS)
Le partage des ressources Cross-Origin permet de demander des ressources dans une page web à partir d’un autre domaine. CORS fonctionne par le biais d’en-têtes HTTP envoyés avec la demande du client et retournés avec la réponse du service. Pour plus d’informations sur CORS et les en-têtes valides, consultez Cross-origin resource sharing sur Wikipédia.
Pour configurer que votre modèle de déploiement prend en charge le partage des ressources Cross-Origin, utilisez la classe AMLResponse
dans votre script d’entrée. Cette classe vous permet de définir les en-têtes de l’objet de réponse.
L’exemple suivant définit l’en-tête Access-Control-Allow-Origin
de la réponse à partir du script d’entrée :
from azureml.contrib.services.aml_request import AMLRequest, rawhttp
from azureml.contrib.services.aml_response import AMLResponse
def init():
print("This is init()")
@rawhttp
def run(request):
print("This is run()")
print("Request: [{0}]".format(request))
if request.method == 'GET':
# For this example, just return the URL for GET.
# For a real-world solution, you would load the data from URL params or headers
# and send it to the model. Then return the response.
respBody = str.encode(request.full_path)
resp = AMLResponse(respBody, 200)
resp.headers["Allow"] = "OPTIONS, GET, POST"
resp.headers["Access-Control-Allow-Methods"] = "OPTIONS, GET, POST"
resp.headers['Access-Control-Allow-Origin'] = "http://www.example.com"
resp.headers['Access-Control-Allow-Headers'] = "*"
return resp
elif request.method == 'POST':
reqBody = request.get_data(False)
# For a real-world solution, you would load the data from reqBody
# and send it to the model. Then return the response.
resp = AMLResponse(reqBody, 200)
resp.headers["Allow"] = "OPTIONS, GET, POST"
resp.headers["Access-Control-Allow-Methods"] = "OPTIONS, GET, POST"
resp.headers['Access-Control-Allow-Origin'] = "http://www.example.com"
resp.headers['Access-Control-Allow-Headers'] = "*"
return resp
elif request.method == 'OPTIONS':
resp = AMLResponse("", 200)
resp.headers["Allow"] = "OPTIONS, GET, POST"
resp.headers["Access-Control-Allow-Methods"] = "OPTIONS, GET, POST"
resp.headers['Access-Control-Allow-Origin'] = "http://www.example.com"
resp.headers['Access-Control-Allow-Headers'] = "*"
return resp
else:
return AMLResponse("bad request", 400)
Important
La classe AMLResponse
se trouve dans l’espace de noms azureml.contrib
. Les entités dans cet espace de noms changent fréquemment car nous cherchons à améliorer le service. Tout ce qui est compris dans cet espace de noms doit être considéré comme une préversion et n’est pas entièrement pris en charge par Microsoft.
Si vous avez besoin d’effectuer un test dans votre environnement de développement local, vous pouvez installer les composants à l’aide de la commande suivante :
pip install azureml-contrib-services
Avertissement
Azure Machine Learning route uniquement les requêtes POST et GET vers les conteneurs exécutant le service de scoring. Cela peut provoquer des erreurs dues à des navigateurs qui utilisent des requêtes OPTIONS pour des requêtes CORS préalables.
Charger les modèles inscrits
Il existe deux façons de localiser les modèles dans votre script d’entrée :
AZUREML_MODEL_DIR
: variable d’environnement contenant le chemin d’accès à l’emplacement du modèleModel.get_model_path
: API qui retourne le chemin d’accès au fichier de modèle d’après le nom de modèle inscrit
AZUREML_MODEL_DIR
AZUREML_MODEL_DIR
est une variable d’environnement créée pendant le déploiement du service. Vous pouvez utiliser cette variable d’environnement pour rechercher l’emplacement de chaque modèle déployé.
Le tableau suivant décrit la valeur de AZUREML_MODEL_DIR
en fonction du nombre de modèles déployés :
Déploiement | Valeur de la variable d’environnement |
---|---|
Modèle unique | Chemin du dossier contenant le modèle. |
Modèles multiples | Chemin du dossier contenant tous les modèles. Les modèles sont localisés par nom et version dans ce dossier ($MODEL_NAME/$VERSION ) |
Pendant l'inscription et le déploiement des modèles, ceux-ci sont placés à l'emplacement AZUREML_MODEL_DIR et ils conservent leur nom de fichier d'origine.
Pour obtenir le chemin d'accès à un fichier modèle dans votre script d'entrée, combinez la variable d'environnement avec le chemin du fichier que vous recherchez.
Exemple avec un modèle unique
# Example when the model is a file
model_path = os.path.join(os.getenv('AZUREML_MODEL_DIR'), 'sklearn_regression_model.pkl')
# Example when the model is a folder containing a file
file_path = os.path.join(os.getenv('AZUREML_MODEL_DIR'), 'my_model_folder', 'sklearn_regression_model.pkl')
Exemple avec des modèles multiples
Dans ce scénario, deux modèles sont inscrits auprès de l’espace de travail :
my_first_model
: contient un fichier (my_first_model.pkl
) et il n’existe qu’une seule version,1
my_second_model
: contient un fichier (my_second_model.pkl
) et il existe deux versions,1
et2
Quand le service est déployé, les deux modèles sont fournis dans l’opération de déploiement :
first_model = Model(ws, name="my_first_model", version=1)
second_model = Model(ws, name="my_second_model", version=2)
service = Model.deploy(ws, "myservice", [first_model, second_model], inference_config, deployment_config)
Dans l’image Docker qui héberge le service, la variable d’environnement AZUREML_MODEL_DIR
contient le répertoire où se trouvent les modèles. Dans ce répertoire, chacun des modèles se trouve à un emplacement de répertoire MODEL_NAME/VERSION
. Où MODEL_NAME
est le nom du modèle inscrit et VERSION
est la version du modèle. Les fichiers qui composent le modèle inscrit sont stockés dans ces répertoires.
Dans cet exemple, les chemins seraient $AZUREML_MODEL_DIR/my_first_model/1/my_first_model.pkl
et $AZUREML_MODEL_DIR/my_second_model/2/my_second_model.pkl
.
# Example when the model is a file, and the deployment contains multiple models
first_model_name = 'my_first_model'
first_model_version = '1'
first_model_path = os.path.join(os.getenv('AZUREML_MODEL_DIR'), first_model_name, first_model_version, 'my_first_model.pkl')
second_model_name = 'my_second_model'
second_model_version = '2'
second_model_path = os.path.join(os.getenv('AZUREML_MODEL_DIR'), second_model_name, second_model_version, 'my_second_model.pkl')
get_model_path
Quand vous inscrivez un modèle, vous fournissez un nom de modèle qui est utilisé pour gérer le modèle dans le Registre. Vous utilisez ce nom avec la méthode Model.get_model_path() pour récupérer le chemin du ou des fichiers de modèle sur le système de fichiers local. Si vous inscrivez un dossier ou une collection de fichiers, cette API retourne le chemin du répertoire contenant ces fichiers.
Quand vous inscrivez un modèle, vous lui donnez un nom. Le nom correspond à l’endroit où le modèle est placé, localement ou durant le déploiement du service.
Exemples spécifiques de l’infrastructure
Consultez les articles suivants pour obtenir d’autres exemples de script d’entrée pour des cas d’usage spécifiques du Machine Learning :
Contenu connexe
- Résolution des problèmes de déploiement de modèle distant
- Déployer un modèle sur un cluster Azure Kubernetes Service avec v1
- Utiliser un modèle Azure Machine Learning déployé en tant que service web
- Mettre à jour un service web déployé (v1)
- Utiliser un conteneur personnalisé pour déployer un modèle sur un point de terminaison en ligne
- Utiliser TLS pour sécuriser un service web par le biais d’Azure Machine Learning
- Superviser et collecter des données à partir des points de terminaison de service web Machine Learning
- Collecter des données pour des modèles en production
- Déclenchement des applications, des processus et des workflows CI/CD en fonction d’événements Azure Machine Learning