Share via


Creazione avanzata di script di immissione

SI APPLICA A:Python SDK azureml v1

Questo articolo illustra come scrivere script di immissione per casi d'uso specializzati.

Prerequisiti

Questo articolo presuppone che sia già disponibile un modello di Machine Learning con training che si intende distribuire con Azure Machine Learning. Per altre informazioni sulla distribuzione dei modelli, vedere Distribuire modelli di Machine Learning in Azure.

Si genera automaticamente uno schema di Swagger

Per generare automaticamente uno schema per il servizio Web, fornire un esempio dell'input e/o dell'output nel costruttore per uno degli oggetti di tipo definiti. Il tipo e l'esempio vengono usati per creare automaticamente lo schema. Azure Machine Learning crea quindi una specifica OpenAPI (in precedenza specifica Swagger) per il servizio Web durante la distribuzione.

Avviso

Non è necessario usare dati sensibili o privati per l'input o l'output di esempio. La pagina Swagger per l'inferenza ospitata in AML espone i dati di esempio.

Questi tipi sono attualmente supportati:

  • pandas
  • numpy
  • pyspark
  • Oggetto Python standard

Per usare la generazione dello schema, includere il pacchetto open source inference-schema versione 1.1.0 o successiva nel file delle dipendenze. Per altre informazioni su questo pacchetto, vedere InferenceSchema in GitHub. Per generare Swagger conforme per l'utilizzo automatizzato del servizio Web, la funzione run() degli script di assegnazione dei punteggi deve avere una forma API di:

  • Primo parametro di tipo StandardPythonParameterType, denominato Input e annidato
  • Secondo parametro facoltativo di tipo StandardPythonParameterType, denominato GlobalParameters
  • Restituisce un dizionario di tipo StandardPythonParameterType, denominato Results e annidato

Definire i formati di esempio di input e output nelle input_sample variabili e output_sample che rappresentano i formati di richiesta e risposta per il servizio Web. Usare questi esempi negli elementi decorator della funzione di input e output nella run() funzione . L'esempio scikit-learn seguente usa la generazione dello schema.

Endpoint compatibile con Power BI

L'esempio seguente illustra come definire la forma API in base all'istruzione precedente. Questo metodo è supportato per l'utilizzo del servizio Web distribuito da 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

Suggerimento

Il valore restituito dallo script può essere qualsiasi oggetto Python serializzabile in JSON. Ad esempio, se il modello restituisce un frame di dati Pandas contenente più colonne, è possibile usare un elemento Decorator di output simile al codice seguente:

output_sample = pd.DataFrame(data=[{"a1": 5, "a2": 6}])
@output_schema(PandasParameterType(output_sample))
...
result = model.predict(data)
return result

Dati binari (ovvero immagine)

Se il modello accetta dati binari, ad esempio un'immagine, è necessario modificare il file score.py usato per la distribuzione per accettare richieste HTTP non elaborate. Per accettare dati non elaborati, usare la AMLRequest classe nello script di immissione e aggiungere l'elemento @rawhttp Decorator alla run() funzione .

Di seguito è riportato un esempio di che score.py accetta dati binari:

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)

Importante

La classe AMLRequest si trova nello spazio dei nomi azureml.contrib. Le entità in questo spazio dei nomi cambiano frequentemente man mano che si lavora per migliorare il servizio. Qualsiasi elemento in questo spazio dei nomi deve essere considerato un'anteprima non completamente supportata da Microsoft.

Se è necessario testarlo nell'ambiente di sviluppo locale, è possibile installare i componenti usando il comando seguente:

pip install azureml-contrib-services

Nota

500 non è consigliato come codice di stato personalizzato, come sul lato azureml-fe, il codice di stato verrà riscritto in 502.

  • Il codice di stato viene passato tramite azureml-fe, quindi inviato al client.
  • Azureml-fe riscrive solo i 500 restituiti dal lato del modello per essere 502, il client riceve 502.
  • Tuttavia, se azureml-fe restituisce 500, il lato client riceve comunque 500.

La AMLRequest classe consente solo di accedere ai dati pubblicati non elaborati nel file score.py , non esiste alcun componente lato client. Da un client si pubblicano i dati come di consueto. Ad esempio, il codice Python seguente legge un file di immagine e pubblica i dati:

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)

