Wyświetlanie kodu szkoleniowego dla modelu zautomatyzowanego uczenia maszynowego

Z tego artykułu dowiesz się, jak wyświetlić wygenerowany kod szkoleniowy z dowolnego zautomatyzowanego wytrenowanego modelu uczenia maszynowego.

Generowanie kodu dla zautomatyzowanych wytrenowanych modeli uczenia maszynowego umożliwia wyświetlenie następujących szczegółów, które zautomatyzowane uczenie maszynowe używa do trenowania i tworzenia modelu dla określonego przebiegu.

  • Przetwarzanie wstępne danych
  • Wybór algorytmu
  • Dobieranie cech
  • Hiperparametry

Możesz wybrać dowolny zautomatyzowany model trenowania uczenia maszynowego, zalecany lub podrzędny oraz wyświetlić wygenerowany kod szkoleniowy języka Python, który utworzył ten konkretny model.

Kod trenowania wygenerowanego modelu umożliwia:

  • Dowiedz się , jakiego procesu cechowania i hiperparametrów używa algorytm modelu.
  • Śledzenie/wersja/inspekcja wytrenowanych modeli. Przechowuj kod w wersji, aby śledzić, jaki konkretny kod szkoleniowy jest używany z modelem, który ma zostać wdrożony w środowisku produkcyjnym.
  • Dostosuj kod trenowania, zmieniając hiperparametry lub stosując umiejętności/doświadczenie w zakresie uczenia maszynowego i algorytmów, a następnie przetrenuj nowy model przy użyciu dostosowanego kodu.

Na poniższym diagramie pokazano, że można wygenerować kod dla eksperymentów zautomatyzowanego uczenia maszynowego ze wszystkimi typami zadań. Najpierw wybierz model. Wybrany model zostanie wyróżniony, a następnie usługa Azure Machine Edukacja kopiuje pliki kodu używane do tworzenia modelu i wyświetla je w folderze udostępnionym notesów. W tym miejscu możesz wyświetlać i dostosowywać kod zgodnie z potrzebami.

Screenshot showing models tab, as well as having a model selected, as explained in the above text.

Wymagania wstępne

  • Obszar roboczy usługi Azure Machine Learning. Aby utworzyć obszar roboczy, zobacz Tworzenie zasobów obszaru roboczego.

  • W tym artykule założono, że znasz konfigurowanie eksperymentu zautomatyzowanego uczenia maszynowego. Postępuj zgodnie z samouczkiem lub instrukcjami, aby zobaczyć główne wzorce projektowania eksperymentów zautomatyzowanego uczenia maszynowego.

  • Automatyczne generowanie kodu uczenia maszynowego jest dostępne tylko w przypadku eksperymentów uruchamianych na zdalnej maszynie azure Edukacja docelowych zasobów obliczeniowych. Generowanie kodu nie jest obsługiwane w przypadku przebiegów lokalnych.

  • Wszystkie przebiegi zautomatyzowanego uczenia maszynowego wyzwalane za pośrednictwem usługi Azure Machine Edukacja Studio, SDKv2 lub CLIv2 będą miały włączone generowanie kodu.

Pobieranie wygenerowanego kodu i artefaktów modelu

Domyślnie każdy zautomatyzowany model trenowany przez uczenie maszynowe generuje kod trenowania po zakończeniu trenowania. Zautomatyzowane uczenie maszynowe zapisuje ten kod w eksperymencie outputs/generated_code dla tego konkretnego modelu. Można je wyświetlić w interfejsie użytkownika usługi Azure Machine Edukacja Studio na karcie Dane wyjściowe i dzienniki wybranego modelu.

  • script.py Jest to kod trenowania modelu, który prawdopodobnie chcesz przeanalizować za pomocą kroków cechowania, używanego algorytmu i hiperparametrów.

  • script_run_notebook.ipynb Notebook z kodem płyty kotłowej w celu uruchomienia kodu trenowania modelu (script.py) w usłudze Azure Machine Edukacja obliczeniowych za pomocą usługi Azure Machine Edukacja SDKv2.

