Rozwiązywanie problemów z potokami uczenia maszynowego

DOTYCZY:Zestaw SDK języka Python w wersji 1

W tym artykule dowiesz się, jak rozwiązywać problemy po błędach podczas uruchamiania potoku uczenia maszynowego w zestawie SDK usługi Azure Machine Learning i projektancie usługi Azure Machine Learning.

Wskazówki dotyczące rozwiązywania problemów

W poniższej tabeli przedstawiono typowe problemy podczas tworzenia potoków oraz ich potencjalne rozwiązania.

Problem Możliwe rozwiązanie
Nie można przekazać danych do katalogu PipelineData Upewnij się, że utworzono katalog w skrypcie, który odpowiada miejscu, w którym potok oczekuje danych wyjściowych kroku. W większości przypadków argument wejściowy definiuje katalog wyjściowy, a następnie jawnie utworzysz katalog. Użyj polecenia os.makedirs(args.output_dir, exist_ok=True), aby utworzyć katalog wyjściowy. Zobacz samouczek, aby zapoznać się z przykładowym skryptem oceniania, który pokazuje ten wzorzec projektowy.
Błędy zależności Jeśli widzisz błędy zależności w potoku zdalnym, które nie wystąpiły podczas testowania lokalnego, potwierdź zależności i wersje środowiska zdalnego zgodne z tymi w środowisku testowym. (Zobacz Kompilowanie, buforowanie i ponowne używanie środowiska
Niejednoznaczne błędy dotyczące docelowych obiektów obliczeniowych Spróbuj usunąć i ponownie utworzyć docelowe obiekty obliczeniowe. Ponowne tworzenie docelowych obiektów obliczeniowych trwa krótko i może rozwiązać niektóre przejściowe problemy.
Potok nie używa ponownie kroków Ponowne używanie kroków jest domyślnie włączone, ale upewnij się, że nie zostało wyłączone w kroku potoku. Jeśli ponowne użycie jest wyłączone, allow_reuse parametr w kroku jest ustawiony na Falsewartość .
Potok jest niepotrzebnie ponownie uruchamiany Aby się upewnić, że kroki są ponownie uruchamiane tylko wtedy, gdy zmienią się ich dane lub skrypty źródłowe, należy oddzielić katalogi kodu źródłowego dla każdego kroku. Jeśli używasz tego samego katalogu źródłowego dla wielu kroków, mogą wystąpić niepotrzebne ponowne uruchomienia. Użyj parametru source_directory w obiekcie kroku potoku, aby wskazać izolowany katalog dla tego kroku i upewnij się, że nie używasz tej samej source_directory ścieżki dla wielu kroków.
Krok spowalnia w kolejnych epokach trenowania lub podczas innego zachowania w pętli Spróbuj przełączyć wszystkie zapisy plików, w tym rejestrowanie, z trybu as_mount() na tryb as_upload(). Tryb instalacji używa zdalnego zwirtualizowanego systemu plików i przekazuje cały plik za każdym razem, gdy następuje dołączenie do niego.
Uruchamianie docelowego obiektu obliczeniowego trwa długo Obrazy platformy Docker dla docelowych obiektów obliczeniowych są ładowane z usługi Azure Container Registry (ACR). Domyślnie usługa Azure Machine Learning tworzy usługę ACR korzystającą z podstawowej warstwy usług. Zmiana usługi ACR dla obszaru roboczego na warstwę Standardowa lub Premium może skrócić czas kompilowania i ładowania obrazów. Aby uzyskać więcej informacji, zobacz Warstwy usługi Azure Container Registry.

Błędy uwierzytelniania

Jeśli wykonujesz operację zarządzania na docelowym obiekcie obliczeniowym z zadania zdalnego, zostanie wyświetlony jeden z następujących błędów:

{"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."}}

Na przykład występuje błąd podczas próby utworzenia lub dołączenia docelowego obiektu obliczeniowego z potoku uczenia maszynowego przesłanego do zdalnego wykonywania.

Rozwiązywanie problemów ParallelRunStep

