Tutorial: Implantar um modelo de classificação de imagem em Instâncias de Contêiner do AzureTutorial: Deploy an image classification model in Azure Container Instances

Este tutorial é parte dois de uma série de tutoriais de duas partes.This tutorial is part two of a two-part tutorial series. No tutorial anterior, você treinou modelos de machine learning e, depois, registrou um modelo no workspace na nuvem.In the previous tutorial, you trained machine learning models and then registered a model in your workspace on the cloud.

Agora, você está pronto para implantar o modelo como um serviço Web na Instâncias de Contêiner do Azure.Now you're ready to deploy the model as a web service in Azure Container Instances. Um serviço Web é uma imagem, neste caso, uma imagem do Docker.A web service is an image, in this case a Docker image. Ele encapsula a lógica de pontuação e o próprio modelo.It encapsulates the scoring logic and the model itself.

Nesta parte do tutorial, você deve usar o Serviço do Azure Machine Learning para as seguintes tarefas:In this part of the tutorial, you use Azure Machine Learning service for the following tasks:

  • Configurar seu ambiente de teste.Set up your testing environment.
  • Recuperar o modelo de seu workspace.Retrieve the model from your workspace.
  • Testar o modelo localmente.Test the model locally.
  • Implantar o modelo nas Instâncias de Contêiner.Deploy the model to Container Instances.
  • Testar o modelo implantado.Test the deployed model.

Instâncias de Contêiner são uma ótima solução para testar e compreender o fluxo de trabalho.Container Instances is a great solution for testing and understanding the workflow. Para implantações de produção escalonável, considere usar o Serviço de Kubernetes do Azure.For scalable production deployments, consider using Azure Kubernetes Service. Para obter mais informações, confira como e em que local implantar.For more information, see how to deploy and where.

Observação

O código deste artigo foi testado com a versão 1.0.8 do SDK do Azure Machine Learning.Code in this article was tested with Azure Machine Learning SDK version 1.0.8.

Pré-requisitosPrerequisites

Vá para Definir o ambiente de desenvolvimento para ler as etapas de notebook.Skip to Set the development environment to read through the notebook steps.

Para executar o notebook, primeiro conclua o treinamento de modelo no Tutorial (parte 1): Treinar um modelo de classificação de imagem com o serviço do Azure Machine Learning.To run the notebook, first complete the model training in Tutorial (part 1): Train an image classification model with Azure Machine Learning service. Em seguida, execute o notebook tutorials/img-classification-part2-deploy.ipynb usando o mesmo servidor do notebook.Then run the tutorials/img-classification-part2-deploy.ipynb notebook using the same notebook server.

Configurar o ambienteSet up the environment

Inicie configurando um ambiente de teste.Start by setting up a testing environment.

Importar pacotesImport packages

Importe os pacotes do Python necessários para este tutorial:Import the Python packages needed for this tutorial:

%matplotlib inline
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
 
import azureml
from azureml.core import Workspace, Run

# display the core SDK version number
print("Azure ML SDK Version: ", azureml.core.VERSION)

Recuperar o modeloRetrieve the model

Você registrou um modelo no workspace no tutorial anterior.You registered a model in your workspace in the previous tutorial. Agora, carregue esse workspace e baixe o modelo para seu diretório local:Now load this workspace and download the model to your local directory:

from azureml.core import Workspace
from azureml.core.model import Model
import os 
ws = Workspace.from_config()
model=Model(ws, 'sklearn_mnist')

model.download(target_dir=os.getcwd(), exist_ok=True)

# verify the downloaded model file
file_path = os.path.join(os.getcwd(), "sklearn_mnist_model.pkl")

os.stat(file_path)

Testar o modelo localmenteTest the model locally

Antes de implantar, verifique se seu modelo está operando localmente:Before you deploy, make sure your model is working locally:

  • Dados do teste de carga.Load test data.
  • Preveja os dados de teste.Predict test data.
  • Examine a matriz de confusão.Examine the confusion matrix.

Carregar dados de testeLoad test data

Carregue os dados de teste do diretório ./data/ criado durante o tutorial de treinamento:Load the test data from the ./data/ directory created during the training tutorial:

from utils import load_data
import os

data_folder = os.path.join(os.getcwd(), 'data')
# note we also shrink the intensity values (X) from 0-255 to 0-1. This helps the neural network converge faster
X_test = load_data(os.path.join(data_folder, 'test-images.gz'), False) / 255.0
y_test = load_data(os.path.join(data_folder, 'test-labels.gz'), True).reshape(-1)