Po zakończeniu przebiegu zautomatyzowanego trenowania uczenia maszynowego można uzyskać dostęp do script.py plików i script_run_notebook.ipynb za pośrednictwem interfejsu użytkownika usługi Azure Machine Edukacja Studio.

W tym celu przejdź do karty Modele na stronie nadrzędnego przebiegu eksperymentu zautomatyzowanego uczenia maszynowego. Po wybraniu jednego z wytrenowanych modeli możesz wybrać przycisk Wyświetl wygenerowany kod . Ten przycisk przekierowuje Cię do rozszerzenia portalu Notesy , w którym można wyświetlać, edytować i uruchamiać wygenerowany kod dla danego wybranego modelu.

parent run models tab view generate code button

Po przejściu do strony uruchamiania podrzędnego określonego modelu możesz również uzyskać dostęp do wygenerowanego kodu modelu w górnej części strony przebiegu podrzędnego.

child run page view generated code button

Jeśli używasz zestawu SDKKv2 języka Python, możesz również pobrać "script.py" i "script_run_notebook.ipynb", pobierając najlepszy przebieg za pośrednictwem biblioteki MLFlow i pobierając wynikowe artefakty.

Ograniczenia

Podczas wybierania pozycji Wyświetl wygenerowany kod występuje znany problem. Ta akcja nie może przekierować do portalu notesów, gdy magazyn znajduje się za siecią wirtualną. Aby obejść ten problem, użytkownik może ręcznie pobrać script.py i pliki script_run_notebook.ipynb, przechodząc do karty Dane wyjściowe i dzienniki w folderze outputs>generated_code. Te pliki można przekazać ręcznie do folderu notesów, aby je uruchomić lub edytować. Użyj tego linku, aby dowiedzieć się więcej o sieciach wirtualnych w usłudze Azure Machine Edukacja.

Screenshot showing Outputs and Logs tab, as well as having the outputs and generated code folder selected, as explained in the above text.

script.py

Plik script.py zawiera podstawową logikę wymaganą do wytrenowania modelu przy użyciu wcześniej używanych hiperparametrów. Chociaż ma zostać wykonany w kontekście uruchomienia skryptu usługi Azure Machine Edukacja, z pewnymi modyfikacjami kod trenowania modelu może być również uruchamiany autonomicznie we własnym środowisku lokalnym.

Skrypt można podzielić na kilka następujących części: ładowanie danych, przygotowywanie danych, cechowanie danych, preprocesor/specyfikacja algorytmu i trenowanie.

Ładowanie danych

Funkcja get_training_dataset() ładuje wcześniej używany zestaw danych. Przyjęto założenie, że skrypt jest uruchamiany w skrypsie usługi Azure Machine Edukacja uruchamianym w tym samym obszarze roboczym co oryginalny eksperyment.

def get_training_dataset(dataset_id):
    from azureml.core.dataset import Dataset
    from azureml.core.run import Run
    
    logger.info("Running get_training_dataset")
    ws = Run.get_context().experiment.workspace
    dataset = Dataset.get_by_id(workspace=ws, id=dataset_id)
    return dataset.to_pandas_dataframe()

Podczas uruchamiania w ramach uruchomienia Run.get_context().experiment.workspace skryptu pobiera prawidłowy obszar roboczy. Jeśli jednak ten skrypt jest uruchamiany w innym obszarze roboczym lub uruchamiany lokalnie, należy zmodyfikować skrypt, aby jawnie określić odpowiedni obszar roboczy.