Skrypt elementu ParallelRunStepmusi zawierać dwie funkcje:

  • init(): użyj tej funkcji w przypadku kosztownych lub typowych przygotowań do późniejszego wnioskowania. Na przykład użyj go do załadowania modelu do obiektu globalnego. Ta funkcja jest wywoływana tylko raz na początku procesu.
  • run(mini_batch): Funkcja jest uruchamiana dla każdego mini_batch wystąpienia.
    • mini_batch: ParallelRunStep wywołuje metodę run i przekazuje listę lub bibliotekę pandas DataFrame jako argument do metody. Każdy wpis w mini_batch jest ścieżką pliku, jeśli dane wejściowe to biblioteka FileDataset pandas DataFrame lub, jeśli dane wejściowe to TabularDataset.
    • response: metoda run() powinna zwrócić bibliotekę pandas DataFrame lub tablicę. W przypadku append_row output_action te zwrócone elementy są dołączane do wspólnego pliku wyjściowego. W przypadku summary_only zawartość elementów jest ignorowana. Dla wszystkich akcji wyjściowych każdy zwrócony element wyjściowy wskazuje jeden pomyślny przebieg elementu wejściowego w minisadowej partii wejściowej. Upewnij się, że w wyniku uruchomienia znajduje się wystarczająca ilość danych, aby zamapować dane wejściowe w celu uruchomienia wyniku wyjściowego. Uruchamianie danych wyjściowych jest zapisywane w pliku wyjściowym i nie ma gwarancji, że należy użyć klucza w danych wyjściowych, aby zamapować je na dane wejściowe.
%%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

Jeśli masz inny plik lub folder w tym samym katalogu co skrypt wnioskowania, możesz go odwołać, wyszukując bieżący katalog roboczy.

script_dir = os.path.realpath(os.path.join(__file__, '..',))
file_path = os.path.join(script_dir, "<file_name>")

Parametry elementu ParallelRunConfig

ParallelRunConfig jest główną konfiguracją wystąpienia ParallelRunStep w potoku usługi Azure Machine Learning. Służy do zawijania skryptu i konfigurowania niezbędnych parametrów, w tym wszystkich następujących wpisów:

  • entry_script: Skrypt użytkownika jako lokalna ścieżka pliku, która jest uruchamiana równolegle w wielu węzłach. Jeśli source_directory jest obecny, użyj ścieżki względnej. W przeciwnym razie użyj dowolnej ścieżki dostępnej na maszynie.
  • mini_batch_size: rozmiar mini-partii przekazany do pojedynczego run() wywołania. (opcjonalnie; wartość domyślna to 10 pliki i FileDataset1MB dla TabularDataset.)
    • W przypadku FileDatasetprogramu jest to liczba plików o minimalnej wartości 1. Można połączyć wiele plików w jedną minisadę.
    • W przypadku TabularDatasetelementu jest to rozmiar danych. Przykładowe wartości to 1024, 1024KB, 10MBi 1GB. Zalecana wartość to 1MB. Mini-batch z TabularDataset nigdy nie przekroczy granic plików. Jeśli na przykład masz .csv plików o różnych rozmiarach, najmniejszy plik to 100 KB, a największy to 10 MB. W przypadku ustawienia mini_batch_size = 1MBparametru pliki o rozmiarze mniejszym niż 1 MB są traktowane jako jedna minisadowa. Pliki o rozmiarze większym niż 1 MB są podzielone na wiele minisadów.
  • error_threshold: liczba błędów rekordów dla TabularDataset błędów i plików, FileDataset które powinny być ignorowane podczas przetwarzania. Jeśli liczba błędów dla całego danych wejściowych przekroczy tę wartość, zadanie zostanie przerwane. Próg błędu dotyczy całego danych wejściowych, a nie pojedynczej minisadowej wysłanej run() do metody. Zakres to [-1, int.max]. Część -1 wskazuje na ignorowanie wszystkich błędów podczas przetwarzania.
  • output_action: Jedna z następujących wartości wskazuje sposób organizowania danych wyjściowych:
    • summary_only: skrypt użytkownika przechowuje dane wyjściowe. ParallelRunStep używa danych wyjściowych tylko dla obliczenia progu błędu.
    • append_row: dla wszystkich danych wejściowych w folderze wyjściowym jest tworzony tylko jeden plik, aby dołączyć wszystkie dane wyjściowe oddzielone wierszem.
  • append_row_file_name: Aby dostosować nazwę pliku wyjściowego dla append_row output_action (opcjonalnie; wartość domyślna to parallel_run_step.txt).
  • source_directory: ścieżki do folderów zawierających wszystkie pliki do wykonania w obiekcie docelowym obliczeniowym (opcjonalnie).
  • compute_target: obsługiwane jest tylko AmlCompute .
  • node_count: liczba węzłów obliczeniowych, które mają być używane do uruchamiania skryptu użytkownika.
  • process_count_per_node: liczba procesów na węzeł. Najlepszym rozwiązaniem jest ustawienie liczby procesorów GPU lub procesora CPU z jednym węzłem (opcjonalnie; wartość domyślna to 1).
  • environment: Definicja środowiska języka Python. Można ją skonfigurować tak, aby korzystała z istniejącego środowiska języka Python lub skonfigurować środowisko tymczasowe. Definicja jest również odpowiedzialna za ustawianie wymaganych zależności aplikacji (opcjonalnie).
  • logging_level: Czasownik dziennika. Wartości rosnącej szczegółowości to: WARNING, INFOi DEBUG. (opcjonalnie; wartość domyślna to INFO)
  • run_invocation_timeoutrun(): limit czasu wywołania metody w sekundach. (opcjonalnie; wartość domyślna to 60)
  • run_max_try: maksymalna liczba run() prób dla mini-partii. Wartość a run() nie powiedzie się, jeśli zostanie zgłoszony wyjątek lub nie zostanie zwrócony nic po run_invocation_timeout osiągnięciu (opcjonalnie; wartość domyślna to 3).