Prever dados de testePredict test data

Para obter previsões, forneça o conjunto de dados de teste ao modelo:To get predictions, feed the test dataset to the model:

import pickle
from sklearn.externals import joblib

clf = joblib.load( os.path.join(os.getcwd(), 'sklearn_mnist_model.pkl'))
y_hat = clf.predict(X_test)

Examine a matriz de confusãoExamine the confusion matrix

Gere uma matriz de confusão para ver quantas amostras do conjunto de testes são classificadas corretamente.Generate a confusion matrix to see how many samples from the test set are classified correctly. Observe o valor classificado incorretamente para as previsões incorretas:Notice the misclassified value for the incorrect predictions:

from sklearn.metrics import confusion_matrix

conf_mx = confusion_matrix(y_test, y_hat)
print(conf_mx)
print('Overall accuracy:', np.average(y_hat == y_test))

A saída mostra a matriz de confusão:The output shows the confusion matrix:

[[ 960    0    1    2    1    5    6    3    1    1]
 [   0 1112    3    1    0    1    5    1   12    0]
 [   9    8  920   20   10    4   10   11   37    3]
 [   4    0   17  921    2   21    4   12   20    9]
 [   1    2    5    3  915    0   10    2    6   38]
 [  10    2    0   41   10  770   17    7   28    7]
 [   9    3    7    2    6   20  907    1    3    0]
 [   2    7   22    5    8    1    1  950    5   27]
 [  10   15    5   21   15   27    7   11  851   12]
 [   7    8    2   13   32   13    0   24   12  898]]
Overall accuracy: 0.9204

Use matplotlib para exibir a matriz de confusão como um grafo.Use matplotlib to display the confusion matrix as a graph. Neste gráfico, o eixo x mostra os valores reais e o eixo y mostra os valores previstos.In this graph, the x-axis shows the actual values, and the y-axis shows the predicted values. A cor de cada grade mostra a taxa de erro.The color in each grid shows the error rate. Quanto mais clara a cor, maior é a taxa de erro.The lighter the color, the higher the error rate is. Por exemplo, muitos 5's são classificados incorretamente como 3'.For example, many 5's are misclassified as 3's. Assim, você vê uma grade brilhante em (5,3):So you see a bright grid at (5,3):

# normalize the diagonal cells so that they don't overpower the rest of the cells when visualized
row_sums = conf_mx.sum(axis=1, keepdims=True)
norm_conf_mx = conf_mx / row_sums
np.fill_diagonal(norm_conf_mx, 0)

fig = plt.figure(figsize=(8,5))
ax = fig.add_subplot(111)
cax = ax.matshow(norm_conf_mx, cmap=plt.cm.bone)
ticks = np.arange(0, 10, 1)
ax.set_xticks(ticks)
ax.set_yticks(ticks)
ax.set_xticklabels(ticks)
ax.set_yticklabels(ticks)
fig.colorbar(cax)
plt.ylabel('true labels', fontsize=14)
plt.xlabel('predicted values', fontsize=14)
plt.savefig('conf.png')
plt.show()

Matriz de confusão de exibição de gráfico

Implantar como um serviço WebDeploy as a web service

Depois de testar o modelo e ficar satisfeito com os resultados, implante o modelo como um serviço Web hospedado nas Instâncias de Contêiner.After you tested the model and you're satisfied with the results, deploy the model as a web service hosted in Container Instances.

Para compilar o ambiente correto para Instâncias de Contêiner, forneça os seguintes componentes:To build the correct environment for Container Instances, provide the following components:

  • Um script de pontuação para mostrar como usar o modelo.A scoring script to show how to use the model.
  • Um arquivo de ambiente para mostrar quais pacotes precisam ser instalados.An environment file to show what packages need to be installed.
  • Um arquivo de configuração para criar a instância de contêiner.A configuration file to build the container instance.
  • O modelo treinado anteriormente.The model you trained previously.

Criar script de pontuaçãoCreate scoring script

Crie o script de pontuação, chamado score.py.Create the scoring script, called score.py. A chamada de serviço Web utiliza esse script para mostrar como usar o modelo.The web service call uses this script to show how to use the model.

Inclua estas duas funções necessárias no script de pontuação:Include these two required functions in the scoring script:

  • A função init(), que normalmente carrega o modelo em um objeto global.The init() function, which typically loads the model into a global object. Essa função é executada apenas uma vez quando o contêiner do Docker é iniciado.This function is run only once when the Docker container is started.

  • A função run(input_data) usa o modelo para prever um valor com base nos dados de entrada.The run(input_data) function uses the model to predict a value based on the input data. Entradas e saídas para a execução normalmente usam JSON para serialização e desserialização, mas outros formatos têm suporte.Inputs and outputs to the run typically use JSON for serialization and de-serialization, but other formats are supported.

