概要: Azure Databricks で最初の機械学習モデルを構築する
この記事では、Azure Databricks で scikit-learn
ライブラリを使用して機械学習分類モデルを構築する方法について説明します。
目標は、ワインが "高品質" と見なされるかどうかを予測する分類モデルを作成することです。 データセットは、さまざまなワインの 11 種類の特徴 (アルコール含有量、酸度、残留糖など) と、1 から 10 の品質ランク付けで構成されます。
この例では、MLflow を使用してモデル開発プロセスを追跡し、Hyperopt を使用してハイパーパラメーターの調整を自動化する方法についても説明します。
データセットは、「Modeling wine preferences by data mining from physicochemical properties」(物理化学的特性からのデータ マイニングによるワインの好みのモデリング) [Cortez 他、2009 年] で発表された、UCI Machine Learning リポジトリのものです。
- ワークスペースは、Unity Catalog に対して有効にする必要があります。
- クラスターを作成するためのアクセス許可またはクラスターへのアクセスが必要です。
- カタログに対する USE_CATALOG 権限が必要です。
- そのカタログ内で、スキーマに対する次の権限が必要です: USE_SCHEMA、CREATE_TABLE、および CREATE_MODEL。
ヒント
この記事のすべてのコードは、ワークスペースに直接インポートできるノートブックで使用することができます。 「ノートブックの例: 分類モデルを構築する」を参照してください。
ワークスペースにノートブックを作成するには、サイドバーの [新規] をクリックしてから、[ノートブック] をクリックします。 ワークスペースに空のノートブックが開きます。
ノートブックの作成と管理について詳しくは、「Notebooks を管理する」を参照してください。
探索的データ分析とデータ エンジニアリングを行うには、コンピューティングにアクセスできる必要があります。
既存のコンピューティング リソースに接続する手順については、「コンピュート」を参照してください。 新しいコンピューティング リソースを構成する手順については、「コンピューティング構成リファレンス」を参照してください。
この記事の手順には、Databricks Runtime for Machine Learning が必要です。 ML バージョンの Databricks Runtime を選択する手順などの詳細については、「Databricks Runtime for Machine Learning」を参照してください。
開始する前に、2 つの重要な手順が必要です。 まず、モデル レジストリとして Unity Catalog を使用するように MLflow クライアントを構成する必要があります。 ノートブックの新しいセルに以下のコードを入力します。
import mlflow
mlflow.set_registry_uri("databricks-uc")
また、モデルを登録するカタログとスキーマを設定する必要があります。 カタログに対する USE CATALOG 権限と、スキーマに対する USE_SCHEMA、CREATE_TABLE、および CREATE_MODEL 権限が必要です。
Unity Catalog の使用方法の詳細については、「Unity Catalog とは」を参照してください。
ノートブックの新しいセルに以下のコードを入力します。
# If necessary, replace "main" and "default" with a catalog and schema for which you have the required permissions.
CATALOG_NAME = "main"
SCHEMA_NAME = "default"
この例では、Azure Databricks に組み込まれている 2 つの CSV ファイルを使用します。 独自のデータを取り込む方法については、「Databricks レイクハウスにデータを取り込む」を参照してください。
ノートブックの新しいセルに以下のコードを入力します。
white_wine = spark.read.csv("dbfs:/databricks-datasets/wine-quality/winequality-white.csv", sep=';', header=True)
red_wine = spark.read.csv("dbfs:/databricks-datasets/wine-quality/winequality-red.csv", sep=';', header=True)
# Remove the spaces from the column names
for c in white_wine.columns:
white_wine = white_wine.withColumnRenamed(c, c.replace(" ", "_"))
for c in red_wine.columns:
red_wine = red_wine.withColumnRenamed(c, c.replace(" ", "_"))
# Define table names
red_wine_table = f"{CATALOG_NAME}.{SCHEMA_NAME}.red_wine"
white_wine_table = f"{CATALOG_NAME}.{SCHEMA_NAME}.white_wine"
# Write to tables in Unity Catalog
spark.sql(f"DROP TABLE IF EXISTS {red_wine_table}")
spark.sql(f"DROP TABLE IF EXISTS {white_wine_table}")
white_wine.write.saveAsTable(f"{CATALOG_NAME}.{SCHEMA_NAME}.white_wine")
red_wine.write.saveAsTable(f"{CATALOG_NAME}.{SCHEMA_NAME}.red_wine")
この手順では、手順 4 で作成した Unity Catalog テーブルから Pandas DataFrames にデータを読み込み、データを前処理します。 このセクションのコードでは、次のことが行われます。
- Pandas DataFrames としてデータを読み込みます。
- 赤ワインと白ワインを区別するために各 DataFrame にブール型の列を追加し、DataFrame を新しい DataFrame
data_df
に結合します。 - データセットには、1 から 10 まで (10 は最高品質) でワインを評価する
quality
列が含まれます。 このコードは、この列を次の 2 つの分類値に変換します。"True" は高品質ワイン (quality
>= 7) を示し、"False" は高品質ではないワイン (quality
< 7) を示します。 - DataFrame を個別のトレーニング データセットとテスト データセットに分割します。
まず、必要なライブラリをインポートします。
import numpy as np
import pandas as pd
import sklearn.datasets
import sklearn.metrics
import sklearn.model_selection
import sklearn.ensemble
import matplotlib.pyplot as plt
from hyperopt import fmin, tpe, hp, SparkTrials, Trials, STATUS_OK
from hyperopt.pyll import scope
ここでデータを読み込み、前処理します。
# Load data from Unity Catalog as Pandas dataframes
white_wine = spark.read.table(f"{CATALOG_NAME}.{SCHEMA_NAME}.white_wine").toPandas()
red_wine = spark.read.table(f"{CATALOG_NAME}.{SCHEMA_NAME}.red_wine").toPandas()
# Add Boolean fields for red and white wine
white_wine['is_red'] = 0.0
red_wine['is_red'] = 1.0
data_df = pd.concat([white_wine, red_wine], axis=0)
# Define classification labels based on the wine quality
data_labels = data_df['quality'].astype('int') >= 7
data_df = data_df.drop(['quality'], axis=1)
# Split 80/20 train-test
X_train, X_test, y_train, y_test = sklearn.model_selection.train_test_split(
data_df,
data_labels,
test_size=0.2,
random_state=1
)
この手順では、デフォルトのアルゴリズム設定を使用して、勾配ブースティング分類器をトレーニングします。 次に、結果のモデルをテスト データセットに適用し、受信者操作曲線の下の領域を計算してログに記録し、表示することでモデルのパフォーマンスを評価します。
まず、MLflow の自動ログ記録を有効化します。
mlflow.autolog()
ここで、モデル トレーニングの実行を開始します。
with mlflow.start_run(run_name='gradient_boost') as run:
model = sklearn.ensemble.GradientBoostingClassifier(random_state=0)
# Models, parameters, and training metrics are tracked automatically
model.fit(X_train, y_train)
predicted_probs = model.predict_proba(X_test)
roc_auc = sklearn.metrics.roc_auc_score(y_test, predicted_probs[:,1])
roc_curve = sklearn.metrics.RocCurveDisplay.from_estimator(model, X_test, y_test)
# Save the ROC curve plot to a file
roc_curve.figure_.savefig("roc_curve.png")
# The AUC score on test data is not automatically logged, so log it manually
mlflow.log_metric("test_auc", roc_auc)
# Log the ROC curve image file as an artifact
mlflow.log_artifact("roc_curve.png")
print("Test AUC of: {}".format(roc_auc))
セルの結果には、曲線の下の計算領域と ROC 曲線のプロットが表示されます。
MLflow 実験追跡では、モデルを反復開発するときにコードと結果をログに記録することで、モデル開発を追跡することができます。
先ほど実行したトレーニング実行のログ結果を表示するには、次の図に示すように、セル出力のリンクをクリックします。
実験ページでは、実行を比較し、特定の実行の詳細を表示することができます。 「MLflow 実験追跡」を参照してください。
ML モデルを開発する際の重要な手順は、ハイパーパラメーターと呼ばれる、アルゴリズムを制御するパラメーターを調整することにより、モデルの精度を最適化することです。
Databricks Runtime ML には、ハイパーパラメーターの調整のための Python ライブラリである Hyperopt が含まれています。 Hyperopt を使用してハイパーパラメーター スイープを実行し、複数のモデルを並列でトレーニングすると、モデルのパフォーマンスを最適化するために必要な時間を短縮できます。 MLflow 追跡は Hyperopt と統合され、モデルとパラメーターを自動的にログ記録します。 Databricks でのハイパーパラメーターの使用に関する詳細については、「ハイパーパラメーターの調整」を参照してください。
次のコードは、Hyperopt の使用例を示しています。
# Define the search space to explore
search_space = {
'n_estimators': scope.int(hp.quniform('n_estimators', 20, 1000, 1)),
'learning_rate': hp.loguniform('learning_rate', -3, 0),
'max_depth': scope.int(hp.quniform('max_depth', 2, 5, 1)),
}
def train_model(params):
# Enable autologging on each worker
mlflow.autolog()
with mlflow.start_run(nested=True):
model_hp = sklearn.ensemble.GradientBoostingClassifier(
random_state=0,
**params
)
model_hp.fit(X_train, y_train)
predicted_probs = model_hp.predict_proba(X_test)
# Tune based on the test AUC
# In production, you could use a separate validation set instead
roc_auc = sklearn.metrics.roc_auc_score(y_test, predicted_probs[:,1])
mlflow.log_metric('test_auc', roc_auc)
# Set the loss to -1*auc_score so fmin maximizes the auc_score
return {'status': STATUS_OK, 'loss': -1*roc_auc}
# SparkTrials distributes the tuning using Spark workers
# Greater parallelism speeds processing, but each hyperparameter trial has less information from other trials
# On smaller clusters try setting parallelism=2
spark_trials = SparkTrials(
parallelism=1
)
with mlflow.start_run(run_name='gb_hyperopt') as run:
# Use hyperopt to find the parameters yielding the highest AUC
best_params = fmin(
fn=train_model,
space=search_space,
algo=tpe.suggest,
max_evals=32,
trials=spark_trials)
次のコードは、ROC 曲線の下の領域で測定された、最適な結果を生成した実行を識別します。
# Sort runs by their test auc. In case of ties, use the most recent run.
best_run = mlflow.search_runs(
order_by=['metrics.test_auc DESC', 'start_time DESC'],
max_results=10,
).iloc[0]
print('Best Run')
print('AUC: {}'.format(best_run["metrics.test_auc"]))
print('Num Estimators: {}'.format(best_run["params.n_estimators"]))
print('Max Depth: {}'.format(best_run["params.max_depth"]))
print('Learning Rate: {}'.format(best_run["params.learning_rate"]))
次のコードは、最適なモデルとして識別した run_id
を使用して、そのモデルを Unity Catalog に登録します。
model_uri = 'runs:/{run_id}/model'.format(
run_id=best_run.run_id
)
mlflow.register_model(model_uri, f"{CATALOG_NAME}.{SCHEMA_NAME}.wine_quality_model")
この記事の手順を実行するには、次のノートブックを使用します。 Azure Databricks ワークスペースにノートブックをインポートする手順については、「ノートブックをインポートする」を参照してください。
Databricks では、生データから、提供されるモデルのすべての要求と応答が保存される推論テーブルまで、ML の開発とデプロイのすべてのステップが 1 つのプラットフォームで提供されます。 データ サイエンティスト、データ エンジニア、ML エンジニア、DevOps は、同じツール セットと、データの信頼できる唯一の情報源を使って、自分の仕事を行うことができます。
詳細については、次の記事を参照してください。