Można określić mini_batch_size, , node_count, process_count_per_node, logging_level, run_invocation_timeouti run_max_try jako PipelineParameter, aby po ponownym przesłaniu uruchomienia potoku można dostosować wartości parametrów. W tym przykładzie użyto PipelineParametermini_batch_size elementu i Process_count_per_node zmienisz te wartości podczas ponownego ponownego uruchomienia później.

Parametry tworzenia elementu ParallelRunStep

Utwórz element ParallelRunStep przy użyciu skryptu, konfiguracji środowiska i parametrów. Określ docelowy obiekt obliczeniowy, który został już dołączony do obszaru roboczego jako element docelowy wykonywania dla skryptu wnioskowania. Użyj ParallelRunStep polecenia , aby utworzyć krok potoku wnioskowania wsadowego, który przyjmuje wszystkie następujące parametry:

  • name: Nazwa kroku z następującymi ograniczeniami nazewnictwa: unikatowe, 3–32 znaki i regex ^[a-z]([-a-z0-9]*[a-z0-9])?$.
  • parallel_run_configParallelRunConfig: obiekt zdefiniowany wcześniej.
  • inputs: Co najmniej jeden zestaw danych usługi Azure Machine Learning, który ma być podzielony na partycje na potrzeby przetwarzania równoległego.
  • side_inputs: Co najmniej jedno dane referencyjne lub zestawy danych używane jako dane wejściowe po stronie bez konieczności partycjonowania.
  • outputOutputFileDatasetConfig: obiekt odpowiadający katalogowi wyjściowemu.
  • arguments: lista argumentów przekazanych do skryptu użytkownika. Użyj unknown_args, aby pobrać je w skrypcie wpisu (opcjonalnie).
  • allow_reuse: czy krok powinien ponownie używać poprzednich wyników podczas uruchamiania z tymi samymi ustawieniami/danymi wejściowymi. Jeśli ten parametr to False, zostanie wygenerowany nowy przebieg dla tego kroku podczas wykonywania potoku. (opcjonalnie; wartość domyślna to 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
)