Po pobraniu obszaru roboczego oryginalny zestaw danych jest pobierany przez jego identyfikator. Inny zestaw danych o dokładnie takiej samej strukturze może być również określony przez identyfikator lub nazwę odpowiednio z wartością get_by_id() lub get_by_name(). Identyfikator można znaleźć w dalszej części skryptu w podobnej sekcji, jak w poniższym kodzie.

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('--training_dataset_id', type=str, default='xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx', help='Default training dataset id is populated from the parent run')
    args = parser.parse_args()
    
    main(args.training_dataset_id)

Możesz również zastąpić tę całą funkcję własnym mechanizmem ładowania danych; Jedynymi ograniczeniami jest to, że wartość zwracana musi być ramką danych Pandas i że dane muszą mieć taki sam kształt jak w oryginalnym eksperymencie.

Kod przygotowywania danych

Funkcja prepare_data() czyści dane, dzieli kolumny funkcji i wagi przykładowej oraz przygotowuje dane do użycia w trenowaniu. Ta funkcja może się różnić w zależności od typu zestawu danych i typu zadania eksperymentu: klasyfikacja, regresja, prognozowanie szeregów czasowych, obrazy lub zadania NLP.

Poniższy przykład pokazuje, że ogólnie ramka danych z kroku ładowania danych jest przekazywana. Kolumna etykiety i wagi próbek, jeśli zostały pierwotnie określone, są wyodrębniane, a wiersze zawierające NaN są porzucane z danych wejściowych.

def prepare_data(dataframe):
    from azureml.training.tabular.preprocessing import data_cleaning
    
    logger.info("Running prepare_data")
    label_column_name = 'y'
    
    # extract the features, target and sample weight arrays
    y = dataframe[label_column_name].values
    X = dataframe.drop([label_column_name], axis=1)
    sample_weights = None
    X, y, sample_weights = data_cleaning._remove_nan_rows_in_X_y(X, y, sample_weights,
     is_timeseries=False, target_column=label_column_name)
    
    return X, y, sample_weights

Jeśli chcesz wykonać więcej przygotowywania danych, możesz to zrobić w tym kroku, dodając niestandardowy kod przygotowywania danych.

Kod cechowania danych

Funkcja generate_data_transformation_config() określa krok cechowania w końcowym potoku scikit-learn. Featurizery z oryginalnego eksperymentu są odtwarzane tutaj wraz z ich parametrami.

Na przykład możliwe przekształcenia danych, które mogą wystąpić w tej funkcji, mogą być oparte na imputerach, takich jak , i , lub transformatory, SimpleImputer() takie jak StringCastTransformer() i CatImputer()LabelEncoderTransformer().

Poniżej przedstawiono transformator typu StringCastTransformer() , który może służyć do przekształcania zestawu kolumn. W tym przypadku zestaw wskazany przez column_names.

def get_mapper_0(column_names):
    # ... Multiple imports to package dependencies, removed for simplicity ...
    
    definition = gen_features(
        columns=column_names,
        classes=[
            {
                'class': StringCastTransformer,
            },
            {
                'class': CountVectorizer,
                'analyzer': 'word',
                'binary': True,
                'decode_error': 'strict',
                'dtype': numpy.uint8,
                'encoding': 'utf-8',
                'input': 'content',
                'lowercase': True,
                'max_df': 1.0,
                'max_features': None,
                'min_df': 1,
                'ngram_range': (1, 1),
                'preprocessor': None,
                'stop_words': None,
                'strip_accents': None,
                'token_pattern': '(?u)\\b\\w\\w+\\b',
                'tokenizer': wrap_in_lst,
                'vocabulary': None,
            },
        ]
    )
    mapper = DataFrameMapper(features=definition, input_df=True, sparse=True)
    
    return mapper

Jeśli masz wiele kolumn, które muszą mieć zastosowaną tę samą cechę/transformację (na przykład 50 kolumn w kilku grupach kolumn), te kolumny są obsługiwane przez grupowanie na podstawie typu.

W poniższym przykładzie zwróć uwagę, że każda grupa ma zastosowany unikatowy maper. Ten maper jest następnie stosowany do każdej kolumny tej grupy.

