Resolver problemas nos pipelines de aprendizagem automática
APLICA-SE A:SDK python azureml v1
Neste artigo, vai aprender a resolver problemas quando obtém erros ao executar um pipeline de machine learning no SDK do Azure Machine Learning e no estruturador do Azure Machine Learning.
Sugestões de resolução de problemas
A tabela seguinte apresenta problemas comuns durante o desenvolvimento de pipelines, com soluções possíveis.
Problema | Solução possível |
---|---|
Não é possível transmitir dados para o diretório PipelineData |
Verifique se criou um diretório no script correspondente ao local onde o pipeline aguarda os dados de saída do passo. Na maioria dos casos, um argumento de entrada define o diretório de saída e, em seguida, cria o diretório explicitamente. Utilize os.makedirs(args.output_dir, exist_ok=True) para criar o diretório de saída. Veja o tutorial para obter um exemplo de script de classificação que mostra este padrão de design. |
Erros de dependência | Se vir erros de dependência no pipeline remoto que não ocorria durante o teste local, confirme se as dependências e versões do ambiente remoto correspondem às do seu ambiente de teste. (Veja Criação, colocação em cache e reutilização do ambiente |
Erros ambíguos com destinos de computação | Tente eliminar e recriar os destinos de computação. A recriação de destinos de computação é rápida e pode resolver alguns problemas transitórios. |
O pipeline não está a reutilizar os passos | A reutilização de passos está ativada por predefinição, mas garanta que não a desativou num passo do pipeline. Se a reutilização estiver desativada, o allow_reuse parâmetro no passo está definido como False . |
O pipeline está a voltar a ser executado desnecessariamente | Para garantir que os passos só voltam a ser executados quando os dados ou scripts subjacentes forem alterados, desassocie os diretórios de código de origem de cada passo. Se utilizar o mesmo diretório de origem para vários passos, poderão ocorrer repetições desnecessárias. Utilize o source_directory parâmetro num objeto de passo do pipeline para apontar para o diretório isolado desse passo e certifique-se de que não está a utilizar o mesmo source_directory caminho para vários passos. |
Passo a abrandar ao longo das épocas da preparação ou outro comportamento em ciclo | Tente mudar as escritas de ficheiros, incluindo o registo, de as_mount() para as_upload() . O modo de montagem utiliza um sistema de ficheiros virtualizado remoto e carrega todo o ficheiro sempre que este é anexado. |
O destino de computação demora muito tempo a ser iniciado | As imagens do Docker para destinos de computação são carregadas do Azure Container Registry (ACR). Por predefinição, o Azure Machine Learning cria um ACR que utiliza o escalão de serviço básico . Mudar o ACR da área de trabalho para o escalão standard ou premium pode reduzir o tempo de criação e carregamento de imagens. Para obter mais informações, veja Escalões de serviço do Azure Container Registry (ACR). |
Erros de autenticação
Se executar uma operação de gestão num destino de computação a partir de uma tarefa remota, receberá um dos seguintes erros:
{"code":"Unauthorized","statusCode":401,"message":"Unauthorized","details":[{"code":"InvalidOrExpiredToken","message":"The request token was either invalid or expired. Please try again with a valid token."}]}
{"error":{"code":"AuthenticationFailed","message":"Authentication failed."}}
Por exemplo, receberá um erro se tentar criar ou anexar um destino de computação a partir de um Pipeline de ML submetido para execução remota.
Resolução de problemas ParallelRunStep
O script de um tem de ParallelRunStep
conter duas funções:
init()
: utilize esta função para qualquer preparação dispendiosa ou comum para inferência posterior. Por exemplo, utilize-o para carregar o modelo para um objeto global. Esta função é chamada apenas uma vez no início do processo.run(mini_batch)
: a função é executada para cadamini_batch
instância.mini_batch
:ParallelRunStep
invoca o método run e transmite uma lista ou pandasDataFrame
como um argumento para o método . Cada entrada no mini_batch é um caminho de ficheiro se a entrada for umFileDataset
ou um pandasDataFrame
se a entrada for umTabularDataset
.response
: o método run() deve devolver um pandasDataFrame
ou uma matriz. Por append_row output_action, estes elementos devolvidos são acrescentados ao ficheiro de saída comum. Por summary_only, os conteúdos dos elementos são ignorados. Para todas as ações de saída, cada elemento de saída devolvido indica uma execução bem-sucedida do elemento de entrada no mini-lote de entrada. Confirme que estão incluídos dados suficientes no resultado da execução para mapear a entrada para executar o resultado da saída. A saída de execução é escrita no ficheiro de saída e não é garantido que esteja por ordem. Deve utilizar alguma chave na saída para mapeá-la para entrada.
%%writefile digit_identification.py
# Snippets from a sample script.
# Refer to the accompanying digit_identification.py
# (https://github.com/Azure/MachineLearningNotebooks/tree/master/how-to-use-azureml/machine-learning-pipelines/parallel-run)
# for the implementation script.
import os
import numpy as np
import tensorflow as tf
from PIL import Image
from azureml.core import Model
def init():
global g_tf_sess
# Pull down the model from the workspace
model_path = Model.get_model_path("mnist")
# Construct a graph to execute
tf.reset_default_graph()
saver = tf.train.import_meta_graph(os.path.join(model_path, 'mnist-tf.model.meta'))
g_tf_sess = tf.Session()
saver.restore(g_tf_sess, os.path.join(model_path, 'mnist-tf.model'))
def run(mini_batch):
print(f'run method start: {__file__}, run({mini_batch})')
resultList = []
in_tensor = g_tf_sess.graph.get_tensor_by_name("network/X:0")
output = g_tf_sess.graph.get_tensor_by_name("network/output/MatMul:0")
for image in mini_batch:
# Prepare each image
data = Image.open(image)
np_im = np.array(data).reshape((1, 784))
# Perform inference
inference_result = output.eval(feed_dict={in_tensor: np_im}, session=g_tf_sess)
# Find the best probability, and add it to the result list
best_result = np.argmax(inference_result)
resultList.append("{}: {}".format(os.path.basename(image), best_result))
return resultList
Se tiver outro ficheiro ou pasta no mesmo diretório que o script de inferência, pode referenciá-lo ao localizar o diretório de trabalho atual.
script_dir = os.path.realpath(os.path.join(__file__, '..',))
file_path = os.path.join(script_dir, "<file_name>")
Parâmetros para ParallelRunConfig
ParallelRunConfig
é a configuração principal, por ParallelRunStep
exemplo, no pipeline do Azure Machine Learning. Utilize-o para encapsular o script e configurar os parâmetros necessários, incluindo todas as seguintes entradas:
entry_script
: um script de utilizador como um caminho de ficheiro local que é executado em paralelo em vários nós. Sesource_directory
estiver presente, utilize um caminho relativo. Caso contrário, utilize qualquer caminho acessível no computador.mini_batch_size
: o tamanho do mini-lote transmitido para uma únicarun()
chamada. (opcional; o valor predefinido é10
ficheiros paraFileDataset
e1MB
paraTabularDataset
.)- Para
FileDataset
, é o número de ficheiros com um valor mínimo de1
. Pode combinar múltiplos ficheiros num mini-lote. - Para
TabularDataset
, é o tamanho dos dados. Os valores de exemplo são1024
,1024KB
,10MB
e1GB
. O valor recomendado é1MB
. O mini-lote deTabularDataset
nunca irá ultrapassar os limites dos ficheiros. Por exemplo, se tiver .csv ficheiros com vários tamanhos, o ficheiro mais pequeno é de 100 KB e o maior é de 10 MB. Se definirmini_batch_size = 1MB
, os ficheiros com um tamanho inferior a 1 MB são tratados como um mini-lote. Os ficheiros com um tamanho superior a 1 MB são divididos em vários mini-lotes.
- Para
error_threshold
: o número de falhas de registo paraTabularDataset
e falhas de ficheiros paraFileDataset
o mesmo deve ser ignorado durante o processamento. Se a contagem de erros de toda a entrada for superior a este valor, a tarefa será abortada. O limiar de erro destina-se a toda a entrada e não ao mini-lote individual enviado para orun()
método . O intervalo é[-1, int.max]
. A-1
parte indica ignorar todas as falhas durante o processamento.output_action
: um dos seguintes valores indica como o resultado está organizado:summary_only
: o script de utilizador armazena a saída.ParallelRunStep
utiliza a saída apenas para o cálculo do limiar de erro.append_row
: para todas as entradas, só é criado um ficheiro na pasta de saída para acrescentar todas as saídas separadas por linha.
append_row_file_name
: para personalizar o nome do ficheiro de saída para append_row output_action (opcional; o valor predefinido éparallel_run_step.txt
).source_directory
: caminhos para pastas que contêm todos os ficheiros a executar no destino de computação (opcional).compute_target
: sóAmlCompute
é suportado.node_count
: o número de nós de computação a utilizar para executar o script de utilizador.process_count_per_node
: o número de processos por nó. A melhor prática é definir para o número de GPU ou CPU que um nó tem (opcional; o valor predefinido é1
).environment
: a definição de ambiente python. Pode configurá-lo para utilizar um ambiente Python existente ou para configurar um ambiente temporário. A definição também é responsável por definir as dependências de aplicação necessárias (opcional).logging_level
: verbosidade do registo. Os valores no aumento da verbosidade são:WARNING
,INFO
eDEBUG
. (opcional; o valor predefinido éINFO
)run_invocation_timeout
: orun()
tempo limite de invocação do método em segundos. (opcional; o valor predefinido é60
)run_max_try
: número máximo de tentativas derun()
para um mini-lote. Arun()
falha se for emitida uma exceção ou se não for devolvida nada quandorun_invocation_timeout
for atingido (opcional; o valor predefinido é3
).
Pode especificar mini_batch_size
, node_count
, process_count_per_node
, logging_level
, run_invocation_timeout
e run_max_try
como PipelineParameter
, para que, quando submeter novamente uma execução de pipeline, possa ajustar os valores dos parâmetros. Neste exemplo, utiliza PipelineParameter
e mini_batch_size
Process_count_per_node
altera estes valores quando submeter novamente uma execução mais tarde.
Parâmetros para criar o ParallelRunStep
Crie o ParallelRunStep com o script, a configuração do ambiente e os parâmetros. Especifique o destino de computação que já anexou à área de trabalho como o destino da execução do script de inferência. Utilize ParallelRunStep
para criar o passo do pipeline de inferência de lotes, que utiliza todos os seguintes parâmetros:
name
: o nome do passo, com as seguintes restrições de nomenclatura: exclusivo, 3-32 carateres e regex ^[a-z]([-a-z0-9]*[a-z0-9])?$.parallel_run_config
: umParallelRunConfig
objeto, conforme definido anteriormente.inputs
: um ou mais conjuntos de dados do Azure Machine Learning de tipo único a serem particionados para processamento paralelo.side_inputs
: Um ou mais dados de referência ou conjuntos de dados utilizados como entradas laterais sem necessidade de particionar.output
: umOutputFileDatasetConfig
objeto que corresponde ao diretório de saída.arguments
: uma lista de argumentos transmitidos ao script de utilizador. Utilize unknown_args para os obter no script de entrada (opcional).allow_reuse
: se o passo deve reutilizar os resultados anteriores quando executado com as mesmas definições/entradas. Se este parâmetro forFalse
, é gerada uma nova execução para este passo durante a execução do pipeline. (opcional; o valor predefinido éTrue
.)
from azureml.pipeline.steps import ParallelRunStep
parallelrun_step = ParallelRunStep(
name="predict-digits-mnist",
parallel_run_config=parallel_run_config,
inputs=[input_mnist_ds_consumption],
output=output_dir,
allow_reuse=True
)
Técnicas de depuração
Existem três técnicas principias para depurar pipelines:
- Depurar os passos de pipeline individuais no computador local
- Utilizar o registo e o Application Insights para isolar e diagnosticar a origem do problema
- Anexar um depurador remoto a um pipeline em execução no Azure
Depurar scripts localmente
Uma das falhas mais comuns num pipeline é que o script de domínio não é executado conforme pretendido ou contém erros de runtime no contexto de computação remota que são difíceis de depurar.
Os próprios pipelines não podem ser executados localmente. No entanto, executar os scripts isoladamente no computador local permite-lhe depurar mais rapidamente porque não tem de esperar pelo processo de compilação de ambiente e computação. É necessário algum trabalho de desenvolvimento para o fazer:
- Se os seus dados estiverem num arquivo de dados na cloud, terá de transferir dados e disponibilizá-lo para o script. Utilizar uma pequena amostra dos seus dados é uma boa forma de reduzir o runtime e obter rapidamente feedback sobre o comportamento do script
- Se estiver a tentar simular um passo de pipeline intermédio, poderá ter de criar manualmente os tipos de objeto que o script específico espera do passo anterior
- Tem de definir o seu próprio ambiente e replicar as dependências definidas no seu ambiente de computação remota
Assim que tiver uma configuração de script para ser executada no seu ambiente local, é mais fácil efetuar a depuração de tarefas como:
- Anexar uma configuração de depuração personalizada
- Colocar em pausa a execução e inspecionar o estado do objeto
- Captura de tipo ou erros lógicos que não serão expostos até ao runtime
Dica
Assim que puder verificar se o script está em execução conforme esperado, um bom passo seguinte é executar o script num pipeline de um único passo antes de tentar executá-lo num pipeline com vários passos.
Configurar, escrever e rever registos de pipelines
Testar scripts localmente é uma excelente forma de depurar fragmentos de código principais e lógica complexa antes de começar a criar um pipeline. A dada altura, tem de depurar scripts durante a execução real do pipeline, especialmente quando diagnosticar o comportamento que ocorre durante a interação entre os passos do pipeline. Recomendamos a utilização liberal de print()
instruções nos seus scripts de passo para que possa ver o estado do objeto e os valores esperados durante a execução remota, semelhante à forma como depuraria o código JavaScript.
Opções de registo e comportamento
A tabela seguinte fornece informações para diferentes opções de depuração para pipelines. Não é uma lista exaustiva, uma vez que existem outras opções para além das opções do Azure Machine Learning, Python e OpenCensus apresentadas aqui.
Biblioteca | Tipo | Exemplo | Destino | Recursos |
---|---|---|---|---|
Azure Machine Learning SDK | Metric | run.log(name, val) |
IU do Portal do Azure Machine Learning | Como monitorizar as experimentações azureml.core.Run class |
Registo/impressão Python | Registo | print(val) logging.info(message) |
Registos do controlador, estruturador do Azure Machine Learning | Como monitorizar as experimentações Registo Python |
OpenCensus Python | Registo | logger.addHandler(AzureLogHandler()) logging.log(message) |
Application Insights – rastreios | Depurar pipelines no Application Insights OpenCensus Azure Monitor Exporters (Exportadores do Azure Monitor do OpenCensus) Guia detalhado do registo Python |
Exemplo de opções de registo
import logging
from azureml.core.run import Run
from opencensus.ext.azure.log_exporter import AzureLogHandler
run = Run.get_context()
# Azure Machine Learning Scalar value logging
run.log("scalar_value", 0.95)
# Python print statement
print("I am a python print statement, I will be sent to the driver logs.")
# Initialize Python logger
logger = logging.getLogger(__name__)
logger.setLevel(args.log_level)
# Plain Python logging statements
logger.debug("I am a plain debug statement, I will be sent to the driver logs.")
logger.info("I am a plain info statement, I will be sent to the driver logs.")
handler = AzureLogHandler(connection_string='<connection string>')
logger.addHandler(handler)
# Python logging with OpenCensus AzureLogHandler
logger.warning("I am an OpenCensus warning statement, find me in Application Insights!")
logger.error("I am an OpenCensus error statement with custom dimensions", {'step_id': run.id})
Estruturador do Azure Machine Learning
Para pipelines criados no estruturador, pode encontrar o ficheiro 70_driver_log na página de criação ou na página de detalhes da execução do pipeline.
Ativar o registo para pontos finais em tempo real
Para resolver problemas e depurar pontos finais em tempo real no estruturador, tem de ativar o registo do Application Insight com o SDK. O registo permite-lhe resolver problemas de implementação e utilização de modelos de depuração. Para obter mais informações, veja Registo de modelos implementados.
Obter registos da página de criação
Quando submete uma execução de pipeline e permanece na página de criação, pode encontrar os ficheiros de registo gerados para cada componente à medida que cada componente termina a execução.
Selecione um componente que tenha terminado de ser executado na tela de criação.
No painel direito do componente, aceda ao separador Saídas + registos .
Expanda o painel direito e selecione o 70_driver_log.txt para ver o ficheiro no browser. Também pode transferir registos localmente.
Obter registos de execuções de pipelines
Também pode encontrar os ficheiros de registo para execuções específicas na página de detalhes da execução do pipeline, que pode ser encontrada na secção Pipelines ou Experiments do estúdio.
Selecione uma execução de pipeline criada no estruturador.
Selecione um componente no painel de pré-visualização.
No painel direito do componente, aceda ao separador Saídas + registos .
Expanda o painel direito para ver o ficheiro std_log.txt no browser ou selecione o ficheiro para transferir os registos localmente.
Importante
Para atualizar um pipeline a partir da página de detalhes da execução do pipeline, tem de clonar a execução do pipeline para um novo rascunho de pipeline. Uma execução de pipeline é um instantâneo do pipeline. É semelhante a um ficheiro de registo e não pode ser alterado.
Application Insights
Para obter mais informações sobre como utilizar a biblioteca Python do OpenCensus desta forma, veja este guia: Depurar e resolver problemas de pipelines de machine learning no Application Insights
Depuração interativa com o Visual Studio Code
Em determinados casos, poderá ter de depurar interativamente o código do Python utilizado no pipeline do ML. Ao utilizar o Visual Studio Code (VS Code) e debugpy, pode anexar ao código tal como é executado no ambiente de preparação. Para obter mais informações, veja a depuração interativa no guia do VS Code.
HyperdriveStep e AutoMLStep falham com isolamento de rede
Depois de utilizar HyperdriveStep e AutoMLStep, quando tentar registar o modelo, poderá receber um erro.
Está a utilizar o SDK do Azure Machine Learning v1.
A área de trabalho do Azure Machine Learning está configurada para isolamento de rede (VNet).
O pipeline tenta registar o modelo gerado pelo passo anterior. Por exemplo, no exemplo seguinte, o
inputs
parâmetro é o saved_model de um HyperdriveStep:register_model_step = PythonScriptStep(script_name='register_model.py', name="register_model_step01", inputs=[saved_model], compute_target=cpu_cluster, arguments=["--saved-model", saved_model], allow_reuse=True, runconfig=rcfg)
Solução
Importante
Este comportamento não ocorre ao utilizar o SDK do Azure Machine Learning v2.
Para contornar este erro, utilize a classe Executar para criar o modelo a partir do HyperdriveStep ou autoMLStep. Segue-se um script de exemplo que obtém o modelo de saída de um HyperdriveStep:
%%writefile $script_folder/model_download9.py
import argparse
from azureml.core import Run
from azureml.pipeline.core import PipelineRun
from azureml.core.experiment import Experiment
from azureml.train.hyperdrive import HyperDriveRun
from azureml.pipeline.steps import HyperDriveStepRun
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument(
'--hd_step_name',
type=str, dest='hd_step_name',
help='The name of the step that runs AutoML training within this pipeline')
args = parser.parse_args()
current_run = Run.get_context()
pipeline_run = PipelineRun(current_run.experiment, current_run.experiment.name)
hd_step_run = HyperDriveStepRun((pipeline_run.find_step_run(args.hd_step_name))[0])
hd_best_run = hd_step_run.get_best_run_by_primary_metric()
print(hd_best_run)
hd_best_run.download_file("outputs/model/saved_model.pb", "saved_model.pb")
print("Successfully downloaded model")
Em seguida, o ficheiro pode ser utilizado a partir de um PythonScriptStep:
from azureml.pipeline.steps import PythonScriptStep
conda_dep = CondaDependencies()
conda_dep.add_pip_package("azureml-sdk")
conda_dep.add_pip_package("azureml-pipeline")
rcfg = RunConfiguration(conda_dependencies=conda_dep)
model_download_step = PythonScriptStep(
name="Download Model 9",
script_name="model_download9.py",
arguments=["--hd_step_name", hd_step_name],
compute_target=compute_target,
source_directory=script_folder,
allow_reuse=False,
runconfig=rcfg
)
Passos seguintes
Para obter um tutorial completo com
ParallelRunStep
o , veja Tutorial: Criar um pipeline do Azure Machine Learning para classificação em lote.Para obter um exemplo completo que mostra a aprendizagem automática automatizada em pipelines de ML, veja Utilizar o ML automatizado num pipeline do Azure Machine Learning em Python.
Veja a referência do SDK para obter ajuda com o pacote azureml-pipelines-core e o pacote azureml-pipelines-steps .
Veja a lista de exceções e códigos de erro do estruturador.