Techniki debugowania

Istnieją trzy główne techniki debugowania potoków

  • Debugowanie poszczególnych kroków potoku na komputerze lokalnym
  • Korzystanie z rejestrowania i usługi Application Insights w celu izolowania i diagnozowania źródła problemu
  • Dołącz zdalny debuger do potoku uruchomionego na platformie Azure

Lokalne debugowanie skryptów

Jednym z najczęstszych błędów w potoku jest to, że skrypt domeny nie działa zgodnie z oczekiwaniami lub zawiera błędy środowiska uruchomieniowego w zdalnym kontekście obliczeniowym, które są trudne do debugowania.

Same potoki nie mogą być uruchamiane lokalnie. Jednak uruchamianie skryptów w izolacji na komputerze lokalnym pozwala na szybsze debugowanie, ponieważ nie trzeba czekać na proces kompilacji zasobów obliczeniowych i środowiska. Aby to zrobić, należy wykonać niektóre prace programistyczne:

  • Jeśli dane są w magazynie danych w chmurze, musisz pobrać dane i udostępnić je skryptowi. Użycie niewielkiej próbki danych jest dobrym sposobem na zmniejszenie środowiska uruchomieniowego i szybkie uzyskanie opinii na temat zachowania skryptu
  • Jeśli próbujesz zasymulować krok potoku pośredniego, może być konieczne ręczne skompilowanie typów obiektów, których oczekuje określony skrypt z poprzedniego kroku
  • Musisz zdefiniować własne środowisko i replikować zależności zdefiniowane w zdalnym środowisku obliczeniowym

Po skonfigurowaniu skryptu do uruchomienia w środowisku lokalnym łatwiej jest wykonywać zadania debugowania, takie jak:

  • Dołączanie niestandardowej konfiguracji debugowania
  • Wstrzymując wykonywanie i inspekcję stanu obiektu
  • Przechwytywanie typów lub błędów logicznych, które nie zostaną ujawnione do czasu wykonania

Porada

Po sprawdzeniu, czy skrypt działa zgodnie z oczekiwaniami, dobrym następnym krokiem jest uruchomienie skryptu w potoku jednoetapowym przed podjęciem próby uruchomienia go w potoku z wieloma krokami.

Konfigurowanie, zapisywanie i przeglądanie dzienników potoków

Lokalne testowanie skryptów to doskonały sposób debugowania głównych fragmentów kodu i złożonej logiki przed rozpoczęciem tworzenia potoku. W pewnym momencie należy debugować skrypty podczas rzeczywistego uruchomienia potoku, szczególnie w przypadku diagnozowania zachowania występującego podczas interakcji między krokami potoku. Zalecamy liberalne użycie instrukcji print() w skryptach kroków, aby można było zobaczyć stan obiektu i oczekiwane wartości podczas zdalnego wykonywania, podobnie jak w przypadku debugowania kodu JavaScript.

Opcje rejestrowania i zachowanie

Poniższa tabela zawiera informacje dotyczące różnych opcji debugowania potoków. Nie jest to wyczerpująca lista, ponieważ istnieją inne opcje oprócz tylko usług Azure Machine Learning, Python i OpenCensus pokazanych tutaj.

Biblioteka Typ Przykład Element docelowy Zasoby
Azure Machine Learning SDK Metric run.log(name, val) Interfejs użytkownika portalu usługi Azure Machine Learning Jak śledzić eksperymenty
Klasa azureml.core.Run
Drukowanie/logowanie w języku Python Dziennik print(val)
logging.info(message)
Dzienniki sterowników, projektant usługi Azure Machine Learning Jak śledzić eksperymenty

Rejestrowanie w języku Python
Zestaw OpenCensus Python Dziennik logger.addHandler(AzureLogHandler())
logging.log(message)
Application Insights — ślady Debugowanie potoków w usłudze Application Insights

Eksporterzy biblioteki OpenCensus usługi Azure Monitor
Podręcznik rejestrowania w języku Python

Przykład opcji rejestrowania

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})

Projektant usługi Azure Machine Learning

