Share via


教學課程:在 ML.NET 中使用二元分類來分析網站批註的情感

本教學課程示範如何建立 .NET Core 主控台應用程式,來分類網站評論中的情感並採取適當動作。 二進位情感分類器會在 Visual Studio 2022 中使用 C#。

在本教學課程中,您會了解如何:

  • 建立主控台應用程式
  • 準備資料
  • 載入資料
  • 建置和定型模型
  • 評估模型
  • 使用模型來進行預測
  • 查看結果

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

必要條件

建立主控台應用程式

  1. 建立名為 「SentimentAnalysis」 的 C# 主控台應用程式 。 按 [下一步] 按鈕。

  2. 選擇 .NET 6 作為要使用的架構。 按一下 [ 建立 ] 按鈕。

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

  4. 安裝「Microsoft.ML NuGet 套件」

    注意

    除非另有說明,否則此樣本會使用所提及 NuGet 封裝的最新穩定版本。

    在 [方案總管] 中,於您的專案上按一下滑鼠右鍵,然後選取 [管理 NuGet 套件]。 選擇 [nuget.org] 作為套件來源,然後選取 [ 流覽] 索引標籤。搜尋 Microsoft.ML,選取您想要的套件,然後選取 [ 安裝 ] 按鈕。 同意您所選套件的授權條款,以繼續進行安裝。

準備您的資料

注意

