チュートリアル: ML.NET で多クラス分類を使用してサポートの問題を分類する
このサンプル チュートリアルでは、ML.NET を使用して GitHub 問題分類子を作成し、Visual Studio の C# を使用して .NET コンソール アプリケーションを介して GitHub の問題の領域ラベルを分類して予測するモデルをトレーニングする方法を示します。
このチュートリアルでは、次の方法について説明します。
- データを準備する
- データを変換する
- モデルをトレーニングする
- モデルを評価する
- トレーニング済みモデルを使用して予測する
- 読み込まれたモデルを使用したデプロイと予測
このチュートリアルのソース コードは、dotnet/samples リポジトリにあります。
前提 条件
- インストールされた「.NET デスクトップ開発」ワークロードを備えた Visual Studio 2022 。
- GitHub は、トレーニング タブ区切りファイル (issues_train.tsv)を発行します。
- GitHub の問題のテスト タブ区切りのファイル (issues_test.tsv)。
コンソール アプリケーションを作成する
プロジェクトを作成する
"GitHubIssueClassification" と呼ばれる C# コンソール アプリケーション を作成します。 [次へ] を選択します。
使用するフレームワークとして .NET 7 を選択します。 [作成] を選択します。
Data という名前のディレクトリをプロジェクトに作成して、データ セット ファイルを保存します。
ソリューション エクスプローラーで、プロジェクトを右クリックし、[追加>新しいフォルダー] を選択します。 「データ」と入力し、Enter
押します。 プロジェクトに Models という名前のディレクトリを作成して、モデルを保存します。
ソリューション エクスプローラーで、プロジェクトを右クリックし、追加>[新しいフォルダー] を選択します。 「モデル」と入力し、Enter
押します。 Microsoft.ML NuGet パッケージをインストールします。
手記
このサンプルでは、特に明記されていない限り、記載されている最新の安定バージョンの NuGet パッケージを使用します。
ソリューション エクスプローラーでプロジェクトを右クリックし、[NuGet パッケージの管理]
選択します。 パッケージ ソースとして "nuget.org" を選択します。[参照] タブを選択し、「Microsoft.ML」を検索して、[インストール] を選択します。 [ Preview Changes ] ダイアログで [OK ] ボタンを選択し、表示されているパッケージのライセンス条項に同意する場合は、[ライセンス同意 ] ダイアログで [ 同意する] ボタンを選択します。
データを準備する
issues_train.tsv と issues_test.tsv データ セットをダウンロードし、先に作成した Data フォルダーに保存します。 最初のデータセットは機械学習モデルをトレーニングし、2 番目のデータセットを使用してモデルの精度を評価できます。
ソリューション エクスプローラーで、各 *.tsv ファイルを右クリックし、[プロパティ]
選択します。 [詳細設定] で、[出力ディレクトリにコピー] の値を [新しい場合はコピーする] に変更します。
クラスの作成とパスの定義
Program.cs ファイルの先頭に、次の追加の using
ディレクティブを追加します。
using Microsoft.ML;
using GitHubIssueClassification;
最近ダウンロードしたファイルへのパスと、MLContext
、DataView
、および PredictionEngine
のグローバル変数を保持する 3 つのグローバル フィールドを作成します。
_trainDataPath
には、モデルのトレーニングに使用されるデータセットへのパスがあります。_testDataPath
には、モデルの評価に使用されるデータセットへのパスがあります。_modelPath
には、トレーニング済みのモデルが保存されるパスがあります。_mlContext
は、処理コンテキストを提供する MLContext です。_trainingDataView
は、トレーニング データセットの処理に使用される IDataView です。_predEngine
は、単一の予測に使用される PredictionEngine<TSrc,TDst> です。
using
ディレクティブのすぐ下の行に次のコードを追加して、それらのパスとその他の変数を指定します。
string _appPath = Path.GetDirectoryName(Environment.GetCommandLineArgs()[0]) ?? ".";
string _trainDataPath = Path.Combine(_appPath, "..", "..", "..", "Data", "issues_train.tsv");
string _testDataPath = Path.Combine(_appPath, "..", "..", "..", "Data", "issues_test.tsv");
string _modelPath = Path.Combine(_appPath, "..", "..", "..", "Models", "model.zip");
MLContext _mlContext;
PredictionEngine<GitHubIssue, IssuePrediction> _predEngine;
ITransformer _trainedModel;
IDataView _trainingDataView;
入力データと予測のクラスをいくつか作成します。 新しいクラスをプロジェクトに追加します。
ソリューション エクスプローラーで、プロジェクトを右クリックして、[追加>]、[新しいアイテム] の順に選びます。
[
新しい項目の追加 ] ダイアログ ボックスで、[クラス]選択し、[ 名] フィールドを [GitHubIssueData.cs ] に変更します。 次に、[の追加]を選択します。GitHubIssueData.cs ファイルがコード エディターで開きます。 次の
using
ディレクティブを GitHubIssueData.csの先頭に追加します。using Microsoft.ML.Data;
既存のクラス定義を削除し、次のコードを GitHubIssueData.cs ファイルに追加します。 このコードには、
GitHubIssue
とIssuePrediction
の 2 つのクラスがあります。public class GitHubIssue { [LoadColumn(0)] public string? ID { get; set; } [LoadColumn(1)] public string? Area { get; set; } [LoadColumn(2)] public required string Title { get; set; } [LoadColumn(3)] public required string Description { get; set; } } public class IssuePrediction { [ColumnName("PredictedLabel")] public string? Area; }
label
は予測する列です。 識別されたFeatures
は、ラベルを予測するためにモデルに与える入力です。LoadColumnAttribute を使用して、データ セット内のソース列のインデックスを指定します。
GitHubIssue
は入力データセット クラスであり、次の String フィールドがあります。- 最初の列
ID
(GitHub の問題 ID)。 - 2 番目の列
Area
(トレーニングの予測)。 - 3 番目の列
Title
(GitHub 問題のタイトル) は、Area
の予測に使用される最初のfeature
です。 - 4 列目の
Description
は、Area
の予測に使用される 2 番目のfeature
です。
IssuePrediction
は、モデルのトレーニング後に予測に使用されるクラスです。 1 つのstring
(Area
) とPredictedLabel
ColumnName
属性があります。PredictedLabel
は、予測と評価中に使用されます。 評価には、トレーニング データ、予測値、およびモデルを含む入力が使用されます。すべての ML.NET 操作は、MLContext クラスで開始されます。
mlContext
初期化すると、モデル作成ワークフロー オブジェクト間で共有できる新しい ML.NET 環境が作成されます。 概念的には、Entity Framework
でDBContext
に似ています。- 最初の列
変数を初期化する
複数のトレーニングで反復可能/確定的な結果を得るには、ランダム シード (seed: 0
) を使用して、MLContext
の新しいインスタンスを使用して、_mlContext
グローバル変数を初期化します。 Console.WriteLine("Hello World!")
行を次のコードに置き換えます。
_mlContext = new MLContext(seed: 0);
データを読み込む
ML.NET では、IDataView インターフェイス を使用して、数値またはテキストの表形式データを柔軟かつ効率的に記述できます。 IDataView
は、テキスト ファイルまたはリアルタイム (SQL データベースやログ ファイルなど) を読み込むことができます。
パイプラインに使用するために _trainingDataView
グローバル変数を初期化して読み込むには、mlContext
初期化の後に次のコードを追加します。
_trainingDataView = _mlContext.Data.LoadFromTextFile<GitHubIssue>(_trainDataPath,hasHeader: true);
LoadFromTextFile() は、データ スキーマを定義し、ファイル内を読み取ります。 データ パス変数を受け取り、IDataView
を返します。
LoadFromTextFile()
メソッドを呼び出した後、次のコードを追加します。
var pipeline = ProcessData();
ProcessData
メソッドは、次のタスクを実行します。
- データを抽出して変換します。
- 処理パイプラインを返します。
次のコードを使用して、Program.cs ファイルの下部に ProcessData
メソッドを作成します。
IEstimator<ITransformer> ProcessData()
{
}
特徴を抽出してデータを変換する
GitHubIssue
の Area GitHub ラベルを予測する場合は、MapValueToKey() メソッドを使用して、Area
列を数値キー型 Label
列 (分類アルゴリズムで受け入れられる形式) に変換し、新しいデータセット列として追加します。
var pipeline = _mlContext.Transforms.Conversion.MapValueToKey(inputColumnName: "Area", outputColumnName: "Label")
次に、mlContext.Transforms.Text.FeaturizeText
を呼び出します。テキスト (Title
と Description
) の列を、TitleFeaturized
と DescriptionFeaturized
呼び出されるそれぞれの数値ベクトルに変換します。 次のコードを使用して、両方の列の特徴量化をパイプラインに追加します。
.Append(_mlContext.Transforms.Text.FeaturizeText(inputColumnName: "Title", outputColumnName: "TitleFeaturized"))
.Append(_mlContext.Transforms.Text.FeaturizeText(inputColumnName: "Description", outputColumnName: "DescriptionFeaturized"))
データ準備の最後の手順では、Concatenate() メソッドを使用して、すべての特徴列を Features 列に結合します。 既定では、学習アルゴリズムは Features 列の特徴のみを処理します。 次のコードを使用して、この変換をパイプラインに追加します。
.Append(_mlContext.Transforms.Concatenate("Features", "TitleFeaturized", "DescriptionFeaturized"))
次に、DataView をキャッシュする AppendCacheCheckpoint を追加して、キャッシュを使用してデータを複数回反復処理すると、次のコードのようにパフォーマンスが向上する可能性があります。
.AppendCacheCheckpoint(_mlContext);
警告
トレーニング時間を短縮するには、小/中規模のデータセットに AppendCacheCheckpoint を使用します。 非常に大きなデータセットを処理する際には、.AppendCacheCheckpoint()を使用しないでください(削除してください)。
ProcessData
メソッドの末尾にあるパイプラインを返します。
return pipeline;
この手順では、前処理/特徴付け処理を処理します。 ML.NET で使用できる追加のコンポーネントを使用すると、モデルでより優れた結果を得ることができます。
モデルを構築してトレーニングする
ProcessData()
メソッドの呼び出しの後の次の行として、BuildAndTrainModel
メソッドに次の呼び出しを追加します。
var trainingPipeline = BuildAndTrainModel(_trainingDataView, pipeline);
BuildAndTrainModel
メソッドは、次のタスクを実行します。
- トレーニング アルゴリズム クラスを作成します。
- モデルをトレーニングします。
- トレーニング データに基づいて領域を予測します。
- モデルを返します。
次のコードを使用して、ProcessData()
メソッドの宣言の直後に、BuildAndTrainModel
メソッドを作成します。
IEstimator<ITransformer> BuildAndTrainModel(IDataView trainingDataView, IEstimator<ITransformer> pipeline)
{
}
分類タスクについて
分類は、データを使用して項目またはデータ行のカテゴリ、型、またはクラスを決定する機械学習タスクであり、多くの場合、次のいずれかの種類です。
- バイナリ: A または B。
- 多クラス: 1 つのモデルを使用して予測できる複数のカテゴリ。
この種の問題では、問題カテゴリの予測は 2 つ (バイナリ) ではなく複数のカテゴリ (多クラス) の 1 つになる可能性があるため、多クラス分類学習アルゴリズムを使用します。
BuildAndTrainModel()
のコードの最初の行として次のコードを追加して、機械学習アルゴリズムをデータ変換定義に追加します。
var trainingPipeline = pipeline.Append(_mlContext.MulticlassClassification.Trainers.SdcaMaximumEntropy("Label", "Features"))
.Append(_mlContext.Transforms.Conversion.MapKeyToValue("PredictedLabel"));
SdcaMaximumEntropy は、多クラス分類トレーニング アルゴリズムです。 これは pipeline
に追加され、特徴付けされた Title
と Description
(Features
) と、履歴データから学習する Label
入力パラメーターを受け取ります。
モデルをトレーニングする
モデルを splitTrainSet
データに合わせ、BuildAndTrainModel()
メソッドの次のコード行として次のコード行を追加して、トレーニング済みのモデルを返します。
_trainedModel = trainingPipeline.Fit(trainingDataView);
Fit()
メソッドは、データセットを変換し、トレーニングを適用することで、モデルをトレーニングします。
PredictionEngine は、データの単一インスタンスに渡して予測を実行できる便利な API です。 これを BuildAndTrainModel()
メソッドの次の行として追加します。
_predEngine = _mlContext.Model.CreatePredictionEngine<GitHubIssue, IssuePrediction>(_trainedModel);
トレーニング済みモデルを使用して予測する
GitHubIssue
のインスタンスを作成して、Predict
メソッドでトレーニング済みのモデルの予測をテストする GitHub の問題を追加します。
GitHubIssue issue = new GitHubIssue() {
Title = "WebSockets communication is slow in my machine",
Description = "The WebSockets communication used under the covers by SignalR looks like is going slow in my development machine.."
};
Predict() 関数を使用して、1 行のデータに対して予測を行います。
var prediction = _predEngine.Predict(issue);
モデルの使用: 予測結果
結果を共有し、それに応じてアクションを実行するために、GitHubIssue
と対応する Area
ラベル予測を表示します。 次の Console.WriteLine() コードを使用して、結果の表示を作成します。
Console.WriteLine($"=============== Single Prediction just-trained-model - Result: {prediction.Area} ===============");
評価に使用するようにトレーニングされたモデルを返す
BuildAndTrainModel
メソッドの末尾にあるモデルを返します。
return trainingPipeline;
モデルを評価する
モデルを作成してトレーニングしたので、品質保証と検証のために別のデータセットでモデルを評価する必要があります。 Evaluate
メソッドでは、BuildAndTrainModel
で作成されたモデルが渡されて評価されます。 次のコードのように、BuildAndTrainModel
の直後に Evaluate
メソッドを作成します。
void Evaluate(DataViewSchema trainingDataViewSchema)
{
}
Evaluate
メソッドは、次のタスクを実行します。
- テスト データセットを読み込みます。
- 多クラス エバリュエーターを作成します。
- モデルを評価し、メトリックを作成します。
- メトリックを表示します。
次のコードを使用して、BuildAndTrainModel
メソッド呼び出しのすぐ下にある新しいメソッドへの呼び出しを追加します。
Evaluate(_trainingDataView.Schema);
トレーニング データセットで前に行ったように、次のコードを Evaluate
メソッドに追加してテスト データセットを読み込みます。
var testDataView = _mlContext.Data.LoadFromTextFile<GitHubIssue>(_testDataPath,hasHeader: true);
Evaluate() メソッドは、指定されたデータセットを使用してモデルの品質メトリックを計算します。 多クラス分類エバリュエーターによって計算された全体的なメトリックを含む MulticlassClassificationMetrics オブジェクトを返します。
メトリックを表示してモデルの品質を判断するには、まずそれらを取得する必要があります。
機械学習の Transform() メソッド _trainedModel
グローバル変数 (ITransformer) を使用して特徴を入力し、予測を返していることに注意してください。 次の行として、Evaluate
メソッドに次のコードを追加します。
var testMetrics = _mlContext.MulticlassClassification.Evaluate(_trainedModel.Transform(testDataView));
多クラス分類では、次のメトリックが評価されます。
- マイクロ精度 - すべてのサンプル クラス ペアは、精度メトリックに等しく寄与します。 マイクロ精度を可能な限り 1 に近づけるようにします。
- マクロの精度 - すべてのクラスが精度メトリックに等しく寄与します。 少数派クラスには、より大きなクラスと同じ重みが与えられます。 マクロの精度を可能な限り 1 に近づけます。
- 対数損失: 対数損失に関するページを参照してください。 ログ損失を可能な限りゼロに近づけます。
- 対数損失の減少 - [-inf, 1.00] の範囲です。1.00 は完全な予測であり、0 は平均予測を示します。 ログ損失の削減を可能な限り 1 に近づけるようにします。
モデル検証のメトリックを表示する
次のコードを使用して、メトリックを表示し、結果を共有し、それらに対処します。
Console.WriteLine($"*************************************************************************************************************");
Console.WriteLine($"* Metrics for Multi-class Classification model - Test Data ");
Console.WriteLine($"*------------------------------------------------------------------------------------------------------------");
Console.WriteLine($"* MicroAccuracy: {testMetrics.MicroAccuracy:0.###}");
Console.WriteLine($"* MacroAccuracy: {testMetrics.MacroAccuracy:0.###}");
Console.WriteLine($"* LogLoss: {testMetrics.LogLoss:#.###}");
Console.WriteLine($"* LogLossReduction: {testMetrics.LogLossReduction:#.###}");
Console.WriteLine($"*************************************************************************************************************");
モデルをファイルに保存する
モデルに問題がなければ、後でまたは別のアプリケーションで予測を行うためにファイルに保存します。 Evaluate
メソッドに次のコードを追加します。
SaveModelAsFile(_mlContext, trainingDataViewSchema, _trainedModel);
Evaluate
メソッドの下に SaveModelAsFile
メソッドを作成します。
void SaveModelAsFile(MLContext mlContext,DataViewSchema trainingDataViewSchema, ITransformer model)
{
}
SaveModelAsFile
メソッドに次のコードを追加します。 このコードでは、Save
メソッドを使用して、トレーニング済みのモデルをシリアル化し、zip ファイルとして格納します。
mlContext.Model.Save(model, trainingDataViewSchema, _modelPath);
モデルを使用したデプロイと予測
次のコードを使用して、Evaluate
メソッド呼び出しのすぐ下にある新しいメソッドへの呼び出しを追加します。
PredictIssue();
次のコードを使用して、Evaluate
メソッドの直後 (および SaveModelAsFile
メソッドの直前) に、PredictIssue
メソッドを作成します。
void PredictIssue()
{
}
PredictIssue
メソッドは、次のタスクを実行します。
- 保存したモデルを読み込みます。
- テスト データの 1 つの問題を作成します。
- テスト データに基づいて面積を予測します。
- レポート用のテスト データと予測を組み合わせます。
- 予測された結果を表示します。
PredictIssue
メソッドに次のコードを追加して、保存したモデルをアプリケーションに読み込みます。
ITransformer loadedModel = _mlContext.Model.Load(_modelPath, out var modelInputSchema);
GitHubIssue
のインスタンスを作成して、Predict
メソッドでトレーニング済みのモデルの予測をテストする GitHub の問題を追加します。
GitHubIssue singleIssue = new GitHubIssue() { Title = "Entity Framework crashes", Description = "When connecting to the database, EF is crashing" };
前に行ったように、次のコードを使用して PredictionEngine
インスタンスを作成します。
_predEngine = _mlContext.Model.CreatePredictionEngine<GitHubIssue, IssuePrediction>(loadedModel);
PredictionEngine は、データの単一インスタンスに対して予測を実行できる便利な API です。 PredictionEngine
はスレッド セーフではありません。 シングルスレッド環境またはプロトタイプ環境で使用することは許容されます。 運用環境でのパフォーマンスとスレッド セーフを向上させるには、アプリケーション全体で使用する PredictionEngine
オブジェクトの ObjectPool
を作成する PredictionEnginePool
サービスを使用します。 ASP.NET Core Web API で PredictionEnginePool
を使用する方法については、こちらのガイドを参照してください。
手記
PredictionEnginePool
サービス拡張機能は現在プレビュー段階です。
PredictionEngine
を使用して、予測の PredictIssue
メソッドに次のコードを追加して、Area GitHub ラベルを予測します。
var prediction = _predEngine.Predict(singleIssue);
読み込まれたモデルを予測に使用する
問題を分類し、それに応じて対処するために、Area
を表示します。 次の Console.WriteLine() コードを使用して、結果の表示を作成します。
Console.WriteLine($"=============== Single Prediction - Result: {prediction.Area} ===============");
結果
結果は次のようになります。 パイプラインが処理すると、メッセージが表示されます。 警告が表示されたり、メッセージが処理されたりすることがあります。 これらのメッセージは、わかりやすくするために、次の結果から削除されています。
=============== Single Prediction just-trained-model - Result: area-System.Net ===============
*************************************************************************************************************
* Metrics for Multi-class Classification model - Test Data
*------------------------------------------------------------------------------------------------------------
* MicroAccuracy: 0.738
* MacroAccuracy: 0.668
* LogLoss: .919
* LogLossReduction: .643
*************************************************************************************************************
=============== Single Prediction - Result: area-System.Data ===============
おめでとうございます! これで、GitHub の問題の Area ラベルを分類して予測するための機械学習モデルが正常に構築されました。 このチュートリアルのソース コードは、dotnet/samples リポジトリにあります。
次の手順
このチュートリアルでは、次の方法を学習しました。
- データを準備する
- データを変換する
- モデルをトレーニングする
- モデルを評価する
- トレーニング済みモデルを使用して予測する
- 読み込まれたモデルを使用したデプロイと予測
詳細については、次のチュートリアルに進んでください。
.NET