這個教學會教你如何建立一個 .NET 控制台應用程式,將網站留言中的情感分類並採取適當的處理方式。 二進位情感分類器在 Visual Studio 2022 中使用 C#。
在本教學課程中,您將瞭解如何:
- 建立主控台應用程式
- 準備資料
- 載入資料
- 建置並訓練模型
- 評估模型
- 利用模型來做預測
- 查看結果
你可以在 dotnet/samples 倉庫找到這個教學的原始碼。
先決條件
Visual Studio 2022 或更高版本。
UCI 情感標籤句子資料集 (ZIP 檔)
建立主控台應用程式
建立一個名為「SentimentAnalysis」的 C# 主控台應用程式 。 按一下 [下一步] 按鈕。
選擇 .NET 8 作為框架。 按下 [建立] 按鈕。
在專案中建立一個名為 Data 的目錄來儲存資料集檔案。
安裝 Microsoft.ML NuGet 套件:
備註
除非另有說明,本範例使用上述 NuGet 套件的最新穩定版本。
在解決方案總管中,右鍵點擊您的專案並選擇 「管理 NuGet 套件」。 選擇「nuget.org」作為套件來源,然後 選擇瀏覽標籤 。搜尋 Microsoft.ML,選擇你想要的套件,然後選擇 安裝。 安裝時,請同意你選擇的套件的授權條款。
準備資料
備註
本教學的資料集來自 Kotzias 等人所發表的《從群組到個別標籤:使用深度特徵》。 KDD 2015,並存放於 UCI 機器學習資料庫 - Dua, D. 和 Karra Taniskidou, E. (2017)。 UCI 機器學習資料庫 [http://archive.ics.uci.edu/ml]。 加利福尼亞州爾灣:加州大學信息與計算機科學學院。
把檔案複製
yelp_labelled.txt到你 建立的資料目錄 。在解決方案總管中,右鍵點擊該
yelp_labelled.txt檔案並選擇 屬性。 在 進階中,將 複製到輸出目錄 的值更改為 若較新則複製。
建立類別並定義路徑
請在
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頂部加上以下指令: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,具有 string a 用於用戶留言 (SentimentText) 以及 bool (Sentiment) 值,代表情感為 1(正面)或 0(負面)。 這兩個欄位都附加了 LoadColumn 屬性,描述每個欄位的資料檔案順序。 此外,該 Sentiment 屬性還有 ColumnName 屬性來指定為欄位 Label 。 以下範例檔案沒有標頭列,看起來如下:
| 情感文本 | Sentiment(唱片公司) |
|---|---|
| 女服務生服務有點慢。 | 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% 來評估更多資料。在方法結束
splitDataView時回傳 :LoadData()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欄位,並新增為資料集欄位:情感文本 情緒 Features 女服務生服務有點慢。 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輸入參數,以從歷史數據中學習。
訓練模型
將模型擬合於資料 splitTrainSet ,並透過在方法中加入以下程式碼 BuildAndTrainModel() 返回訓練好的模型:
Console.WriteLine("=============== Create and Train the Model ===============");
var model = estimator.Fit(splitTrainSet);
Console.WriteLine("=============== End of training ===============");
Console.WriteLine();
Fit() 方法透過轉換資料集並套用訓練來訓練你的模型。
回傳訓練用於評估的模型
方法結束 BuildAndTrainModel() 時回傳模型:
return model;
評估模型
模型訓練完成後,利用測試資料驗證模型的效能。
在 之後,請用以下程式碼建立
Evaluate()該方法BuildAndTrainModel():void Evaluate(MLContext mlContext, ITransformer model, IDataView splitTestSet) { }該
Evaluate()方法執行以下任務:- 載入測試資料集。
- 建立 BinaryClassification 評估器。
- 評估模型並建立指標。
- 顯示指標。
在方法呼叫下方
BuildAndTrainModel,使用以下程式碼新增對新方法的呼叫:Evaluate(mlContext, model, splitDataView.TestSet);透過
splitTestSet加入以下程式碼轉換Evaluate()資料: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。
預測測試資料的結果
在方法之後
UseModelWithSingleItem(),使用以下程式碼建立該Evaluate()方法: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服務,它能在整個應用程式中建立ObjectPool多個PredictionEngine物件。 請參閱這份關於如何在 ASP.NET Core Web API 中使用PredictionEnginePool的指南。備註
PredictionEnginePool服務擴充目前處於預覽階段。在
UseModelWithSingleItem()方法中新增註解以測試訓練模型的預測,然後建立SentimentData的實例。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();
使用模型進行預測
部署與預測批次項目
在方法之後
UseModelWithBatchItems(),使用以下程式碼建立該UseModelWithSingleItem()方法: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 ===============");
Results
你的結果應該會與以下類似。 在處理過程中,訊息會被顯示出來。 你可能會看到警告或處理相關訊息。 以下結果已移除這些資料以求清晰。
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 倉庫找到這個教學的原始碼。
後續步驟
在本教程中,您將學到如何:
- 建立主控台應用程式
- 準備資料
- 載入資料
- 建置並訓練模型
- 評估模型
- 利用模型來做預測
- 查看結果
請繼續閱讀下一個教學