共用方式為


教學課程:使用多類別分類搭配 ML.NET 來分類支持問題

演示如何使用 ML.NET 來建立 GitHub 問題分類器,以便在 Visual Studio 中使用 C# 開發的 .NET 主控台應用程式,訓練模型來分類和預測 GitHub 問題的區域標籤。

在本教學課程中,您將瞭解如何:

  • 準備您的資料
  • 轉換數據
  • 訓練模型
  • 評估模型
  • 使用定型模型預測
  • 使用已載入的模型進行部署和預測

您可以在 dotnet/samples 存放庫找到本教學課程的原始程式碼。

先決條件

建立主控台應用程式

建立專案

  1. 建立名為 「GitHubIssueClassification」 的 C# 主控台應用程式。 請選取下一步

  2. 選擇 [.NET 7] 作為要使用的架構。 選取 [建立]

  3. 在專案中建立名為 Data 的目錄,以儲存資料集檔案:

    在 [方案總管]中,以滑鼠右鍵按兩下您的項目,然後選取 [新增>新增資料夾]。 輸入「Data」,然後按 Enter

  4. 在您的專案中建立名為 Models 的目錄,以儲存您的模型:

    在 [方案總管]中,以滑鼠右鍵點擊您的專案,然後選取 [新增>新資料夾]。 輸入 “Models”,然後按 Enter

  5. 安裝 Microsoft.ML NuGet 套件

    注意

    除非另有說明,否則此範例會使用所提及 NuGet 套件的最新穩定版本。

    在 [方案總管] 中,以滑鼠右鍵按下您的項目,然後選取 [管理 NuGet 套件]。 選擇 [nuget.org] 作為套件來源,選取 [瀏覽] 索引標籤,搜尋 Microsoft.ML,然後選取 [安裝]。 選取 [確定] 按鈕,然後在 [預覽變更] 對話方塊上選取 [我接受] 按鈕,在 [授權接受] 對話方塊上如果你同意列出的套件的授權條款。

準備您的資料

  1. 下載 issues_train.tsvissues_test.tsv 數據集,並將其儲存至您先前建立的 Data 資料夾。 第一個數據集會定型機器學習模型,而第二個數據集可用來評估模型的精確度。

  2. 在 [方案總管] 中,以滑鼠右鍵按一下每個 *.tsv 檔案,然後選取 [屬性]。 在 [進階] 中,將 [複製到輸出目錄] 的值變更為 [如果更新則複製]。

建立類別並定義路徑

將下列其他 using 指示詞新增至 Program.cs 檔案頂端:

using Microsoft.ML;
using GitHubIssueClassification;

建立三個全域欄位來保存最近下載之檔案的路徑,以及 MLContextDataViewPredictionEngine的全域變數:

  • _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

    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 Issue ID)。
    • 第二個欄位 Area(訓練的預測)。
    • 第三欄 Title(GitHub 問題標題)是第一個用於預測 Areafeature
    • 第四欄 Description 是用於預測 Area的第二個數據 feature

    IssuePrediction 是模型定型之後用於預測的類別。 它有單一 stringArea) 和 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的區域 GitHub 標籤時,請使用 MapValueToKey() 方法,將 Area 數據行轉換成數值索引鍵類型 Label 數據行(分類演算法接受的格式),並將其新增為新的數據集數據行:

var pipeline = _mlContext.Transforms.Conversion.MapValueToKey(inputColumnName: "Area", outputColumnName: "Label")

接下來,呼叫 mlContext.Transforms.Text.FeaturizeText,它會將每個呼叫 TitleFeaturizedDescriptionFeaturized的文字 (TitleDescription) 數據行轉換成數值向量。 使用以下程式碼,將這兩個欄位的特徵提取附加到管道中:

.Append(_mlContext.Transforms.Text.FeaturizeText(inputColumnName: "Title", outputColumnName: "TitleFeaturized"))
.Append(_mlContext.Transforms.Text.FeaturizeText(inputColumnName: "Description", outputColumnName: "DescriptionFeaturized"))

數據準備的最後一個步驟會使用 Concatenate() 方法,將所有特徵數據行合併到 功能 數據行。 根據預設,學習演算法只會處理 特徵 欄的資料。 使用下列程式代碼將此轉換附加至管線:

.Append(_mlContext.Transforms.Concatenate("Features", "TitleFeaturized", "DescriptionFeaturized"))

接下來,附加 AppendCacheCheckpoint 來將 DataView 快取起來,這樣當您多次使用快取逐一查看數據時,可能會取得更好的效能,如下列程式碼所示:

.AppendCacheCheckpoint(_mlContext);

警告

針對小型/中型數據集使用 AppendCacheCheckpoint 以縮短訓練時間。 請勿在處理非常大的數據集時使用它(移除 .AppendCacheCheckpoint())。

ProcessData 方法的結尾處返回管線。

return pipeline;

這個步驟負責進行前置處理與特徵化。 使用 ML.NET 中提供的其他元件,即可為您的模型提供更好的結果。

建置和定型模型

將下列呼叫新增至 BuildAndTrainModel方法,做為呼叫 ProcessData() 方法之後的下一行:

var trainingPipeline = BuildAndTrainModel(_trainingDataView, pipeline);

BuildAndTrainModel 方法會執行下列工作:

  • 建立訓練算法類別。
  • 訓練模型。
  • 根據訓練數據預測區域。
  • 傳回模型。

使用下列程序代碼,在宣告 ProcessData() 方法之後,建立 BuildAndTrainModel 方法:

IEstimator<ITransformer> BuildAndTrainModel(IDataView trainingDataView, IEstimator<ITransformer> pipeline)
{

}

關於分類工作

分類是一項機器學習工作,會使用數據來判斷項目或數據列的類別、型別或項目,而且通常是下列其中之一類型:

  • 二進位:A 或 B。
  • 多類別:可使用單一模型預測的多個類別。

針對這種類型的問題,請使用多類別分類學習演算法,因為您的問題類別預測可以是多個類別之一(多類別),而不只是兩個(二進位)。

將下列程式代碼新增為 BuildAndTrainModel()中的第一行程式代碼,將機器學習演算法附加至資料轉換定義:

var trainingPipeline = pipeline.Append(_mlContext.MulticlassClassification.Trainers.SdcaMaximumEntropy("Label", "Features"))
        .Append(_mlContext.Transforms.Conversion.MapKeyToValue("PredictedLabel"));

SdcaMaximumEntropy 是您的多類別分類訓練演算法。 這會附加至 pipeline,並接受特徵化 TitleDescriptionFeatures)和 Label 輸入參數,以從歷史數據中學習。

訓練模型

將模型擬合到 splitTrainSet 數據,然後在 BuildAndTrainModel() 方法中新增下列程式碼作為下一行,以傳回訓練好的模型:

_trainedModel = trainingPipeline.Fit(trainingDataView);

Fit()方法會藉由轉換數據集並進行訓練來訓練模型。

PredictionEngine 是一個方便的 API,它允許您輸入單筆資料並進行預測。 將此新增為 BuildAndTrainModel() 方法中的下一行:

_predEngine = _mlContext.Model.CreatePredictionEngine<GitHubIssue, IssuePrediction>(_trainedModel);

使用定型模型預測

藉由建立 GitHubIssue的實例,新增 GitHub 問題,以在 Predict 方法中測試定型模型的預測:

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() 函式,對單一數據列進行預測:

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 物件,其中包含多類別分類評估工具計算的整體計量。 若要顯示計量以判斷模型的品質,您需要先取得它們。 請注意,使用機器學習 _trainedModel 全域變數的 Transform() 方法(ITransformer),來輸入特徵並傳回預測。 請將下列程式碼新增至 Evaluate 方法中,作為下一行程式碼:

var testMetrics = _mlContext.MulticlassClassification.Evaluate(_trainedModel.Transform(testDataView));

下列計量會針對多類別分類進行評估:

  • 微精確度 - 每個樣本類別組都同樣有助於精確度計量。 您希望 Micro Accuracy 盡可能接近 1。
  • 宏觀準確性 - 每個類別都對準確性指標貢獻相等。 少數類別與較大的類別被賦予相等的權重。 您希望整體準確率盡可能接近 1。
  • 記錄遺失 - 請參閱 記錄遺失。 您希望對數損失(Log-loss)盡可能接近零。
  • 記錄損失縮減 - 範圍從 [-inf, 1.00],其中 1.00 是完美的預測,0 表示平均預測。 您希望對數損失的降低盡可能接近一。

顯示模型驗證的計量

使用下列程式代碼來顯示計量、共享結果,然後對其採取行動:

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 方法之後建立 PredictIssue 方法(在 SaveModelAsFile 方法之前:

void PredictIssue()
{

}

PredictIssue 方法會執行下列工作:

  • 載入儲存的模型。
  • 建立一個測試數據項。
  • 根據測試數據預測區域。
  • 將測試數據和預測進行結合以便報告。
  • 顯示預測的結果。

將下列程式代碼新增至 PredictIssue 方法,將儲存的模型載入您的應用程式:

ITransformer loadedModel = _mlContext.Model.Load(_modelPath, out var modelInputSchema);

藉由建立 GitHubIssue的實例,新增 GitHub 問題,以在 Predict 方法中測試定型模型的預測:

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 不是线程安全。 在單個線程或原型環境中可以使用。 若要改善生產環境中的效能和線程安全性,請使用 PredictionEnginePool 服務,以建立 PredictionEngine 對象的 ObjectPool,以在整個應用程式中使用。 請參閱本指南,以瞭解如何在 ASP.NET Core Web API中 使用

注意

PredictionEnginePool 服務擴展目前處於預覽階段。

使用 PredictionEngine 預測區域 GitHub 標籤,方法是將下列程式代碼新增至 PredictIssue 方法以進行預測:

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 問題的區域標籤。 您可以在 dotnet/samples 存放庫找到本教學課程的原始程式碼。

後續步驟

在本教學課程中,您已瞭解如何:

  • 準備您的數據
  • 轉換數據
  • 訓練模型
  • 評估模型
  • 使用定型模型預測
  • 使用載入的模型部署和預測

繼續下一個教學課程以更深入了解。