%%writefile score.py
import json
import numpy as np
import os
import pickle
from sklearn.externals import joblib
from sklearn.linear_model import LogisticRegression

from azureml.core.model import Model

def init():
    global model
    # retrieve the path to the model file using the model name
    model_path = Model.get_model_path('sklearn_mnist')
    model = joblib.load(model_path)

def run(raw_data):
    data = np.array(json.loads(raw_data)['data'])
    # make prediction
    y_hat = model.predict(data)
    # you can return any data type as long as it is JSON-serializable
    return y_hat.tolist()

Criar arquivo de ambienteCreate environment file

Em seguida, crie um arquivo de ambiente, chamado myenv.yml, que especifica todas as dependências de pacote do script.Next create an environment file, called myenv.yml, that specifies all of the script's package dependencies. Este arquivo é usado para assegurar que todas essas dependências sejam instaladas na imagem do Docker.This file is used to make sure that all of those dependencies are installed in the Docker image. Este modelo precisa de scikit-learn e azureml-sdk:This model needs scikit-learn and azureml-sdk:

from azureml.core.conda_dependencies import CondaDependencies 

myenv = CondaDependencies()
myenv.add_conda_package("scikit-learn")

with open("myenv.yml","w") as f:
    f.write(myenv.serialize_to_string())

Examine o conteúdo do arquivo myenv.yml:Review the content of the myenv.yml file:

with open("myenv.yml","r") as f:
    print(f.read())

Criar um arquivo de configuraçãoCreate a configuration file

Crie um arquivo de configuração de implantação.Create a deployment configuration file. Especifique o número de CPUs e gigabytes de RAM necessários para seu contêiner de Instâncias de Contêiner.Specify the number of CPUs and gigabytes of RAM needed for your Container Instances container. Embora dependa do modelo, o padrão de um núcleo e 1 gigabyte de RAM é suficiente para muitos modelos.Although it depends on your model, the default of one core and 1 gigabyte of RAM is sufficient for many models. Se você precisar de mais posteriormente, precisará recriar a imagem e reimplantar o serviço.If you need more later, you have to re-create the image and redeploy the service.

from azureml.core.webservice import AciWebservice

aciconfig = AciWebservice.deploy_configuration(cpu_cores=1, 
                                               memory_gb=1, 
                                               tags={"data": "MNIST",  "method" : "sklearn"}, 
                                               description='Predict MNIST with sklearn')

Implantar em Instâncias de ContêinerDeploy in Container Instances

O tempo estimado para concluir a implantação é de cerca de sete a oito minutos.The estimated time to finish deployment is about seven to eight minutes.

Configure a imagem e implante.Configure the image and deploy. O código a seguir passa por estas etapas:The following code goes through these steps:

  1. Crie uma imagem usando estes arquivos:Build an image by using these files:
    • O arquivo de pontuação, score.py.The scoring file, score.py.
    • O arquivo de ambiente, myenv.yml.The environment file, myenv.yml.
    • o arquivo de modelo.The model file.
  2. Registre a imagem no workspace.Register the image under the workspace.
  3. Envie a imagem para o contêiner das Instâncias de Contêiner.Send the image to the Container Instances container.
  4. Inicie um contêiner em Instâncias de Contêiner usando a imagem.Start up a container in Container Instances by using the image.
  5. Obtenha o terminal HTTP do serviço Web.Get the web service HTTP endpoint.
%%time
from azureml.core.webservice import Webservice
from azureml.core.image import ContainerImage

# configure the image
image_config = ContainerImage.image_configuration(execution_script="score.py", 
                                                  runtime="python", 
                                                  conda_file="myenv.yml")

service = Webservice.deploy_from_model(workspace=ws,
                                       name='sklearn-mnist-svc',
                                       deployment_config=aciconfig,
                                       models=[model],
                                       image_config=image_config)

service.wait_for_deployment(show_output=True)

Obtenha o ponto de extremidade HTTP do serviço Web de pontuação, que aceita chamadas do cliente REST.Get the scoring web service's HTTP endpoint, which accepts REST client calls. Você pode compartilhar esse ponto de extremidade com qualquer pessoa que queira testar o serviço Web ou integrá-lo a um aplicativo:You can share this endpoint with anyone who wants to test the web service or integrate it into an application:

print(service.scoring_uri)

Testar o serviço implantadoTest the deployed service

Anteriormente, você marcou todos os dados de teste com a versão local do modelo.Earlier, you scored all the test data with the local version of the model. Agora, você pode testar o modelo implantado com uma amostra aleatória de 30 imagens dos dados de teste.Now you can test the deployed model with a random sample of 30 images from the test data.

O código a seguir passa por estas etapas:The following code goes through these steps:

  1. Envie os dados como uma matriz JSON para o serviço Web hospedado nas Instâncias de Contêiner.Send the data as a JSON array to the web service hosted in Container Instances.

  2. Use a API run do SDK para invocar o serviço.Use the SDK's run API to invoke the service. Também é possível fazer chamadas brutas usando qualquer ferramenta HTTP, como curl.You can also make raw calls by using any HTTP tool such as curl.

  3. Imprima as previsões retornadas e plote-as junto com as imagens de entrada.Print the returned predictions and plot them along with the input images. A fonte vermelha e a imagem inversa, branco sobre preto, são usadas para realçar as amostras classificadas incorretamente.Red font and inverse image, white on black, is used to highlight the misclassified samples.

Uma vez que a precisão do modelo é alta, talvez seja necessário executar o código a seguir algumas vezes, antes de poder ver uma amostra classificada incorretamente:Because the model accuracy is high, you might have to run the following code a few times before you can see a misclassified sample:

import json

# find 30 random samples from test set
n = 30
sample_indices = np.random.permutation(X_test.shape[0])[0:n]

test_samples = json.dumps({"data": X_test[sample_indices].tolist()})
test_samples = bytes(test_samples, encoding='utf8')

# predict using the deployed model
result = service.run(input_data=test_samples)

# compare actual value vs. the predicted values:
i = 0
plt.figure(figsize = (20, 1))

for s in sample_indices:
    plt.subplot(1, n, i + 1)
    plt.axhline('')
    plt.axvline('')
    
    # use different color for misclassified sample
    font_color = 'red' if y_test[s] != result[i] else 'black'
    clr_map = plt.cm.gray if y_test[s] != result[i] else plt.cm.Greys
    
    plt.text(x=10, y =-10, s=result[i], fontsize=18, color=font_color)
    plt.imshow(X_test[s].reshape(28, 28), cmap=clr_map)
    
    i = i + 1
plt.show()

Esse resultado é de uma amostra aleatória das imagens de teste:This result is from one random sample of test images:

Gráfico mostrando resultados

Também é possível enviar uma solicitação HTTP bruta para testar o serviço Web:You can also send a raw HTTP request to test the web service:

import requests

# send a random row from the test set to score
random_index = np.random.randint(0, len(X_test)-1)
input_data = "{\"data\": [" + str(list(X_test[random_index])) + "]}"

headers = {'Content-Type':'application/json'}

# for AKS deployment you'd need to the service key in the header as well
# api_key = service.get_key()
# headers = {'Content-Type':'application/json',  'Authorization':('Bearer '+ api_key)} 

resp = requests.post(service.scoring_uri, input_data, headers=headers)

print("POST to url", service.scoring_uri)
#print("input data:", input_data)
print("label:", y_test[random_index])
print("prediction:", resp.text)

Limpar recursosClean up resources

Para manter o grupo de recursos e o workspace para outros tutoriais e exploração, você pode excluir apenas a implantação das Instâncias de Contêiner usando esta chamada à API:To keep the resource group and workspace for other tutorials and exploration, you can delete only the Container Instances deployment by using this API call:

service.delete()

Importante

Os recursos que você criou podem ser usados como pré-requisitos em outros tutoriais e artigos de instruções do Serviço do Azure Machine Learning.The resources you created can be used as prerequisites to other Azure Machine Learning service tutorials and how-to articles.

Se você não pretende usar os recursos criados, exclua-os para não gerar encargos:If you don't plan to use the resources you created, delete them, so you don't incur any charges:

  1. No portal do Azure, selecione Grupos de recursos no canto esquerdo.In the Azure portal, select Resource groups on the far left.

    Exclusão no portal do Azure

  2. Selecione o grupo de recursos criado na lista.From the list, select the resource group you created.

  3. Selecione Excluir grupo de recursos.Select Delete resource group.

  4. Insira o nome do grupo de recursos.Enter the resource group name. Em seguida, selecione Excluir.Then select Delete.

Próximas etapasNext steps