次の方法で共有


チュートリアル: ML.NET で多クラス分類を使用してサポートの問題を分類する

このサンプル チュートリアルでは、ML.NET を使用して GitHub 問題分類子を作成し、Visual Studio の C# を使用して .NET コンソール アプリケーションを介して GitHub の問題の領域ラベルを分類して予測するモデルをトレーニングする方法を示します。

このチュートリアルでは、次の方法について説明します。

  • データを準備する
  • データを変換する
  • モデルをトレーニングする
  • モデルを評価する
  • トレーニング済みモデルを使用して予測する
  • 読み込まれたモデルを使用したデプロイと予測

このチュートリアルのソース コードは、dotnet/samples リポジトリにあります。

前提 条件

コンソール アプリケーションを作成する

プロジェクトを作成する

  1. "GitHubIssueClassification" と呼ばれる C# コンソール アプリケーション を作成します。 [次へ] を選択します。

  2. 使用するフレームワークとして .NET 7 を選択します。 [作成] を選択します。

  3. Data という名前のディレクトリをプロジェクトに作成して、データ セット ファイルを保存します。

    ソリューション エクスプローラーで、プロジェクトを右クリックし、[追加>新しいフォルダー] を選択します。 「データ」と入力し、Enter押します。

  4. プロジェクトに Models という名前のディレクトリを作成して、モデルを保存します。

    ソリューション エクスプローラーで、プロジェクトを右クリックし、追加>[新しいフォルダー] を選択します。 「モデル」と入力し、Enter押します。

  5. Microsoft.ML NuGet パッケージをインストールします。

    手記

    このサンプルでは、特に明記されていない限り、記載されている最新の安定バージョンの NuGet パッケージを使用します。

    ソリューション エクスプローラーでプロジェクトを右クリックし、[NuGet パッケージの管理]選択します。 パッケージ ソースとして "nuget.org" を選択します。[参照] タブを選択し、「Microsoft.ML」を検索して、[インストール] を選択します。 [Preview Changes] ダイアログで [OK] ボタンを選択し、表示されているパッケージのライセンス条項に同意する場合は、[ライセンス同意] ダイアログで [ 同意する] ボタンを 選択します。

データを準備する

  1. issues_train.tsvissues_test.tsv データ セットをダウンロードし、先に作成した Data フォルダーに保存します。 最初のデータセットは機械学習モデルをトレーニングし、2 番目のデータセットを使用してモデルの精度を評価できます。

  2. ソリューション エクスプローラーで、各 *.tsv ファイルを右クリックし、[プロパティ]選択します。 [詳細設定] で、[出力ディレクトリにコピー] の値を [新しい場合はコピーする] に変更します。

クラスの作成とパスの定義

Program.cs ファイルの先頭に、次の追加の using ディレクティブを追加します。

using Microsoft.ML;
using GitHubIssueClassification;

最近ダウンロードしたファイルへのパスと、MLContextDataView、および 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;

入力データと予測のクラスをいくつか作成します。 新しいクラスをプロジェクトに追加します。

  1. ソリューション エクスプローラーで、プロジェクトを右クリックして、[追加>]、[新しいアイテム] の順に選びます。

  2. [新しい項目の追加] ダイアログ ボックスで、[クラス] 選択し、[名] フィールドを [GitHubIssueData.cs] に変更します。 次に、[の追加]を選択します。

    GitHubIssueData.cs ファイルがコード エディターで開きます。 次の using ディレクティブを GitHubIssueData.csの先頭に追加します。

    using Microsoft.ML.Data;
    
  3. 既存のクラス定義を削除し、次のコードを GitHubIssueData.cs ファイルに追加します。 このコードには、GitHubIssueIssuePredictionの 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) と PredictedLabelColumnName 属性があります。 PredictedLabel は、予測と評価中に使用されます。 評価には、トレーニング データ、予測値、およびモデルを含む入力が使用されます。

    すべての ML.NET 操作は、MLContext クラスで開始されます。 mlContext 初期化すると、モデル作成ワークフロー オブジェクト間で共有できる新しい ML.NET 環境が作成されます。 概念的には、Entity FrameworkDBContext に似ています。

変数を初期化する

複数のトレーニングで反復可能/確定的な結果を得るには、ランダム シード (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を呼び出します。テキスト (TitleDescription) の列を、TitleFeaturizedDescriptionFeaturized呼び出されるそれぞれの数値ベクトルに変換します。 次のコードを使用して、両方の列の特徴量化をパイプラインに追加します。

.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 に追加され、特徴付けされた TitleDescription (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 リポジトリにあります。

次の手順

このチュートリアルでは、次の方法を学習しました。

  • データを準備する
  • データを変換する
  • モデルをトレーニングする
  • モデルを評価する
  • トレーニング済みモデルを使用して予測する
  • 読み込まれたモデルを使用したデプロイと予測

詳細については、次のチュートリアルに進んでください。