本教程介绍如何创建一个 .NET 控制台应用程序,该应用程序将情绪从网站注释分类并采取相应的作。 二进制情绪分类器在 Visual Studio 2022 中使用 C# 。
本教程中,您将学习如何:
- 创建控制台应用程序
- 准备数据
- 加载数据
- 生成和训练模型
- 评估模型
- 使用模型进行预测
- 查看结果
可以在 dotnet/samples 存储库中找到本教程的源代码。
先决条件
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]。 加州大学欧文分校的信息与计算机科学学院。
下载 UCI 情绪标记句子数据集 ZIP 文件,然后解压缩。
将
yelp_labelled.txt文件复制到所创建 的数据 目录中。在解决方案资源管理器中,右键单击
yelp_labelled.txt该文件并选择 “属性”。 在 高级 下,将 复制到输出目录 的值更改为 若较新则复制。
创建类并定义路径
将以下附加
using指令添加到 Program.cs 文件的顶部: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 具有一个 string,用于用户评论(SentimentText),以及一个表示情感的 bool,其值为Sentiment 1(正面)或 0(负面)。 这两个字段都附加了 LoadColumn 属性,用于描述每个字段的数据文件顺序。 此外,该 Sentiment 属性还有一个 ColumnName 属性,用于将其指定为 Label 字段。 以下示例文件没有标题行,如下所示:
| SentimentText | 情绪(标签) |
|---|---|
| 服务员服务速度有点慢。 | 0 |
| 地壳不好。 | 0 |
| 哇。。。喜欢这个地方。 | 1 |
| 服务非常提示。 | 1 |
SentimentPrediction 是模型训练后使用的预测类。 它继承自 SentimentData 以便可以显示输入 SentimentText 以及输出预测。 模型在提供新输入SentimentText时预测的值是布尔值Prediction。
输出类 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列,并将其添加为新的数据集列:SentimentText 情绪 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 值进行比较,并返回 一个BinaryClassificationMetrics 对象,说明模型的性能。
显示模型验证的指标
使用以下代码显示指标:
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尽可能接近一个。该
F1Score指标获取模型的 F1 分数,这是 精度 和 召回率之间的平衡度量值。 希望F1Score尽可能接近一个。
预测测试数据结果
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该服务,该服务会创建一个ObjectPoolPredictionEngine对象用于整个应用程序。 请参阅本指南,了解如何在 ASP.NET Core Web API 中使用PredictionEnginePool。注释
PredictionEnginePool服务扩展目前为预览版。通过创建以下
UseModelWithSingleItem()实例,添加注释以测试方法中SentimentData训练的模型的预测:SentimentData sampleStatement = new SentimentData { SentimentText = "This was a very bad steak" };通过在
UseModelWithSingleItem()方法中添加以下代码作为下一行代码,将测试注释数据传递给PredictionEngine。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 存储库中找到本教程的源代码。
后续步骤
在本教程中,你将学习到如何:
- 创建控制台应用程序
- 准备数据
- 加载数据
- 生成和训练模型
- 评估模型
- 使用模型进行预测
- 查看结果
转到下一教程,了解详细信息