Condivisione di risorse tra le origini (CORS)

La condivisione di risorse tra le origini è un modo per consentire alle risorse in una pagina Web di essere richiesta da un altro dominio. CORS funziona tramite intestazioni HTTP inviate con la richiesta client e restituite con la risposta del servizio. Per altre informazioni su CORS e intestazioni valide, vedere Condivisione di risorse tra le origini in Wikipedia.

Per configurare la distribuzione del modello per supportare CORS, usare la AMLResponse classe nello script di immissione. Questa classe consente di impostare le intestazioni sull'oggetto risposta.

Nell'esempio seguente viene impostata l'intestazione Access-Control-Allow-Origin per la risposta dallo script di immissione:

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)

Importante

La classe AMLResponse si trova nello spazio dei nomi azureml.contrib. Le entità in questo spazio dei nomi cambiano frequentemente man mano che si lavora per migliorare il servizio. Qualsiasi elemento in questo spazio dei nomi deve essere considerato un'anteprima non completamente supportata da Microsoft.

Se è necessario testarlo nell'ambiente di sviluppo locale, è possibile installare i componenti usando il comando seguente:

pip install azureml-contrib-services

Avviso

Azure Machine Learning instrada solo le richieste POST e GET ai contenitori che eseguono il servizio di assegnazione dei punteggi. Ciò può causare errori causati dai browser che usano le richieste OPTIONS alle richieste CORS pre-in anteprima.

Caricare i modelli registrati

Sono disponibili due modalità per individuare i modelli nello script di immissione:

  • AZUREML_MODEL_DIR: variabile di ambiente contenente il percorso del modello
  • Model.get_model_path: API che restituisce il percorso del file del modello usando il nome del modello registrato

AZUREML_MODEL_DIR

AZUREML_MODEL_DIR è una variabile di ambiente creata durante la distribuzione del servizio. È possibile usare questa variabile di ambiente per trovare il percorso dei modelli distribuiti.

La tabella seguente descrive il valore di AZUREML_MODEL_DIR a seconda del numero di modelli distribuiti:

Distribuzione Valore della variabile di ambiente
Modello singolo Percorso della cartella contenente il modello.
Più modelli Percorso della cartella contenente tutti i modelli. I modelli si trovano in base al nome e alla versione in questa cartella ($MODEL_NAME/$VERSION)

Durante la registrazione e la distribuzione del modello, i modelli vengono inseriti nel percorso di AZUREML_MODEL_DIR e i relativi nomi file originali vengono mantenuti.

Per ottenere il percorso di un file di modello nello script di immissione, combinare la variabile di ambiente con il percorso del file che si sta cercando.

Esempio di modello singolo

# 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')

Esempio di più modelli

In questo scenario, due modelli vengono registrati nell'area di lavoro:

  • my_first_model: contiene un file (my_first_model.pkl) e c'è una sola versione, 1
  • my_second_model: contiene un file (my_second_model.pkl) e sono disponibili due versioni 1 e 2

Quando il servizio è stato distribuito, entrambi i modelli vengono forniti nell'operazione di distribuzione:

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)

Nell'immagine Docker che ospita il servizio, la AZUREML_MODEL_DIR variabile di ambiente contiene la directory in cui si trovano i modelli. In questa directory, ognuno dei modelli si trova in un percorso di directory di MODEL_NAME/VERSION. Dove MODEL_NAME è il nome del modello registrato e VERSION è la versione del modello. I file che costituiscono il modello registrato vengono archiviati in queste directory.

In questo esempio i percorsi sarebbero $AZUREML_MODEL_DIR/my_first_model/1/my_first_model.pkl e $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

Quando si registra un modello, specificare un nome del modello usato per la gestione del modello nel Registro di sistema. Questo nome viene usato con il metodo Model.get_model_path() per recuperare il percorso del file o dei file del modello nel file system locale. Se si registra una cartella o una raccolta di file, questa API restituisce il percorso della directory che contiene tali file.

Quando si registra un modello, si assegna un nome. Il nome corrisponde alla posizione in cui viene inserito il modello, in locale o durante la distribuzione del servizio.

Esempi specifici del framework

Per altri esempi di script di immissione per casi d'uso specifici di Machine Learning, vedere gli articoli seguenti: