391.C# ML.net 情绪分析
常见应用场景
- 社交媒体监控:企业和品牌可以使用二元情绪分类器来监控社交媒体上的公众情绪,了解客户对产品或服务的看法,以及市场对新发布或事件的反应。
- 客户服务:自动化客户服务工具(如聊天机器人)可以利用情绪分类器来识别客户的情绪状态,并据此调整对话策略或将复杂的情绪问题转交给人工服务人员。
- 产品评论分析:通过分析在线产品评论的情绪,公司可以获得关于哪些功能受欢迎以及哪些可能需要改进的见解。
- 市场调研:市场研究人员可以使用情绪分类器来分析调查反馈、消费者讨论组或论坛的内容,以了解消费者的情绪倾向和品牌形象。
- 股市分析:金融分析师可能会使用情绪分类器来评估新闻文章、社交媒体帖子或分析师报告中的情绪,作为预测股市趋势的一个因素。
- 政治舆情分析:在政治领域,情绪分类器可以帮助分析公众对政策、政治人物或选举的情绪反应。
- 危机管理:在危机情况下,组织可以使用情绪分类器来监控公众的情绪反应,以便更有效地管理通信和缓解策略。
- 健康护理:在心理健康领域,情绪分类器可以帮助识别患者的情绪状态,为临床决策提供支持。
- 内容过滤:在线平台可以使用情绪分类器来识别和过滤掉具有负面情绪的有害内容,如网络欺凌或仇恨言论。
- 娱乐分析:影视和音乐产业可以使用情绪分类器来分析观众对特定作品的情绪反应,从而指导营销策略或未来作品的创作。
构建有效的二元情绪分类器通常涉及自然语言处理(NLP)和机器学习技术,例如情感词典、支持向量机(SVM)、深度学习等。这些分类器的性能可能会受到训练数据的质量、文本数据的复杂性和上下文的影响。因此,为了提高准确性,可能需要对分类器进行定制和细化,以适应特定的应用场景和领域。
基本的步骤:
- 创建一个新的.NET Core控制台应用程序项目。
- 添加ML.NET NuGet包到项目中。
- 创建一个包含情感文本的SentimentData类,用于表示训练和测试数据。
- 创建一个包含情感预测结果的SentimentPrediction类,用于表示预测结果。
- 加载和准备训练数据,将其转换为IDataView对象。
- 定义数据处理管道,包括将文本转换为数字特征、将特征向量化等步骤。
- 创建一个Estimator对象,用于指定模型的训练算法和参数。
- 使用Fit()方法对模型进行训练,得到训练好的模型。
- 创建一些用于测试的样本数据。
- 使用训练好的模型对样本进行情感预测,得到预测结果。
- 打印预测结果。
加载数据
static readonly string _dataPath = Path.Combine(Environment.CurrentDirectory, "Data", "yelp_labelled.txt");
public static TrainTestData LoadData(MLContext mlContext)
{
// 从文件加载训练数据
IDataView dataView = mlContext.Data.LoadFromTextFile<SentimentData>(_dataPath, hasHeader: false);
// 将加载的数据集拆分为训练集和测试集
TrainTestData splitDataView = mlContext.Data.TrainTestSplit(dataView, testFraction: 0.2);
// 返回拆分后的数据集
return splitDataView;
}
将数据集 dataView 分割成训练集和测试集。
在机器学习中,为了评估模型的性能和泛化能力,通常会将数据集分成训练集和测试集。训练集用于训练模型,而测试集用于评估模型在未见过的数据上的性能。
TrainTestSplit 方法是 ML.NET 提供的一个便捷方法,用于将数据集分割成训练集和测试集。在这个方法中,dataView 是要分割的数据集,testFraction 是测试集所占的比例,通常是一个小于1的浮点数,表示测试集占整个数据集的比例。在这个例子中,testFraction 设置为 0.2,表示测试集占数据集的 20%。
TrainTestData 是一个包含训练集和测试集的对象,通过 splitDataView 变量来接收。可以使用 splitDataView.TrainSet 获取训练集的 IDataView 对象,使用 splitDataView.TestSet 获取测试集的 IDataView 对象。
通过将数据集分割成训练集和测试集,可以在训练模型时使用训练集进行参数优化和模型训练,然后使用测试集评估模型的性能和泛化能力,从而帮助选择最佳的模型和参数设置。
构建和训练模型
public static ITransformer BuildAndTrainModel(MLContext mlContext, IDataView splitTrainSet)
{
// 创建一个灵活的管道,用于创建/训练模型
// 这个管道由一系列的估计器组成,用于格式化和清理数据
// 将文本列转换为数值向量(Features列)
var estimator = mlContext.Transforms.Text
.FeaturizeText(outputColumnName: "Features", inputColumnName: nameof(SentimentData.SentimentText))
// 将机器学习任务添加到估计器中
.Append(mlContext.BinaryClassification
.Trainers.SdcaLogisticRegression(labelColumnName: "Label", featureColumnName: "Features"));
// 创建并训练基于加载和转换后的数据集的模型
Console.WriteLine("=============== Create and Train the Model ===============");
var model = estimator.Fit(splitTrainSet);
Console.WriteLine("=============== End of training ===============");
Console.WriteLine();
// 返回训练好的模型
return model;
}
使用
mlContext.Transforms.Text.FeaturizeText方法来将文本数据转换为特征向量。这个方法将输入的文本列(SentimentData.SentimentText)转换为一个名为"Features"的新列,其中包含了表示文本特征的向量。
接下来,使用.Append方法将二元分类任务添加到估计器中。这里使用的是
mlContext.BinaryClassification.Trainers.SdcaLogisticRegression,它是一种基于随机坐标下降(Stochastic Dual Coordinate Ascent)的逻辑回归分类器。
在这个分类器中,labelColumnName参数指定了用于训练的标签列,这里是"Label"列,用于表示情绪类别(正面或负面)。featureColumnName参数指定了用于训练的特征列,这里是之前生成的"Features"列,其中包含了文本的特征向量。
通过这个估计器,可以训练一个二元情绪分类器模型,该模型可以将文本数据进行情绪分类预测。
评估模型
public static void Evaluate(MLContext mlContext, ITransformer model, IDataView splitTestSet)
{
// 对模型进行评估并显示准确性统计信息
Console.WriteLine("=============== Evaluating Model accuracy with Test data===============");
IDataView predictions = model.Transform(splitTestSet);
// 使用BinaryClassificationContext.Evaluate方法计算模型的整体指标
CalibratedBinaryClassificationMetrics metrics = mlContext.BinaryClassification.Evaluate(predictions, "Label");
// Accuracy指标表示测试集中正确预测的比例
// AreaUnderROCCurve指标表示模型对于随机选择的正样本高于随机选择的负样本的概率(假设"正"高于"负")
// F1Score指标表示模型的F1分数,F1分数是精确度和召回率的调和平均值
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 ===============");
}
mlContext.BinaryClassification.Evaluate方法用于评估模型的性能。它接受两个参数:predictions和"Label"。
predictions是一个包含模型对测试集进行预测的结果的IDataView对象。这些预测结果包括预测的情绪类别以及模型对每个样本的置信度。
"Label"是测试集中用于评估的真实情绪类别的列名。这个参数告诉评估器在哪个列中查找真实的情绪类别。
评估结果被存储在
CalibratedBinaryClassificationMetrics对象中,通过metrics变量进行接收。这个对象包含了许多用于评估二元分类模型性能的指标,例如准确率、召回率、F1分数、AUC等。可以使用这些指标来判断模型的性能和泛化能力。
通过这行代码,可以计算出模型在测试集上的性能指标,并将结果存储在metrics对象中,以便进一步分析和比较不同模型的性能。
使用单个项进行预测
private static void UseModelWithSingleItem(MLContext mlContext, ITransformer model)
{
// 创建一个预测引擎,用于进行情感预测
PredictionEngine<SentimentData, SentimentPrediction> predictionFunction = mlContext.Model.CreatePredictionEngine<SentimentData, SentimentPrediction>(model);
// 创建一个用于测试的样本数据
SentimentData sampleStatement = new SentimentData
{
SentimentText = "This was a very bad steak"
};
// 使用预测引擎对样本进行情感预测
var resultPrediction = predictionFunction.Predict(sampleStatement);
// 打印预测结果
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();
}
mlContext.Model.CreatePredictionEngine方法用于创建一个预测引擎,它接受两个参数:SentimentData和SentimentPrediction。
SentimentData是输入数据的类型,用于表示待预测的情绪文本数据。SentimentPrediction是输出数据的类型,用于表示预测结果,即情绪分类的预测。
model是经过训练的情绪分类模型。这个模型将用于进行预测。
通过这行代码,可以创建一个预测引擎,该引擎可以接受SentimentData类型的输入数据,并返回SentimentPrediction类型的预测结果。预测引擎可以使用训练好的模型对新的情绪文本数据进行预测,并返回预测的情绪分类结果。
使用批量项进行预测
public static void UseModelWithBatchItems(MLContext mlContext, ITransformer model)
{
// 创建一组用于测试的样本数据
IEnumerable<SentimentData> sentiments = new[]
{
new SentimentData
{
SentimentText = "This was a horrible meal"
},
new SentimentData
{
SentimentText = "I love this spaghetti."
}
};
// 加载刚刚创建的批量评论数据
IDataView batchComments = mlContext.Data.LoadFromEnumerable(sentiments);
// 使用模型对评论数据进行预测
IDataView predictions = model.Transform(batchComments);
// 将预测结果转换为可枚举集合
IEnumerable<SentimentPrediction> predictedResults = mlContext.Data.CreateEnumerable<SentimentPrediction>(predictions, reuseRowObject: false);
// 打印预测结果
Console.WriteLine();
Console.WriteLine("=============== Prediction Test of loaded model with multiple samples ===============");
Console.WriteLine();
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 ===============");
}
主程序入口
static void Main(string[] args)
{
// 创建ML.NET上下文/本地环境 - 允许您添加步骤以保持所有内容的完整性
// 当您发现ML.NET的训练器和转换时
MLContext mlContext = new MLContext();
// 加载数据
TrainTestData splitDataView = LoadData(mlContext);
// 构建和训练模型
ITransformer model = BuildAndTrainModel(mlContext, splitDataView.TrainSet);
// 评估模型
Evaluate(mlContext, model, splitDataView.TestSet);
// 使用单个项进行预测
UseModelWithSingleItem(mlContext, model);
// 使用批量项进行预测
UseModelWithBatchItems(mlContext, model);
Console.WriteLine();
Console.WriteLine("=============== End of process ===============");
}