W przypadku potoków utworzonych w projektancie można znaleźć plik 70_driver_log na stronie tworzenia lub na stronie szczegółów przebiegu potoku.

Włączanie rejestrowania dla punktów końcowych w czasie rzeczywistym

Aby rozwiązywać problemy i debugować punkty końcowe w czasie rzeczywistym w projektancie, należy włączyć rejestrowanie usługi Application Insights przy użyciu zestawu SDK. Rejestrowanie umożliwia rozwiązywanie i debugowanie problemów z wdrażaniem i użyciem modelu. Aby uzyskać więcej informacji, zobacz Rejestrowanie dla wdrożonych modeli.

Pobieranie dzienników ze strony tworzenia

Po przesłaniu uruchomienia potoku i pozostaniu na stronie tworzenia można znaleźć pliki dziennika wygenerowane dla każdego składnika, gdy każdy składnik zakończy działanie.

  1. Wybierz składnik, który zakończył działanie na kanwie tworzenia.

  2. W prawym okienku składnika przejdź do karty Dane wyjściowe i dzienniki .

  3. Rozwiń okienko po prawej stronie i wybierz 70_driver_log.txt , aby wyświetlić plik w przeglądarce. Dzienniki można również pobierać lokalnie.

    Rozwinięte okienko danych wyjściowych w projektancie

Pobieranie dzienników z przebiegów potoku

Pliki dziennika dla określonych przebiegów można również znaleźć na stronie szczegółów przebiegu potoku, która znajduje się w sekcji Potoki lub Eksperymenty w studio.

  1. Wybierz przebieg potoku utworzony w projektancie.

    Strona przebiegu potoku

  2. Wybierz składnik w okienku podglądu.

  3. W prawym okienku składnika przejdź do karty Dane wyjściowe i dzienniki .

  4. Rozwiń okienko po prawej stronie, aby wyświetlić plik std_log.txt w przeglądarce lub wybierz plik, aby pobrać dzienniki lokalnie.

Ważne

Aby zaktualizować potok ze strony szczegółów przebiegu potoku, należy sklonować przebieg potoku do nowej wersji roboczej potoku. Uruchomienie potoku to migawka potoku. Jest on podobny do pliku dziennika i nie można go zmienić.

Application Insights

Aby uzyskać więcej informacji na temat korzystania z biblioteki OpenCensus języka Python w ten sposób, zobacz ten przewodnik: Debugowanie i rozwiązywanie problemów z potokami uczenia maszynowego w usłudze Application Insights

Debugowanie interakcyjne za pomocą programu Visual Studio Code

W niektórych przypadkach może być konieczne interaktywne debugowanie kodu języka Python użytego w potoku usługi ML. Za pomocą programu Visual Studio Code (VS Code) i narzędzia debugpy można dołączać do kodu podczas jego działania w środowisku trenowania. Aby uzyskać więcej informacji, odwiedź przewodnik interaktywnego debugowania w programie VS Code.

Funkcja HyperdriveStep i AutoMLStep kończą się niepowodzeniem z izolacją sieci

Po użyciu funkcji HyperdriveStep i AutoMLStep podczas próby zarejestrowania modelu może wystąpić błąd.

  • Używasz zestawu Azure Machine Learning SDK w wersji 1.

  • Obszar roboczy usługi Azure Machine Learning jest skonfigurowany do izolacji sieci (VNet).

  • Potok próbuje zarejestrować model wygenerowany przez poprzedni krok. Na przykład w poniższym przykładzie inputs parametr jest saved_model z funkcji 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)
    

Obejście

Ważne

To zachowanie nie występuje w przypadku korzystania z zestawu Azure Machine Learning SDK w wersji 2.

Aby obejść ten błąd, użyj klasy Run , aby uzyskać model utworzony na podstawie funkcji HyperdriveStep lub AutoMLStep. Poniżej przedstawiono przykładowy skrypt, który pobiera model wyjściowy z funkcji 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") 

Następnie można użyć pliku z poziomu pliku 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
)

Następne kroki