自動 ML モデルのトレーニング コードを表示する (プレビュー)

適用対象:Python SDK azureml v1

重要

現在、この機能はパブリック プレビュー段階にあります。 このプレビュー バージョンはサービス レベル アグリーメントなしで提供されています。運用環境のワークロードに使用することはお勧めできません。 特定の機能はサポート対象ではなく、機能が制限されることがあります。 詳しくは、Microsoft Azure プレビューの追加使用条件に関するページをご覧ください。

この記事では、自動機械学習のトレーニング済みモデルから生成されたトレーニング コードを表示する方法について説明します。

自動 ML トレーニング済みのモデルに対するコード生成により、特定の実行向けにモデルをトレーニングして構築するために自動 ML が使用する次の詳細を表示できます。

  • データの前処理
  • アルゴリズムの選択
  • 特徴付け
  • ハイパーパラメーター

任意の自動 ML トレーニング済みのモデル、推奨または子の実行を選択することで、その特定のモデルを作成した Python トレーニング コードを生成して表示できます。

生成されたモデルのトレーニング コードを使用して、次の作業を実行できます。

  • モデルのアルゴリズムが使用する特徴付けプロセスとハイパーパラメーターについて学習します。
  • トレーニング済みのモデルの追跡/バージョン管理/監査を行います。 バージョン管理されたコードを保存して、実稼働環境にデプロイされるモデルで使用される特定のトレーニング コードを追跡します。
  • ハイパーパラメーターを変更するか、自分の ML とアルゴリズムのスキル/エクスペリエンスを適用して、トレーニング コードをカスタマイズし、カスタマイズしたコードで新しいモデルの再トレーニングを行います。

タスクの種類の分類、回帰、および時系列予測を使用して、自動 ML 実験用のコードを生成できます。

警告

自動 ML の Computer Vision モデルと自然言語処理ベースのモデルでは、現在、モデルのトレーニング コードの生成はサポートされていません。

次の図は、Azure Machine Learning スタジオ UI または Azure Machine Learning SDK を使用して、自動 ML で作成されたモデルのコード生成を有効にできることを示しています。 モデルを選択すると、モデルの作成に Azure Machine Learning が使用したコード ファイルがコピーされ、ノートブックの共有フォルダーに表示されます。 ここから、必要に応じてコードを表示およびカスタマイズできます。

コード生成の図

前提条件

  • Azure Machine Learning ワークスペース。 ワークスペースを作成するには、Azure Machine Learning ワークスペースの作成に関するページを参照してください。

  • この記事では、自動化された機械学習実験の設定にある程度精通していることを前提としています。 チュートリアルまたは方法に従って、自動化された機械学習実験の主要な設計パターンについて確認してください。

  • 自動 ML のコード生成を使用できるのは、リモートの Azure ML コンピューティング先での実験実行のみです。 コード生成は、ローカル実行ではサポートされていません。

  • SDK でコード生成を有効にするには、次のオプションがあります。

SDK を使用したコード生成

既定では、自動 ML トレーニング済みのモデルごとに、トレーニングの完了後にトレーニング コードが生成されます。 自動 ML は、その特定のモデルの実験の outputs/generated_code にこのコードを保存します。 Azure ML スタジオの UI で、選択したモデルの [Outputs + logs] (出力 + ログ) タブにそれらを表示できます。

enable_code_generation=True パラメーターを使用して、AutoMLConfig オブジェクト内の自動 ML 実験のコード生成を明示的に有効にすることもできます。 このパラメーターは、実験の送信前に設定する必要があります。

自動 ML を持つ最新の Azure ML SDK が含まれている Conda 環境から experiment.submit() を呼び出すようにしてください。 これにより、リモート コンピューティング先で実行される実験に対してコード生成が適切にトリガーされます。

config = AutoMLConfig( task="classification",
                       training_data=data,
                       label_column_name="label",
                       compute_target=compute_target,
                       enable_code_generation=True
                     )

一部のトラブルシューティングでは、コード生成を無効にすることが必要な場合があります。 自動 ML 実験を送信する前に、enable_code_generation=False オブジェクトで AutoMLConfig パラメーターを使用してコード生成を無効にできます。

# Disabling Code Generation
config = AutoMLConfig( task="classification", 
                       training_data=data,
                       label_column_name="label",
                       compute_target=compute_target,
                       enable_code_generation=False
                     )

生成されたコードを含む次の 2 つのメイン ファイルがあります。

  • script.py これは、特徴付けステップ、使用される特定のアルゴリズム、およびハイパーパラメーターを使用して分析するモデルのトレーニング コードです。

  • script_run_notebook.ipynb モデルのトレーニング コード (script.py) を、ScriptRunConfig などの Azure ML SDK クラスを使用して AzureML コンピューティングで実行するためのボイラー プレート コードがあるノートブック。

生成されたコードとモデルの成果物を取得する

自動 ML のトレーニング実行が完了したら、 script.pyscript_run_notebook.ipynb の各ファイルを取得できます。 次のコードでは、最適な子実行を取得し、両方のファイルをダウンロードします。


best_run = remote_run.get_best_child()

best_run.download_file("outputs/generated_code/script.py", "script.py")
best_run.download_file("outputs/generated_code/script_run_notebook.ipynb", "script_run_notebook.ipynb")

生成されたコードの表示と、Azure Machine Learning スタジオ UI を使用したコードのカスタマイズの準備も実行できます。

これを行うには、自動 ML 実験の親実行ページの [Models] (モデル) タブに移動します。 トレーニング済みのモデルのいずれかを選択した後、[View generated code (preview)] (生成されたコードの表示 (プレビュー)) ボタンを選択できます。 このボタンにより、[Notebooks] ポータル拡張機能にリダイレクトされ、そこで特定の選択したモデルに対して生成されたコードを表示、編集、および実行できます。

親実行の [モデル] タブの [生成されたコードの表示] ボタン

別の方法として、特定のモデルの子実行のページに移動すると、子実行のページの上部からモデルに対して生成されたコードにアクセスすることもできます。

子実行ページの [生成されたコードの表示] ボタン

script.py

script.py ファイルには、前に使用したハイパーパラメーターでモデルのトレーニングに必要であったコア ロジックが含まれています。 モデルのトレーニング コードは Azure ML スクリプトの実行のコンテキストで実行することが意図されていますが、いくつかの変更を加えると、独自のオンプレミス環境でスタンドアロンで実行することもできます。

スクリプトは、データの読み込み、データの準備、データの特徴付け、プリプロセッサ/アルゴリズムの指定、トレーニングなどの、いくつかの部分におおまかに分割できます。

データの読み込み

関数 get_training_dataset() が、前に使用したデータセットを読み込みます。 これトは、元の実験と同じワークスペースで実行される AzureML スクリプト実行で実行することを前提にしています。

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

スクリプト実行の一部として実行すると、Run.get_context().experiment.workspace が正 しいワークスペースを取得します。 ただし、このスクリプトを別のワークスペース内で、または ScriptRunConfig を使用せずにローカルで実行する場合は、スクリプトを変更して該当するワークスペースを明示的に指定する必要があります。

ワークスペースが取得されると、元のデータセットが ID によって取得されます。 それぞれ get_by_id() または get_by_name() で、ID または名前を指定してまったく同じ構造の別のデータセットを指定することもできます。 この ID は、このスクリプトの後方にある次のコードのようなセクションで確認できます。

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)

この関数全体を独自のデータ読み込みメカニズムに置き換える選択もできます。唯一の制約は、戻り値が Pandas データフレームであり、データが元の実験と同じ形状である必要があるということです。

データの準備コード

関数 prepare_data() は、データをクリーンアップし、特徴量とサンプル重みの列を分割し、トレーニングで使用するデータを準備します。 この関数は、データセットの種類と実験タスクの種類 (分類、回帰、または時系列予測) によって異なる場合があります。

次の例は、一般に、データ読み込みステップのデータフレームが渡されることを示しています。 ラベル列とサンプルの重み付け (最初に指定した場合) が抽出され、NaN を含む行が入力データから削除されます。

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

追加のデータ準備を行う場合は、このステップでカスタム データ準備コードを追加することで実行できます。

データの特徴付けコード

関数 generate_data_transformation_config() は、最後の scikit-learn パイプラインに特徴付けステップを指定します。 元の実験の特徴抽出器が、パラメーターとともにここで再現されます。

たとえば、この関数で発生する可能性があるデータ変換が、SimpleImputer()CatImputer() などのインピューター、または StringCastTransformer()LabelEncoderTransformer() などのトランスフォーマーに基づいているとします。

列のセットを変換するために使用できる StringCastTransformer() 型のトランスフォーマーを次に示します。 この場合、セットは column_names で示されています。

def get_mapper_c6ba98(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

同じ特徴付け/変換を適用する必要がある多数の列がある場合 (たとえば、複数の列グループ内の 50 列)、これらの列は型に基づいてグループ化することで処理されます。

次の例では、各グループに一意のマッパーが適用されています。 このマッパーは、そのグループの各列に適用されます。

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_ab1045', get_mapper_ab1045(column_group_1)),
        ('mapper_c6ba98', get_mapper_c6ba98(column_group_3)),
        ('mapper_9133f9', get_mapper_9133f9(column_group_2)),
    ])
    return feature_union

この方法では、データセットに数十または数百の列があるときに特に面倒になる可能性がある、各列にトランスフォーマーのコード ブロックを含める作業をせずに、より効率的にコードを作成できます。

分類と回帰のタスクでは、[FeatureUnion] が特徴抽出器として使用されます。 時系列予測モデルの場合、複数の時系列対応の特徴抽出器が scikit-learn パイプラインに収集されて、TimeSeriesTransformer にラップされます。 時系列予測モデルに対してユーザーが提供した特徴付けは、自動 ML によって提供されたものより前に実行されます。

プリプロセッサの指定コード

関数 generate_preprocessor_config() (存在する場合) は、最後の scikit-learn パイプラインの特徴付け後に実行される前処理ステップを指定します。

通常、この前処理ステップは、sklearn.preprocessing で実行されるデータの標準化/正規化のみで構成されます。

自動 ML は、非アンサンブル分類と回帰のモデルの前処理ステップのみを指定します。

生成されたプリプロセッサ コードの例を次に示します。

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

アルゴリズムとハイパーパラメーターの指定コード

アルゴリズムとハイパーパラメーターの指定コードは、多くの ML の専門家が最も関心を持っている可能性があるものです。

関数 generate_algorithm_config() は、最後の scikit-learn パイプラインの最後のステージとして、モデルをトレーニングするための実際のアルゴリズムとハイパーパラメーターを指定します。

次の例では、特定のハイパーパラメーターを指定して XGBoostClassifier アルゴリズムを使用します。

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

ほとんどの場合、生成されるコードはオープン ソース ソフトウェア (OSS) のパッケージとクラスを使用します。 より複雑なコードを簡素化するために中間ラッパー クラスが使用されているインスタンスもあります。 たとえば、XGBoost 分類子や、LightGBM、Scikit-Learn の各アルゴリズムなどの一般的に使用されるライブラリを適用できます。

ML の専門家は、アルゴリズムと特定の ML の問題のスキルと経験に基づいて、必要に応じてハイパーパラメーターを調整することで、そのアルゴリズムの構成コードをカスタマイズできます。

アンサンブル モデルについては、generate_preprocessor_config_N() (必要な場合) と generate_algorithm_config_N() が、アンサンブル モデルの各学習器に対して定義されます。ここで、N はアンサンブル モデルのリスト内の各学習器の配置位置を表します。 スタック アンサンブル モデルについては、メタ学習器 generate_algorithm_config_meta() が定義されます。

エンドツーエンド トレーニング コード

コード生成では、scikit-learn パイプラインを定義し、それに対して fit() を呼び出すために、build_model_pipeline()train_model() がそれぞれ出力されます。

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

scikit-learn パイプラインには、特性付けステップ、プリプロセッサ (使用される場合)、およびアルゴリズムまたはモデルが含まれています。

時系列予測モデルの場合、scikit-learn パイプラインは ForecastingPipelineWrapper にラップされます。これには、適用されたアルゴリズムに応じて時系列データを適切に処理するために必要な追加のロジックがあります。 すべてのタスクの種類について、ラベル列をエンコードする必要がある場合に PipelineWithYTransformer を使用します。

scikit-Learn パイプラインを作成したら、この後呼び出す必要があるのは、モデルをトレーニングする fit() メソッドのみです。

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

train_model() からの戻り値は、入力データに適合し、トレーニングされたモデルです。

上記のすべての関数を実行するメイン コードは次のとおりです。

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 AzureML 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])

トレーニング済みのモデルを作成したら、それを使用して predict () メソッドで予測を行うことができます。 実験が時系列モデルの場合は、予測に forecast() メソッドを使用します。

y_pred = model.predict(X)

最後に、モデルはシリアル化され、"model.pkl" という名前の .pkl ファイルとして保存されます。

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

script_run_notebook.ipynb

script_run_notebook.ipynb ノートブックは、Azure ML コンピューティングで簡単に script.py を実行する方法として機能します。 このノートブックは、既存の自動 ML のサンプル ノートブックに似ていますが、以降のセクションで説明するように、重要な違いがいくつかあります。

環境

通常、自動 ML 実行のトレーニング環境は、SDK によって自動的に設定されます。 ただし、生成されたコードなどのカスタム スクリプト実行を実行するときは、自動 ML によってプロセスが駆動されなくなるため、スクリプト実行を成功させるために環境を指定する必要があります。

コード生成では、可能であれば、元の自動 ML 実験で使用された環境を再利用します。 そうすることで、依存関係がないためにトレーニング スクリプト実行が失敗することがなくなり、Docker イメージを再構築する必要がないという副次的効果があります。これにより、時間とコンピューティングリソースが節約されます。

追加の依存関係が必要な変更を script.py に加える場合、または独自の環境を使用する場合は、それに応じて script_run_notebook.ipynbCreate environment セルを更新する必要があります。

AzureML 環境の詳細については、Environment クラスのドキュメントを参照してください。

実験を送信する

生成されたコードは、自動 ML では駆動されなくなるため、AutoMLConfig を作成して experiment.submit() に渡す代わりに、ScriptRunConfig を作成し、生成されたコード (script.py) をそこに渡す必要があります。

次の例には、計算、環境などの、ScriptRunConfig の実行に必要なパラメーターと通常の依存関係が含まれています。ScriptRunConfig の使用方法の詳細については、「トレーニングの実行を構成して送信する」を参照してください。

from azureml.core import ScriptRunConfig

src = ScriptRunConfig(source_directory=project_folder, 
                      script='script.py', 
                      compute_target=cpu_cluster, 
                      environment=myenv,
                      docker_runtime_config=docker_config)
 
run = experiment.submit(config=src)

シリアル化されたトレーニング済みのモデルをメモリ内にダウンロードして読み込む

トレーニング済みのモデルを作成したら、.pklpickle.dump() を使用して pickle.load() ファイルに保存/シリアル化できます。 joblib.dump()joblib.load() を使用することもできます。

次の例は、ScriptRunConfig を使用して AzureML コンピューティングでトレーニングされたモデルをダウンロードし、メモリ内に読み込む方法を示しています。 このコードは、Azure ML SDK の ScriptRunConfig を使用したのと同じノートブックで実行できます。

import joblib

# Load the fitted model from the script run.

# Note that if training dependencies are not installed on the machine
# this notebook is being run from, this step can fail.
try:
    # Download the model from the run in the Workspace
    run.download_file("outputs/model.pkl", "model.pkl")

    # Load the model into memory
    model = joblib.load("model.pkl")

except ImportError:
    print('Required dependencies are missing; please run pip install azureml-automl-runtime.')
    raise

メモリ内のモデルで予測を行う

最後に、Pandas データフレームにテスト データを読み込み、モデルを使用して予測を行うことができます。

import os
import numpy as np
import pandas as pd

DATA_DIR = "."
filepath = os.path.join(DATA_DIR, 'porto_seguro_safe_driver_test_dataset.csv')

test_data_df = pd.read_csv(filepath)

print(test_data_df.shape)
test_data_df.head(5)

#test_data_df is a Pandas dataframe with test data
y_predictions = model.predict(test_data_df)

Azure ML のコンピューティング インスタンスにはすべての自動 ML 依存関係があるため、モデルを読み込んで、最近作成されたコンピューティング インスタンス内の任意のノートブックから予測を行うことができます。

ただし、カスタムのローカル Conda 環境のノートブックにそのモデルを読み込むには、トレーニング (AutoML 環境) のインストール時に使用された環境由来のすべての依存関係を取得する必要があります。

次のステップ