def generate_data_transformation_config():
    from sklearn.pipeline import FeatureUnion
    
    column_group_1 = [['id'], ['ps_reg_01'], ['ps_reg_02'], ['ps_reg_03'], ['ps_car_11_cat'], ['ps_car_12'], ['ps_car_13'], ['ps_car_14'], ['ps_car_15'], ['ps_calc_01'], ['ps_calc_02'], ['ps_calc_03']]
    
    column_group_2 = ['ps_ind_06_bin', 'ps_ind_07_bin', 'ps_ind_08_bin', 'ps_ind_09_bin', 'ps_ind_10_bin', 'ps_ind_11_bin', 'ps_ind_12_bin', 'ps_ind_13_bin', 'ps_ind_16_bin', 'ps_ind_17_bin', 'ps_ind_18_bin', 'ps_car_08_cat', 'ps_calc_15_bin', 'ps_calc_16_bin', 'ps_calc_17_bin', 'ps_calc_18_bin', 'ps_calc_19_bin', 'ps_calc_20_bin']
    
    column_group_3 = ['ps_ind_01', 'ps_ind_02_cat', 'ps_ind_03', 'ps_ind_04_cat', 'ps_ind_05_cat', 'ps_ind_14', 'ps_ind_15', 'ps_car_01_cat', 'ps_car_02_cat', 'ps_car_03_cat', 'ps_car_04_cat', 'ps_car_05_cat', 'ps_car_06_cat', 'ps_car_07_cat', 'ps_car_09_cat', 'ps_car_10_cat', 'ps_car_11', 'ps_calc_04', 'ps_calc_05', 'ps_calc_06', 'ps_calc_07', 'ps_calc_08', 'ps_calc_09', 'ps_calc_10', 'ps_calc_11', 'ps_calc_12', 'ps_calc_13', 'ps_calc_14']
    
    feature_union = FeatureUnion([
        ('mapper_0', get_mapper_0(column_group_1)),
        ('mapper_1', get_mapper_1(column_group_3)),
        ('mapper_2', get_mapper_2(column_group_2)),
    ])
    return feature_union

Takie podejście pozwala uzyskać bardziej usprawniony kod, nie mając bloku kodu przekształcania dla każdej kolumny, co może być szczególnie uciążliwe nawet wtedy, gdy masz dziesiątki lub setki kolumn w zestawie danych.

W przypadku zadań klasyfikacji i regresji [FeatureUnion] jest używany do cech. W przypadku modeli prognozowania szeregów czasowych wiele cech obsługujących szeregi czasowe są zbierane do potoku TimeSeriesTransformerscikit-learn, a następnie opakowane w . Każdy użytkownik dostarczył cechowanie modeli prognozowania szeregów czasowych przed tymi dostarczonymi przez zautomatyzowane uczenie maszynowe.

Kod specyfikacji preprocesora

Funkcja generate_preprocessor_config(), jeśli jest obecna, określa krok przetwarzania wstępnego, który ma zostać wykonany po cechowaniu w ostatnim potoku scikit-learn.

Zwykle ten krok przetwarzania wstępnego składa się tylko z standaryzacji/normalizacji danych, która jest realizowana za pomocą sklearn.preprocessingpolecenia .

Zautomatyzowane uczenie maszynowe określa tylko krok przetwarzania wstępnego dla modeli klasyfikacji i regresji nonensemble.

Oto przykład wygenerowanego kodu preprocesora:

def generate_preprocessor_config():
    from sklearn.preprocessing import MaxAbsScaler
    
    preproc = MaxAbsScaler(
        copy=True
    )
    
    return preproc

Kod specyfikacji algorytmów i hiperparametrów

Kod specyfikacji algorytmu i hiperparametrów jest prawdopodobnie tym, co najbardziej interesuje wielu specjalistów uczenia maszynowego.