本教學課程的資料集來自「使用深層功能從群組到個別標籤」、Kotzias 等。鋁。 KDD 2015,並裝載於「UCI Machine Learning Repository (UCI 機器學習存放庫)」- Dua, D. and Karra Taniskidou, E. (2017)。 「UCI Machine Learning Repository (UCI 機器學習存放庫)」[http://archive.ics.uci.edu/ml]。 Irvine, CA: University of California, School of Information and Computer Science.

  1. 下載並解壓縮 UCI 情感標記句子資料集 ZIP 檔案

  2. yelp_labelled.txt 檔案複製到您所建立的 Data 目錄。

  3. 在 [方案總管] 中,以滑鼠右鍵按一下 yelp_labeled.txt 檔案,並選取 [內容]。 在 [進階] 底下,將 [複製到輸出目錄] 的值變更為 [有更新時才複製]。

建立類別及定義路徑

  1. Program.cs 檔案頂端新增下列額外的 using 陳述式:

    using Microsoft.ML;
    using Microsoft.ML.Data;
    using SentimentAnalysis;
    using static Microsoft.ML.DataOperationsCatalog;
    
  2. 將下列程式碼新增至 語句正下方 using 的行,以建立欄位來保存最近下載的資料集檔案路徑:

    string _dataPath = Path.Combine(Environment.CurrentDirectory, "Data", "yelp_labelled.txt");
    
  3. 接下來,為輸入資料和預測建立類別。 將新類別新增至專案:

    • 在 [方案總管] 中,以滑鼠右鍵按一下專案,然後選取 [新增]>[新項目]

    • 在 [新增項目] 對話方塊中,選取 [類別],然後將 [名稱] 欄位變更為 SentimentData.cs。 接著,選取 [新增] 按鈕。

  4. SentimentData.cs 檔案隨即在程式碼編輯器中開啟。 將以下 using 陳述式新增至 SentimentData.cs 頂端:

    using Microsoft.ML.Data;
    
  5. 移除現有的類別定義,然後將下列程式碼 (具有 SentimentDataSentimentPrediction 這兩個類別) 新增至 SentimentData.cs 檔案:

    public class SentimentData
    {
        [LoadColumn(0)]
        public string? SentimentText;
    
        [LoadColumn(1), ColumnName("Label")]
        public bool Sentiment;
    }
    
    public class SentimentPrediction : SentimentData
    {
    
        [ColumnName("PredictedLabel")]
        public bool Prediction { get; set; }
    
        public float Probability { get; set; }
    
        public float Score { get; set; }
    }
    

如何準備資料

輸入資料集類別 SentimentData 具有使用者評論 (SentimentText) 的 string,以及代表情感的 bool (Sentiment) 值 1 (正面) 或 0 (負面)。 這兩個欄位都有 LoadColumn 附加屬性,其描述每個欄位的資料檔案順序。 此外,Sentiment 屬性具有 ColumnName 屬性來將它指定為 Label 欄位。 下列範例檔案沒有標頭資料列,且看起來像這樣:

SentimentText 情感 (標籤)
女服務生的服務速度有點慢。 0
不夠酥脆。 0
哇...喜歡這個地方。 1
服務很迅速。 1

SentimentPrediction 是在模型定型後所使用的預測類別。 它繼承自 SentimentData,以便輸入 SentimentText 可以和輸出預測一起顯示。 Prediction 布林值是在提供新輸入 SentimentText 時,模型預測的值。

輸出類別 SentimentPrediction 包含模型計算的兩個其他屬性:Score - 模型計算的原始分數,和 Probability - 針對文字具有正面情感之可能性所校正的分數。

本教學課程中最重要的屬性是 Prediction

載入資料

ML.NET 中的資料會以 IDataView 介面表示。 IDataView 是彈性且有效率的表格式資料描述方式 (數值和文字)。 資料可以從文字或即時 (例如 SQL 資料庫或記錄檔) 載入至 IDataView 物件。

MLContext 類別是所有 ML.NET 作業的起點。 將 mlContext 初始化會建立新的 ML.NET 環境,可在模型建立工作流程物件間共用。 就概念而言,類似於 Entity Framework 中的 DBContext

您可以準備資料,然後載入資料:

  1. 以下列程式碼取代 行 Console.WriteLine("Hello World!") ,以宣告和初始化 mlCoNtext 變數:

    MLContext mlContext = new MLContext();
    
  2. 新增下列專案作為下一行程式碼:

    TrainTestData splitDataView = LoadData(mlContext);
    
  3. 使用下列程式碼在 Program.cs 檔案底部建立 LoadData() 方法:

    TrainTestData LoadData(MLContext mlContext)
    {
    
    }
    

    LoadData() 方法會執行下列工作:

    • 載入資料。
    • 將載入的資料集分割為定型與測試資料集。
    • 傳回分割的定型與測試資料集。
  4. 將下列程式碼新增為 LoadData() 方法的第一行:

    IDataView dataView = mlContext.Data.LoadFromTextFile<SentimentData>(_dataPath, hasHeader: false);
    

    LoadFromTextFile () 方法會定義資料架構,並在檔案中讀取。 會接受資料路徑變數然後傳回 IDataView

分割資料集以進行模型定型與測試

準備模型時,您可以使用部分資料集來定型它,並使用部分資料集來測試模型的準確度。

  1. 若要將載入的資料分割成所需的資料集,請將下列程式碼加入為 LoadData() 方法中的下一行:

    TrainTestData splitDataView = mlContext.Data.TrainTestSplit(dataView, testFraction: 0.2);
    

    先前的程式碼會使用 TrainTestSplit () 方法,將載入的資料集分割成定型和測試資料集,並在 類別中 DataOperationsCatalog.TrainTestData 傳回它們。 您可以使用 testFraction 參數來指定資料的測試集百分比。 預設值是 10%,但您在本例中會使用 20% 以評估更多資料。

  2. LoadData() 方法的結尾傳回 splitDataView

    return splitDataView;
    

建置和定型模型

  1. 將下列呼叫新增至 BuildAndTrainModel 方法的呼叫 LoadData 下方的方法:

    ITransformer model = BuildAndTrainModel(mlContext, splitDataView.TrainSet);
    

    BuildAndTrainModel() 方法會執行下列工作:

    • 擷取並轉換資料。
    • 將模型定型。
    • 根據測試資料預測情感。
    • 傳回模型。
  2. 使用下列程式碼,在 BuildAndTrainModel() 方法下方 LoadData() 建立 方法:

    ITransformer BuildAndTrainModel(MLContext mlContext, IDataView splitTrainSet)
    {
    
    }
    

擷取並轉換資料

  1. 呼叫 FeaturizeText 作為下一行程式碼:

    var estimator = mlContext.Transforms.Text.FeaturizeText(outputColumnName: "Features", inputColumnName: nameof(SentimentData.SentimentText))
    

    上述程式碼中的 FeaturizeText() 方法會將文字資料行 (SentimentText) 轉換成機器學習演算法所使用的數值索引鍵類型 Features 資料行,並將它新增為新的資料集資料行:

    SentimentText 情感 功能
    女服務生的服務速度有點慢。 0 [0.76, 0.65, 0.44, …]
    不夠酥脆。 0 [0.98, 0.43, 0.54, …]
    哇...喜歡這個地方。 1 [0.35, 0.73, 0.46, …]
    服務很迅速。 1 [0.39, 0, 0.75, …]

新增學習演算法

此應用程式使用分類演算法來分類多個項目或資料列。 應用程式會將網站評論分類為正面或負面,因此請使用二元分類工作。

透過將下列內容新增為 BuildAndTrainModel() 中的下一行程式碼,將機器學習工作附加到資料轉換定義:

.Append(mlContext.BinaryClassification.Trainers.SdcaLogisticRegression(labelColumnName: "Label", featureColumnName: "Features"));

SdcaLogisticRegressionBinaryTrainer 是您的分類定型演算法。 這會附加到 estimator,並接受特徵化 SentimentText (Features) 和 Label 輸入參數,以從歷史資料學習。

將模型定型

將下列內容新增為 BuildAndTrainModel() 方法中的下一行程式碼,調整模型為合適於 splitTrainSet 資料並傳回已定型模型:

Console.WriteLine("=============== Create and Train the Model ===============");
var model = estimator.Fit(splitTrainSet);
Console.WriteLine("=============== End of training ===============");
Console.WriteLine();

Fit() 方法透過轉換資料集和套用定型來定型模型。

傳回經訓練以供評估使用的模型

BuildAndTrainModel() 方法的結尾傳回模型:

return model;

評估模型

定型模型之後,請使用測試資料來驗證模型的效能。

  1. BuildAndTrainModel() 之後,使用下列程式碼建立 Evaluate() 方法:

    void Evaluate(MLContext mlContext, ITransformer model, IDataView splitTestSet)
    {
    
    }
    

    Evaluate() 方法會執行下列工作:

    • 載入測試資料集。
    • 建立 BinaryClassification 評估工具。
    • 評估模型並建立計量。
    • 顯示計量。
  2. 使用下列程式碼,將呼叫新增至方法呼叫下方 BuildAndTrainModel 的新方法:

    Evaluate(mlContext, model, splitDataView.TestSet);
    
  3. 將下列程式碼新增至 Evaluate() 以轉換 splitTestSet 資料:

    Console.WriteLine("=============== Evaluating Model accuracy with Test data===============");
    IDataView predictions = model.Transform(splitTestSet);
    

    之前的程式碼使用 Transform() 方法會對測試資料集多個所提供的輸入資料列進行預測。

  4. 將下列內容新增為 Evaluate() 方法中的下一行程式碼來評估模型:

    CalibratedBinaryClassificationMetrics metrics = mlContext.BinaryClassification.Evaluate(predictions, "Label");
    

在您設定好預測 (predictions) 後,Evaluate() 方法會評估模型,將預測值與測試資料集中的實際 Labels 進行比較,並傳回與模型執行情況相關的 CalibratedBinaryClassificationMetrics 物件。

顯示模型驗證的計量

使用下列程式碼來顯示計量:

Console.WriteLine();
Console.WriteLine("Model quality metrics evaluation");
Console.WriteLine("--------------------------------");
Console.WriteLine($"Accuracy: {metrics.Accuracy:P2}");
Console.WriteLine($"Auc: {metrics.AreaUnderRocCurve:P2}");
Console.WriteLine($"F1Score: {metrics.F1Score:P2}");
Console.WriteLine("=============== End of model evaluation ===============");
  • Accuracy 計量會取得模型的準確度,這是資料集中正確預測的比例。

  • AreaUnderRocCurve 計量會指出模型正確分類正面和負面類別的自信程度。 您會希望 AreaUnderRocCurve 盡可能接近 1。

  • F1Score 計量會取得模型的 F1 分數,這是精確度重新叫用率之間的平衡量值。 您會希望 F1Score 盡可能接近 1。

預測測試資料結果

  1. 請使用下列程式碼,在緊接著 Evaluate() 方法之後,建立 UseModelWithSingleItem() 方法:

    void UseModelWithSingleItem(MLContext mlContext, ITransformer model)
    {
    
    }
    

    UseModelWithSingleItem() 方法會執行下列工作:

    • 建立單一評論的測試資料。
    • 根據測試資料預測情感。
    • 合併測試資料和預測來進行報告。
    • 顯示預測的結果。
  2. 使用下列程式碼, Evaluate() 在方法呼叫下,將呼叫新增至新方法:

    UseModelWithSingleItem(mlContext, model);
    
  3. 新增下列程式碼,建立作為 UseModelWithSingleItem() 方法中的第一行:

    PredictionEngine<SentimentData, SentimentPrediction> predictionFunction = mlContext.Model.CreatePredictionEngine<SentimentData, SentimentPrediction>(model);
    

    PredictionEngine 是一種便利的 API,可讓您在單一資料執行個體上接著執行預測。 PredictionEngine 不是安全執行緒。 可接受在單一執行緒或原型環境中使用。 為了提升效能和執行緒安全性,請使用 PredictionEnginePool 服務,以建立 PredictionEngine 物件的 ObjectPool 供整個應用程式使用。 請參閱本指南,以瞭解如何在ASP.NET Core Web API 中使用 PredictionEnginePool

    注意

    PredictionEnginePool 服務延伸模組目前處於預覽狀態。

  4. 透過建立 SentimentData 的執行個體,在 UseModelWithSingleItem() 方法中新增評論,以測試定型模型的預測:

    SentimentData sampleStatement = new SentimentData
    {
        SentimentText = "This was a very bad steak"
    };
    
  5. 透過將下列內容新增為 PredictionEngine 方法中的後續幾行程式碼,將測試評論資料傳遞到 UseModelWithSingleItem()

    var resultPrediction = predictionFunction.Predict(sampleStatement);
    

    Predict() 函式會對單一資料列進行預測。

  6. 使用下列程式碼來顯示 SentimentText 和對應的情感預測:

    Console.WriteLine();
    Console.WriteLine("=============== Prediction Test of model with a single sample and test dataset ===============");
    
    Console.WriteLine();
    Console.WriteLine($"Sentiment: {resultPrediction.SentimentText} | Prediction: {(Convert.ToBoolean(resultPrediction.Prediction) ? "Positive" : "Negative")} | Probability: {resultPrediction.Probability} ");
    
    Console.WriteLine("=============== End of Predictions ===============");
    Console.WriteLine();
    

使用模型來進行預測

部署並預測批次項目

  1. 請使用下列程式碼,在緊接著 UseModelWithSingleItem() 方法之後,建立 UseModelWithBatchItems() 方法:

    void UseModelWithBatchItems(MLContext mlContext, ITransformer model)
    {
    
    }
    

    UseModelWithBatchItems() 方法會執行下列工作:

    • 建立批次測試資料。
    • 根據測試資料預測情感。
    • 合併測試資料和預測來進行報告。
    • 顯示預測的結果。
  2. 使用下列程式碼, UseModelWithSingleItem() 在方法呼叫下,將呼叫新增至新方法:

    UseModelWithBatchItems(mlContext, model);
    
  3. 新增一些評論以測試 UseModelWithBatchItems() 方法中定型模型的預測:

    IEnumerable<SentimentData> sentiments = new[]
    {
        new SentimentData
        {
            SentimentText = "This was a horrible meal"
        },
        new SentimentData
        {
            SentimentText = "I love this spaghetti."
        }
    };
    

預測評論情感

利用 Transform() 方法,使用該模型來預測評論資料情感:

IDataView batchComments = mlContext.Data.LoadFromEnumerable(sentiments);

IDataView predictions = model.Transform(batchComments);

// Use model to predict whether comment data is Positive (1) or Negative (0).
IEnumerable<SentimentPrediction> predictedResults = mlContext.Data.CreateEnumerable<SentimentPrediction>(predictions, reuseRowObject: false);

合併並顯示預測

使用下列程式碼來為預測建立標頭:

Console.WriteLine();

Console.WriteLine("=============== Prediction Test of loaded model with multiple samples ===============");

因為 SentimentPrediction 繼承自 SentimentData,所以 Transform() 方法會使用預測欄位填入 SentimentText。 隨著 ML.NET 處理的進行,每個元件都會新增資料行,使其易於顯示結果:

foreach (SentimentPrediction prediction  in predictedResults)
{
    Console.WriteLine($"Sentiment: {prediction.SentimentText} | Prediction: {(Convert.ToBoolean(prediction.Prediction) ? "Positive" : "Negative")} | Probability: {prediction.Probability} ");
}
Console.WriteLine("=============== End of predictions ===============");

結果

您的結果應該與以下類似。 處理期間會顯示訊息。 您可能會看到警告或處理訊息。 為了清晰起見,下列結果中已將這些都移除。

Model quality metrics evaluation
--------------------------------
Accuracy: 83.96%
Auc: 90.51%
F1Score: 84.04%

=============== End of model evaluation ===============

=============== Prediction Test of model with a single sample and test dataset ===============

Sentiment: This was a very bad steak | Prediction: Negative | Probability: 0.1027377
=============== End of Predictions ===============

=============== Prediction Test of loaded model with a multiple samples ===============

Sentiment: This was a horrible meal | Prediction: Negative | Probability: 0.1369192
Sentiment: I love this spaghetti. | Prediction: Positive | Probability: 0.9960636
=============== End of predictions ===============

=============== End of process ===============
Press any key to continue . . .

恭喜! 您現在已成功建置可對訊息情感進行分類和預測的機器學習模型。

建立成功的模型是一個需要反覆嘗試的程序。 此模型一開始的品質較低,因為此教學課程是使用小型的資料集來提供快速的模型定型。 如果您不熟悉模型品質,您可以藉由提供較大的訓練資料集,或為每個演算法選擇具有不同 超參數 的不同定型演算法,來嘗試加以改善。

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

後續步驟

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

  • 建立主控台應用程式
  • 準備資料
  • 載入資料
  • 建置和定型模型
  • 評估模型
  • 使用模型來進行預測
  • 查看結果

前進到下一個教學課程來深入了解