教學課程:在 ML.NET 中使用二元分類來分析網站批註的情感
本教學課程示範如何建立 .NET Core 主控台應用程式,來分類網站評論中的情感並採取適當動作。 二進位情感分類器會在 Visual Studio 2022 中使用 C#。
在本教學課程中,您會了解如何:
- 建立主控台應用程式
- 準備資料
- 載入資料
- 建置和定型模型
- 評估模型
- 使用模型來進行預測
- 查看結果
您可以在 dotnet/samples 存放庫中找到本教學課程的原始程式碼。
必要條件
UCI 情感標記句子資料集 (ZIP 檔案)
建立主控台應用程式
建立名為 「SentimentAnalysis」 的 C# 主控台應用程式 。 按 [下一步] 按鈕。
選擇 .NET 6 作為要使用的架構。 按一下 [ 建立 ] 按鈕。
在專案中建立一個名為 Data 的目錄以儲存資料集檔案。
安裝「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.
下載並解壓縮 UCI 情感標記句子資料集 ZIP 檔案。
將
yelp_labelled.txt
檔案複製到您所建立的 Data 目錄。在 [方案總管] 中,以滑鼠右鍵按一下
yelp_labeled.txt
檔案,並選取 [內容]。 在 [進階] 底下,將 [複製到輸出目錄] 的值變更為 [有更新時才複製]。
建立類別及定義路徑
在 Program.cs 檔案頂端新增下列額外的
using
陳述式:using Microsoft.ML; using Microsoft.ML.Data; using SentimentAnalysis; using static Microsoft.ML.DataOperationsCatalog;
將下列程式碼新增至 語句正下方
using
的行,以建立欄位來保存最近下載的資料集檔案路徑:string _dataPath = Path.Combine(Environment.CurrentDirectory, "Data", "yelp_labelled.txt");
接下來,為輸入資料和預測建立類別。 將新類別新增至專案:
在 [方案總管] 中,以滑鼠右鍵按一下專案,然後選取 [新增]>[新項目]。
在 [新增項目] 對話方塊中,選取 [類別],然後將 [名稱] 欄位變更為 SentimentData.cs。 接著,選取 [新增] 按鈕。
SentimentData.cs 檔案隨即在程式碼編輯器中開啟。 將以下
using
陳述式新增至 SentimentData.cs 頂端:using Microsoft.ML.Data;
移除現有的類別定義,然後將下列程式碼 (具有
SentimentData
和SentimentPrediction
這兩個類別) 新增至 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
。
您可以準備資料,然後載入資料:
以下列程式碼取代 行
Console.WriteLine("Hello World!")
,以宣告和初始化 mlCoNtext 變數:MLContext mlContext = new MLContext();
新增下列專案作為下一行程式碼:
TrainTestData splitDataView = LoadData(mlContext);
使用下列程式碼在
Program.cs
檔案底部建立LoadData()
方法:TrainTestData LoadData(MLContext mlContext) { }
LoadData()
方法會執行下列工作:- 載入資料。
- 將載入的資料集分割為定型與測試資料集。
- 傳回分割的定型與測試資料集。
將下列程式碼新增為
LoadData()
方法的第一行:IDataView dataView = mlContext.Data.LoadFromTextFile<SentimentData>(_dataPath, hasHeader: false);
LoadFromTextFile () 方法會定義資料架構,並在檔案中讀取。 會接受資料路徑變數然後傳回
IDataView
。
分割資料集以進行模型定型與測試
準備模型時,您可以使用部分資料集來定型它,並使用部分資料集來測試模型的準確度。
若要將載入的資料分割成所需的資料集,請將下列程式碼加入為
LoadData()
方法中的下一行:TrainTestData splitDataView = mlContext.Data.TrainTestSplit(dataView, testFraction: 0.2);
先前的程式碼會使用 TrainTestSplit () 方法,將載入的資料集分割成定型和測試資料集,並在 類別中 DataOperationsCatalog.TrainTestData 傳回它們。 您可以使用
testFraction
參數來指定資料的測試集百分比。 預設值是 10%,但您在本例中會使用 20% 以評估更多資料。在
LoadData()
方法的結尾傳回splitDataView
:return splitDataView;
建置和定型模型
將下列呼叫新增至
BuildAndTrainModel
方法的呼叫LoadData
下方的方法:ITransformer model = BuildAndTrainModel(mlContext, splitDataView.TrainSet);
BuildAndTrainModel()
方法會執行下列工作:- 擷取並轉換資料。
- 將模型定型。
- 根據測試資料預測情感。
- 傳回模型。
使用下列程式碼,在
BuildAndTrainModel()
方法下方LoadData()
建立 方法:ITransformer BuildAndTrainModel(MLContext mlContext, IDataView splitTrainSet) { }
擷取並轉換資料
呼叫
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;
評估模型
定型模型之後,請使用測試資料來驗證模型的效能。
在
BuildAndTrainModel()
之後,使用下列程式碼建立Evaluate()
方法:void Evaluate(MLContext mlContext, ITransformer model, IDataView splitTestSet) { }
Evaluate()
方法會執行下列工作:- 載入測試資料集。
- 建立 BinaryClassification 評估工具。
- 評估模型並建立計量。
- 顯示計量。
使用下列程式碼,將呼叫新增至方法呼叫下方
BuildAndTrainModel
的新方法:Evaluate(mlContext, model, splitDataView.TestSet);
將下列程式碼新增至
Evaluate()
以轉換splitTestSet
資料:Console.WriteLine("=============== Evaluating Model accuracy with Test data==============="); IDataView predictions = model.Transform(splitTestSet);
之前的程式碼使用 Transform() 方法會對測試資料集多個所提供的輸入資料列進行預測。
將下列內容新增為
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。
預測測試資料結果
請使用下列程式碼,在緊接著
Evaluate()
方法之後,建立UseModelWithSingleItem()
方法:void UseModelWithSingleItem(MLContext mlContext, ITransformer model) { }
UseModelWithSingleItem()
方法會執行下列工作:- 建立單一評論的測試資料。
- 根據測試資料預測情感。
- 合併測試資料和預測來進行報告。
- 顯示預測的結果。
使用下列程式碼,
Evaluate()
在方法呼叫下,將呼叫新增至新方法:UseModelWithSingleItem(mlContext, model);
新增下列程式碼,建立作為
UseModelWithSingleItem()
方法中的第一行:PredictionEngine<SentimentData, SentimentPrediction> predictionFunction = mlContext.Model.CreatePredictionEngine<SentimentData, SentimentPrediction>(model);
PredictionEngine 是一種便利的 API,可讓您在單一資料執行個體上接著執行預測。
PredictionEngine
不是安全執行緒。 可接受在單一執行緒或原型環境中使用。 為了提升效能和執行緒安全性,請使用PredictionEnginePool
服務,以建立PredictionEngine
物件的ObjectPool
供整個應用程式使用。 請參閱本指南,以瞭解如何在ASP.NET Core Web API 中使用PredictionEnginePool
。注意
PredictionEnginePool
服務延伸模組目前處於預覽狀態。透過建立
SentimentData
的執行個體,在UseModelWithSingleItem()
方法中新增評論,以測試定型模型的預測:SentimentData sampleStatement = new SentimentData { SentimentText = "This was a very bad steak" };
透過將下列內容新增為
PredictionEngine
方法中的後續幾行程式碼,將測試評論資料傳遞到UseModelWithSingleItem()
:var resultPrediction = predictionFunction.Predict(sampleStatement);
Predict() 函式會對單一資料列進行預測。
使用下列程式碼來顯示
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();
使用模型來進行預測
部署並預測批次項目
請使用下列程式碼,在緊接著
UseModelWithSingleItem()
方法之後,建立UseModelWithBatchItems()
方法:void UseModelWithBatchItems(MLContext mlContext, ITransformer model) { }
UseModelWithBatchItems()
方法會執行下列工作:- 建立批次測試資料。
- 根據測試資料預測情感。
- 合併測試資料和預測來進行報告。
- 顯示預測的結果。
使用下列程式碼,
UseModelWithSingleItem()
在方法呼叫下,將呼叫新增至新方法:UseModelWithBatchItems(mlContext, model);
新增一些評論以測試
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 存放庫中找到本教學課程的原始程式碼。
後續步驟
在本教學課程中,您已了解如何:
- 建立主控台應用程式
- 準備資料
- 載入資料
- 建置和定型模型
- 評估模型
- 使用模型來進行預測
- 查看結果
前進到下一個教學課程來深入了解