Funkcja generate_algorithm_config() określa rzeczywisty algorytm i hiperparametry do trenowania modelu jako ostatni etap końcowego potoku scikit-learn.

W poniższym przykładzie użyto algorytmu XGBoostClassifier z określonymi hiperparametrami.

def generate_algorithm_config():
    from xgboost.sklearn import XGBClassifier
    
    algorithm = XGBClassifier(
        base_score=0.5,
        booster='gbtree',
        colsample_bylevel=1,
        colsample_bynode=1,
        colsample_bytree=1,
        gamma=0,
        learning_rate=0.1,
        max_delta_step=0,
        max_depth=3,
        min_child_weight=1,
        missing=numpy.nan,
        n_estimators=100,
        n_jobs=-1,
        nthread=None,
        objective='binary:logistic',
        random_state=0,
        reg_alpha=0,
        reg_lambda=1,
        scale_pos_weight=1,
        seed=None,
        silent=None,
        subsample=1,
        verbosity=0,
        tree_method='auto',
        verbose=-10
    )
    
    return algorithm

Wygenerowany kod w większości przypadków używa pakietów i klas oprogramowania typu open source (OSS). Istnieją wystąpienia, w których klasy otoki pośredniej są używane do uproszczenia bardziej złożonego kodu. Można na przykład zastosować klasyfikator XGBoost i inne powszechnie używane biblioteki, takie jak LightGBM lub Scikit-Learn.

Jako specjalista ML możesz dostosować kod konfiguracji tego algorytmu, dostosowując jego hiperparametry zgodnie z potrzebami na podstawie umiejętności i doświadczenia w przypadku tego algorytmu i konkretnego problemu uczenia maszynowego.

W przypadku modeli generate_preprocessor_config_N() zespołów (w razie potrzeby) i generate_algorithm_config_N() są definiowane dla każdego ucznia w modelu zespołowym, gdzie N reprezentuje umieszczanie każdego ucznia na liście modelu zespołowego. W przypadku modeli stosu metauczeń generate_algorithm_config_meta() jest definiowany.

Kończ kod szkoleniowy

Generowanie kodu emituje build_model_pipeline() i train_model() do definiowania potoku scikit-learn oraz do wywoływania fit() go odpowiednio.

def build_model_pipeline():
    from sklearn.pipeline import Pipeline
    
    logger.info("Running build_model_pipeline")
    pipeline = Pipeline(
        steps=[
            ('featurization', generate_data_transformation_config()),
            ('preproc', generate_preprocessor_config()),
            ('model', generate_algorithm_config()),
        ]
    )
    
    return pipeline

Potok scikit-learn zawiera krok cechowania, preprocesor (jeśli jest używany) oraz algorytm lub model.

W przypadku modeli prognozowania szeregów czasowych potok scikit-learn jest opakowany w element , który ma dodatkową ForecastingPipelineWrapperlogikę potrzebną do prawidłowego obsługi danych szeregów czasowych w zależności od zastosowanego algorytmu. W przypadku wszystkich typów zadań używamy PipelineWithYTransformer w przypadkach, w których kolumna etykiety musi być zakodowana.

Po utworzeniu potoku scikit-Learn wystarczy wywołać fit() metodę trenowania modelu:

def train_model(X, y, sample_weights):
    
    logger.info("Running train_model")
    model_pipeline = build_model_pipeline()
    
    model = model_pipeline.fit(X, y)
    return model

Wartość zwracana z train_model() to model dopasowany/wytrenowany na danych wejściowych.

Główny kod, który uruchamia wszystkie poprzednie funkcje, jest następujący:

def main(training_dataset_id=None):
    from azureml.core.run import Run
    
    # The following code is for when running this code as part of an Azure Machine Learning script run.
    run = Run.get_context()
    setup_instrumentation(run)
    
    df = get_training_dataset(training_dataset_id)
    X, y, sample_weights = prepare_data(df)
    split_ratio = 0.1
    try:
        (X_train, y_train, sample_weights_train), (X_valid, y_valid, sample_weights_valid) = split_dataset(X, y, sample_weights, split_ratio, should_stratify=True)
    except Exception:
        (X_train, y_train, sample_weights_train), (X_valid, y_valid, sample_weights_valid) = split_dataset(X, y, sample_weights, split_ratio, should_stratify=False)

    model = train_model(X_train, y_train, sample_weights_train)
    
    metrics = calculate_metrics(model, X, y, sample_weights, X_test=X_valid, y_test=y_valid)
    
    print(metrics)
    for metric in metrics:
        run.log(metric, metrics[metric])

Po wytrenowanym modelu można go użyć do tworzenia przewidywań za pomocą metody predict(). Jeśli eksperyment dotyczy modelu szeregów czasowych, użyj metody forecast() dla przewidywań.

y_pred = model.predict(X)

Na koniec model jest serializowany i zapisywany jako .pkl plik o nazwie "model.pkl":

    with open('model.pkl', 'wb') as f:
        pickle.dump(model, f)
    run.upload_file('outputs/model.pkl', 'model.pkl')

script_run_notebook.ipynb

Notes script_run_notebook.ipynb służy jako łatwy sposób wykonywania script.py na maszynie azure Edukacja obliczeniowych. Ten notes jest podobny do istniejących notesów przykładowych zautomatyzowanego uczenia maszynowego, jednak istnieje kilka kluczowych różnic, jak wyjaśniono w poniższych sekcjach.

Środowisko

Zazwyczaj środowisko szkoleniowe dla zautomatyzowanego przebiegu uczenia maszynowego jest automatycznie ustawiane przez zestaw SDK. Jednak w przypadku uruchamiania niestandardowego skryptu, takiego jak wygenerowany kod, zautomatyzowane uczenie maszynowe nie prowadzi już procesu, dlatego należy określić środowisko, aby zadanie polecenia powiodło się.

Generowanie kodu ponownie używa środowiska, które było używane w oryginalnym zautomatyzowanym eksperymencie uczenia maszynowego, jeśli to możliwe. Gwarantuje to, że uruchomienie skryptu trenowania nie kończy się niepowodzeniem z powodu brakujących zależności i ma korzyść po stronie, która nie wymaga ponownego kompilowania obrazu platformy Docker, co pozwala zaoszczędzić czas i zasoby obliczeniowe.

Jeśli wprowadzisz zmiany script.py , które wymagają dodatkowych zależności lub chcesz użyć własnego środowiska, musisz odpowiednio zaktualizować środowisko script_run_notebook.ipynb .

Przesyłanie eksperymentu

Ponieważ wygenerowany kod nie jest już napędzany przez zautomatyzowane uczenie maszynowe, zamiast tworzyć i przesyłać zadanie automatycznego uczenia maszynowego, musisz utworzyć Command Job kod wygenerowany (script.py) i podać do niego wygenerowany kod.

Poniższy przykład zawiera parametry i regularne zależności potrzebne do uruchomienia zadania polecenia, takiego jak obliczenia, środowisko itp.

from azure.ai.ml import command, Input

# To test with new training / validation datasets, replace the default dataset id(s) taken from parent run below
training_dataset_id = '<DATASET_ID>'

dataset_arguments = {'training_dataset_id': training_dataset_id}
command_str = 'python script.py --training_dataset_id ${{inputs.training_dataset_id}}'

command_job = command(
    code=project_folder,
    command=command_str,
    environment='AutoML-Non-Prod-DNN:25',
    inputs=dataset_arguments,
    compute='automl-e2e-cl2',
    experiment_name='build_70775722_9249eda8'
)
 
returned_job = ml_client.create_or_update(command_job)
print(returned_job.studio_url) # link to naviagate to submitted run in Azure Machine Learning Studio

Następne kroki