チュートリアル: テキスト分類モデルを作成、評価、スコア付けする
このチュートリアルでは、Microsoft Fabric のテキスト分類モデルの Synapse Data Science ワークフローのエンド ツー エンドの例を示します。 このシナリオでは、Spark で word2vec とロジスティック回帰を使用して、書籍のタイトルのみに基づいて、大英図書館の書籍データセットから書籍のジャンルを決定します。
このチュートリアルでは、次の手順について説明します。
- カスタム ライブラリをインストールする
- データを読み込む
- 探索的データ分析を使用してデータを理解して処理する
- word2vec とロジスティック回帰を使用して機械学習モデルをトレーニングし、MLflow と Fabric 自動ログ機能を使用して実験を追跡する
- スコアリングと予測のために機械学習モデルを読み込む
前提 条件
Microsoft Fabric サブスクリプションを取得します。 または、無料でMicrosoft Fabricの試用版にサインアップする。
Microsoft Fabric にサインインします。
ホーム ページの左下にあるエクスペリエンス スイッチャーを使用して、Fabric に切り替えます。
- Microsoft Fabric Lakehouse がない場合は、「Microsoft Fabric でレイクハウスを作成するの手順に従って作成します。
ノートブックで作業を進める
ノートブックで作業を進めるために、次のオプションのいずれかを選択できます。
- 組み込みのノートブックを開いて実行します。
- GitHub からノートブックをアップロードします。
組み込みのノートブックを開く
このチュートリアルには、Title genre classification というサンプル ノートブックが付属しています。
このチュートリアルのサンプル ノートブックを開くには、「データサイエンスチュートリアル用にシステムを準備する」の手順に従ってください ()。
コードの実行を開始する前に、必ずレイクハウスをノートブックにアタッチしてください。
GitHub からノートブックをインポートする
AIsample - Title Genre Classification.ipynb は、このチュートリアルに付属するノートブックです。
このチュートリアルの付属のノートブックを開くには、「データ サイエンス用にシステムを準備する」の手順に従って、ノートブックをワークスペースにインポート します。
もしこのページからコードをコピーして貼り付けたい場合は、新しいノートブックを作成することができます。
コードの実行を開始する前に、必ずレイクハウスをノートブックにアタッチしてください。
手順 1: カスタム ライブラリをインストールする
機械学習モデルの開発やアドホック データ分析の場合は、Apache Spark セッション用のカスタム ライブラリをすばやくインストールすることが必要になる場合があります。 ライブラリをインストールするには、2 つのオプションがあります。
- ノートブックのインライン インストール機能 (
%pip
または%conda
) を使用して、現在のノートブックにのみライブラリをインストールします。 - または、ファブリック環境を作成したり、パブリック ソースからライブラリをインストールしたり、カスタム ライブラリをアップロードしたりして、ワークスペース管理者がワークスペースの既定として環境をアタッチすることもできます。 その後、環境内のすべてのライブラリが、ワークスペース内のすべてのノートブックと Spark ジョブ定義で使用できるようになります。 環境の詳細については、「Microsoft Fabric で環境作成、構成、および使用する」を参照してください。
分類モデルでは、wordcloud
ライブラリを使用して、単語の頻度をテキストで表します。単語のサイズはその頻度を表します。 このチュートリアルでは、%pip install
を使用してノートブックに wordcloud
をインストールします。
手記
PySpark カーネルは、%pip install
の実行後に再起動します。 他のセルを実行する前に、必要なライブラリをインストールします。
# Install wordcloud for text visualization by using pip
%pip install wordcloud
手順 2: データを読み込む
データセットには、ライブラリと Microsoft のコラボレーションによってデジタル化された大英図書館の書籍に関するメタデータが含まれています。 メタデータは、書籍が架空か不承認かを示す分類情報です。 このデータセットでは、タイトルのみに基づいて書籍のジャンルを決定する分類モデルをトレーニングすることが目標です。
BL レコード ID | リソースの種類 | 名前 | 名前に関連付けられている日付 | 名前の種類 | 役割 | すべての名前 | タイトル | バリアント タイトル | 系列のタイトル | 系列内の数値 | 発行国 | 発行場所 | 発行者 | 発行日 | エディション | 物理的な説明 | デューイ分類 | BL シェルフマーク | トピック | ジャンル | 言語 | メモ | 物理リソースの BL レコード ID | 分類ID | ユーザーID | created_at | subject_ids | 注釈者_公開日 | annotator_normalised_date_pub | 注釈者の編集声明 | アノテーターのジャンル | annotator_FAST_genre_terms | annotator_FAST_subject_terms | 注釈者のコメント | annotator_main_language | annotator_other_languages_summaries | annotator_summaries_language | annotator_translation | annotator_original_language | 注釈者_出版社 | annotator_place_pub | annotator_country | アノテーターの肩書 | デジタル化された書籍へのリンク | 注釈 付き |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
014602826 | モノグラフ | Yearsley、Ann | 1753-1806 | 人物 | モア, ハンナ, 1745-1833 [人]; イヤーズリー, アン, 1753-1806 [人] | Poems on several occasions [With a prefatory letter by Hannah More.] | イングランド | ロンドン | 1786 | 第4版の原稿ノート | デジタル ストア 11644.d.32 | 英語 | 003996603 | False | |||||||||||||||||||||||||||||||
014602830 | モノグラフ | A、T。 | 人物 | オールダム、ジョン、1653-1683 [人];A、T [人] | A Satyr against Vertue. この詩は、Town-Hector が朗読するように作られています。(ジョン・オールダム作。序文署名: T. A.) | イングランド | ロンドン | 1679 | 15 ページ (4°) | 「Digital Store 11602.ee.10」 (2.) | 英語 | 000001143 | False |
このノートブックをさまざまなデータセットに適用できるように、次のパラメーターを定義します。
IS_CUSTOM_DATA = False # If True, the user must manually upload the dataset
DATA_FOLDER = "Files/title-genre-classification"
DATA_FILE = "blbooksgenre.csv"
# Data schema
TEXT_COL = "Title"
LABEL_COL = "annotator_genre"
LABELS = ["Fiction", "Non-fiction"]
EXPERIMENT_NAME = "sample-aisample-textclassification" # MLflow experiment name
データセットをダウンロードして lakehouse にアップロードする
このコードは、公開されているバージョンのデータセットをダウンロードし、Fabric Lakehouse に格納します。
重要
実行する前に、ノートブックにレイクハウス を追加します。 これを行わないと、エラーが発生します。
if not IS_CUSTOM_DATA:
# Download demo data files into the lakehouse, if they don't exist
import os, requests
remote_url = "https://synapseaisolutionsa.blob.core.windows.net/public/Title_Genre_Classification"
fname = "blbooksgenre.csv"
download_path = f"/lakehouse/default/{DATA_FOLDER}/raw"
if not os.path.exists("/lakehouse/default"):
# Add a lakehouse, if no default lakehouse was added to the notebook
# A new notebook won't link to any lakehouse by default
raise FileNotFoundError(
"Default lakehouse not found, please add a lakehouse and restart the session."
)
os.makedirs(download_path, exist_ok=True)
if not os.path.exists(f"{download_path}/{fname}"):
r = requests.get(f"{remote_url}/{fname}", timeout=30)
with open(f"{download_path}/{fname}", "wb") as f:
f.write(r.content)
print("Downloaded demo data files into lakehouse.")
必要なライブラリをインポートする
処理を行う前に、必要なライブラリ (Spark のライブラリを含む) をインポートし、SynapseML する必要があります。
import numpy as np
from itertools import chain
from wordcloud import WordCloud
import matplotlib.pyplot as plt
import seaborn as sns
import pyspark.sql.functions as F
from pyspark.ml import Pipeline
from pyspark.ml.feature import *
from pyspark.ml.tuning import CrossValidator, ParamGridBuilder
from pyspark.ml.classification import LogisticRegression
from pyspark.ml.evaluation import (
BinaryClassificationEvaluator,
MulticlassClassificationEvaluator,
)
from synapse.ml.stages import ClassBalancer
from synapse.ml.train import ComputeModelStatistics
import mlflow
ハイパーパラメーターの定義
モデル トレーニング用のハイパーパラメーターをいくつか定義します。
重要
これらのハイパーパラメーターは、各パラメーターを理解している場合にのみ変更します。
# Hyperparameters
word2vec_size = 128 # The length of the vector for each word
min_word_count = 3 # The minimum number of times that a word must appear to be considered
max_iter = 10 # The maximum number of training iterations
k_folds = 3 # The number of folds for cross-validation
このノートブックの実行に必要な時間の記録を開始します。
# Record the notebook running time
import time
ts = time.time()
MLflow 実験の追跡を設定する
自動ログは、MLflow ログ機能を拡張します。 自動ログでは、機械学習モデルのトレーニング時に、入力パラメーターの値と出力メトリックが自動的にキャプチャされます。 その後、この情報をワークスペースに記録します。 ワークスペースでは、MLflow API または対応する実験を使用して、ワークスペース内の情報にアクセスして視覚化できます。 自動ログ記録の詳細については、「Microsoft Fabric での自動ログ記録の」を参照してください。
# Set up Mlflow for experiment tracking
mlflow.set_experiment(EXPERIMENT_NAME)
mlflow.autolog(disable=True) # Disable Mlflow autologging
ノートブック セッションで Microsoft Fabric の自動ログ記録を無効にするには、mlflow.autolog()
を呼び出して disable=True
設定します。
レイクハウスから日付の生データを読み取る
raw_df = spark.read.csv(f"{DATA_FOLDER}/raw/{DATA_FILE}", header=True, inferSchema=True)
手順 3: 探索的データ分析を実行する
display
コマンドを使用してデータセットを探索し、データセットの高レベルの統計情報を表示し、グラフ ビューを表示します。
display(raw_df.limit(20))
データを準備する
重複を削除してデータをクリーンアップします。
df = (
raw_df.select([TEXT_COL, LABEL_COL])
.where(F.col(LABEL_COL).isin(LABELS))
.dropDuplicates([TEXT_COL])
.cache()
)
display(df.limit(20))
クラスのバランス調整を適用して、バイアスに対処します。
# Create a ClassBalancer instance, and set the input column to LABEL_COL
cb = ClassBalancer().setInputCol(LABEL_COL)
# Fit the ClassBalancer instance to the input DataFrame, and transform the DataFrame
df = cb.fit(df).transform(df)
# Display the first 20 rows of the transformed DataFrame
display(df.limit(20))
データセットをトークン化するために、段落と文をより小さな単位に分割します。 このようにすると、意味を割り当てるのが簡単になります。 次に、ストップワードを削除してパフォーマンスを向上させます。 ストップワードの削除には、コーパス内のすべてのドキュメントで一般的に発生する単語の削除が含まれます。 ストップワードの削除は、自然言語処理 (NLP) アプリケーションで最もよく使用される前処理手順の 1 つです。
# Text transformer
tokenizer = Tokenizer(inputCol=TEXT_COL, outputCol="tokens")
stopwords_remover = StopWordsRemover(inputCol="tokens", outputCol="filtered_tokens")
# Build the pipeline
pipeline = Pipeline(stages=[tokenizer, stopwords_remover])
token_df = pipeline.fit(df).transform(df)
display(token_df.limit(20))
各クラスのワードクラウド ライブラリを表示します。 ワードクラウド ライブラリは、テキスト データに頻繁に表示されるキーワードの視覚的に目立つプレゼンテーションです。 ワードクラウドライブラリは、キーワードのレンダリングがクラウドのようなカラー画像を形成し、メインテキストデータをより一目でキャプチャするために効果的です。 ワードクラウドの詳細を確認してください。
# WordCloud
for label in LABELS:
tokens = (
token_df.where(F.col(LABEL_COL) == label)
.select(F.explode("filtered_tokens").alias("token"))
.where(F.col("token").rlike(r"^\w+$"))
)
top50_tokens = (
tokens.groupBy("token").count().orderBy(F.desc("count")).limit(50).collect()
)
# Generate a wordcloud image
wordcloud = WordCloud(
scale=10,
background_color="white",
random_state=42, # Make sure the output is always the same for the same input
).generate_from_frequencies(dict(top50_tokens))
# Display the generated image by using matplotlib
plt.figure(figsize=(10, 10))
plt.title(label, fontsize=20)
plt.axis("off")
plt.imshow(wordcloud, interpolation="bilinear")
最後に、word2vec を使用してテキストをベクター化します。 word2vec 手法は、テキスト内の各単語のベクター表現を作成します。 同様のコンテキストで使用される単語、またはセマンティック リレーションシップを持つ単語は、ベクトル空間内の近接性によって効果的にキャプチャされます。 この近接性は、類似した単語に類似の単語ベクトルがあることを示します。
# Label transformer
label_indexer = StringIndexer(inputCol=LABEL_COL, outputCol="labelIdx")
vectorizer = Word2Vec(
vectorSize=word2vec_size,
minCount=min_word_count,
inputCol="filtered_tokens",
outputCol="features",
)
# Build the pipeline
pipeline = Pipeline(stages=[label_indexer, vectorizer])
vec_df = (
pipeline.fit(token_df)
.transform(token_df)
.select([TEXT_COL, LABEL_COL, "features", "labelIdx", "weight"])
)
display(vec_df.limit(20))
手順 4: モデルをトレーニングして評価する
データを配置した状態で、モデルを定義します。 このセクションでは、ベクトル化されたテキストを分類するロジスティック回帰モデルをトレーニングします。
トレーニング データセットとテスト データセットを準備する
# Split the dataset into training and testing
(train_df, test_df) = vec_df.randomSplit((0.8, 0.2), seed=42)
機械学習の実験を追跡する
機械学習実験は、関連するすべての機械学習実行の組織と制御の主要な単位です。 実行は、モデル コードの 1 回の実行に対応します。
機械学習の実験追跡では、パラメーター、メトリック、モデル、その他の成果物など、すべての実験とそのコンポーネントが管理されます。 追跡を使用すると、特定の機械学習実験に必要なすべてのコンポーネントを編成できます。 また、保存された実験を使用して過去の結果を簡単に再現することもできます。 Microsoft Fabricでの機械学習の実験の詳細について説明します。
# Build the logistic regression classifier
lr = (
LogisticRegression()
.setMaxIter(max_iter)
.setFeaturesCol("features")
.setLabelCol("labelIdx")
.setWeightCol("weight")
)
ハイパーパラメーターを調整する
ハイパーパラメーターを検索するパラメーターのグリッドを作成します。 次に、クロスエバリュエーター推定器を構築して、CrossValidator
モデルを生成します。
# Build a grid search to select the best values for the training parameters
param_grid = (
ParamGridBuilder()
.addGrid(lr.regParam, [0.03, 0.1])
.addGrid(lr.elasticNetParam, [0.0, 0.1])
.build()
)
if len(LABELS) > 2:
evaluator_cls = MulticlassClassificationEvaluator
evaluator_metrics = ["f1", "accuracy"]
else:
evaluator_cls = BinaryClassificationEvaluator
evaluator_metrics = ["areaUnderROC", "areaUnderPR"]
evaluator = evaluator_cls(labelCol="labelIdx", weightCol="weight")
# Build a cross-evaluator estimator
crossval = CrossValidator(
estimator=lr,
estimatorParamMaps=param_grid,
evaluator=evaluator,
numFolds=k_folds,
collectSubModels=True,
)
モデルを評価する
テスト データセットのモデルを評価して比較できます。 適切にトレーニングされたモデルでは、検証データセットとテスト データセットに対して実行する際に、関連するメトリックに対して高いパフォーマンスを示す必要があります。
def evaluate(model, df):
log_metric = {}
prediction = model.transform(df)
for metric in evaluator_metrics:
value = evaluator.evaluate(prediction, {evaluator.metricName: metric})
log_metric[metric] = value
print(f"{metric}: {value:.4f}")
return prediction, log_metric
MLflow を使用して実験を追跡する
トレーニングと評価のプロセスを開始します。 MLflow を使用して、すべての実験を追跡し、パラメーター、メトリック、モデルをログに記録します。 この情報はすべて、ワークスペースの実験名の下に記録されます。
with mlflow.start_run(run_name="lr"):
models = crossval.fit(train_df)
best_metrics = {k: 0 for k in evaluator_metrics}
best_index = 0
for idx, model in enumerate(models.subModels[0]):
with mlflow.start_run(nested=True, run_name=f"lr_{idx}") as run:
print("\nEvaluating on test data:")
print(f"subModel No. {idx + 1}")
prediction, log_metric = evaluate(model, test_df)
if log_metric[evaluator_metrics[0]] > best_metrics[evaluator_metrics[0]]:
best_metrics = log_metric
best_index = idx
print("log model")
mlflow.spark.log_model(
model,
f"{EXPERIMENT_NAME}-lrmodel",
registered_model_name=f"{EXPERIMENT_NAME}-lrmodel",
dfs_tmpdir="Files/spark",
)
print("log metrics")
mlflow.log_metrics(log_metric)
print("log parameters")
mlflow.log_params(
{
"word2vec_size": word2vec_size,
"min_word_count": min_word_count,
"max_iter": max_iter,
"k_folds": k_folds,
"DATA_FILE": DATA_FILE,
}
)
# Log the best model and its relevant metrics and parameters to the parent run
mlflow.spark.log_model(
models.subModels[0][best_index],
f"{EXPERIMENT_NAME}-lrmodel",
registered_model_name=f"{EXPERIMENT_NAME}-lrmodel",
dfs_tmpdir="Files/spark",
)
mlflow.log_metrics(best_metrics)
mlflow.log_params(
{
"word2vec_size": word2vec_size,
"min_word_count": min_word_count,
"max_iter": max_iter,
"k_folds": k_folds,
"DATA_FILE": DATA_FILE,
}
)
あなたの実験を表示するには:
- 左側のナビゲーションでワークスペースを選択する
- 実験名 (この場合は、sample_aisample-textclassification) を見つけて選択します
手順 5: 予測結果をスコア付けして保存する
Microsoft Fabric を使用すると、ユーザーは PREDICT
スケーラブルな機能を使用して機械学習モデルを運用化できます。 この関数は、任意のコンピューティング エンジンでのバッチ スコアリング (またはバッチ推論) をサポートします。 バッチ予測は、特定のモデルのノートブックまたは項目ページから直接作成できます。 PREDICT とその Fabric での使用方法の詳細については、Microsoft Fabric の PREDICT を使用した機械学習モデルスコアリングに関するページを参照してください。
前の評価結果から、モデル 1 は、Precision-Recall 曲線下面積 (AUPRC) と曲線レシーバ動作特性の下面積 (AUC-ROC) の両方に対して最大のメトリックを持っています。 そのため、予測にはモデル 1 を使用する必要があります。
AUC-ROC 指標は、バイナリ分類器のパフォーマンスを測定するために広く使用されています。 ただし、AUPRC 測定値に基づいて分類子を評価する方が適切になる場合があります。 AUC-ROC グラフは、真陽性率 (TPR) と偽陽性率 (FPR) のトレードオフを視覚化します。 AUPRC 曲線は、精度 (正の予測値または PPV) と再現率 (真陽性率または TPR) を 1 つの視覚化で結合します。
# Load the best model
model_uri = f"models:/{EXPERIMENT_NAME}-lrmodel/1"
loaded_model = mlflow.spark.load_model(model_uri, dfs_tmpdir="Files/spark")
# Verify the loaded model
batch_predictions = loaded_model.transform(test_df)
batch_predictions.show(5)
# Code to save userRecs in the lakehouse
batch_predictions.write.format("delta").mode("overwrite").save(
f"{DATA_FOLDER}/predictions/batch_predictions"
)
# Determine the entire runtime
print(f"Full run cost {int(time.time() - ts)} seconds.")