一, 要解决的问题
问题: 常常一些单位或组织召开会议时需要录入会议记录, 我们需要通过机器学习对用户输入的文本内容进行自动评判, 合格或不合格.(同样的问题还类似垃圾短信检测, 工作日志质量分析等.)
处理思路: 我们人工对现有会议记录进行评判, 标记合格或不合格, 通过对这些记录的学习形成模型, 学习算法仍采用二元分类的快速决策树算法, 和上一篇文章不同, 这次输入的特征值不再是浮点数, 而是中文文本. 这里就要涉及到文本特征提取.
为什么要进行文本特征提取呢? 因为文本是人类的语言, 符号文字序列不能直接传递给算法. 而计算机程序算法只接受具有固定长度的数字矩阵特征向量 (float 或 float 数组), 无法理解可变长度的文本文档.
常用的文本特征提取方法有如下几种:
以上只是需要了解大致的含义, 我们不需要去实现一个文本特征提取的算法, 只需要使用平台自带的方法就可以了.
系统自带的文本特征处理的方法, 输入是一个字符串, 要求将一个语句中的词语用空格分开, 英语的句子中词汇是天生通过空格分割的, 但中文句子不是, 所以我们需要首先进行分词操作, 具体流程如下:
二, 代码
代码整体流程和上一篇文章描述的基本一致, 为简便起见, 我们省略了模型存储和读取的过程.
先看一下数据集:
代码如下:
- namespace BinaryClassification_TextFeaturize
- {
- class Program
- {
- static readonly string DataPath = Path.Combine(Environment.CurrentDirectory, "Data", "meeting_data_full.csv");
- static void Main(string[] args)
- {
- MLContext mlContext = new MLContext();
- var fulldata = mlContext.Data.LoadFromTextFile<MeetingInfo>(DataPath, separatorChar: ',', hasHeader: false);
- var trainTestData = mlContext.Data.TrainTestSplit(fulldata, testFraction: 0.15);
- var trainData = trainTestData.TrainSet;
- var testData = trainTestData.TestSet;
- var trainingPipeline = mlContext.Transforms.CustomMapping<JiebaLambdaInput, JiebaLambdaOutput>(mapAction: JiebaLambda.MyAction, contractName: "JiebaLambda")
- .Append(mlContext.Transforms.Text.FeaturizeText(outputColumnName: "Features", inputColumnName: "JiebaText"))
- .Append(mlContext.BinaryClassification.Trainers.FastTree(labelColumnName: "Label", featureColumnName: "Features"));
- ITransformer trainedModel = trainingPipeline.Fit(trainData);
- // 评估
- var predictions = trainedModel.Transform(testData);
- var metrics = mlContext.BinaryClassification.Evaluate(data: predictions, labelColumnName: "Label");
- Console.WriteLine($"Evalution Accuracy: {metrics.Accuracy:P2}");
- // 创建预测引擎
- var predEngine = mlContext.Model.CreatePredictionEngine<MeetingInfo, PredictionResult>(trainedModel);
- // 预测 1
- MeetingInfo sampleStatement1 = new MeetingInfo { Text = "支委会." };
- var predictionresult1 = predEngine.Predict(sampleStatement1);
- Console.WriteLine($"{sampleStatement1.Text}:{predictionresult1.PredictedLabel}");
- // 预测 2
- MeetingInfo sampleStatement2 = new MeetingInfo { Text = "开展新时代中国特色社会主义思想三十讲党员答题活动." };
- var predictionresult2 = predEngine.Predict(sampleStatement2);
- Console.WriteLine($"{sampleStatement2.Text}:{predictionresult2.PredictedLabel}");
- Console.WriteLine("Press any to exit!");
- Console.ReadKey();
- }
- }
- public class MeetingInfo
- {
- [LoadColumn(0)]
- public bool Label { get; set; }
- [LoadColumn(1)]
- public string Text { get; set; }
- }
- public class PredictionResult : MeetingInfo
- {
- public string JiebaText { get; set; }
- public float[] Features { get; set; }
- public bool PredictedLabel;
- public float Score;
- public float Probability;
- }
- }
- View Code
三, 代码分析
和上一篇文章中相似的内容我就不再重复解释了, 重点介绍一下学习管道的建立.
- var trainingPipeline = mlContext.Transforms.CustomMapping<JiebaLambdaInput, JiebaLambdaOutput>(mapAction: JiebaLambda.MyAction, contractName: "JiebaLambda")
- .Append(mlContext.Transforms.Text.FeaturizeText(outputColumnName: "Features", inputColumnName: "JiebaText"))
- .Append(mlContext.BinaryClassification.Trainers.FastTree(labelColumnName: "Label", featureColumnName: "Features"));
首先, 在进行文本特征转换之前, 我们需要对文本进行分词操作, 您可以对样本数据进行预处理, 形成分词的结果再进行学习, 我们没有采用这个方法, 而是自定义了一个分词处理的数据处理管道, 通过这个管道进行分词, 其定义如下:
- namespace BinaryClassification_TextFeaturize
- {
- public class JiebaLambdaInput
- {
- public string Text { get; set; }
- }
- public class JiebaLambdaOutput
- {
- public string JiebaText { get; set; }
- }
- public class JiebaLambda
- {
- public static void MyAction(JiebaLambdaInput input, JiebaLambdaOutput output)
- {
- JiebaNet.Segmenter.JiebaSegmenter jiebaSegmenter = new JiebaNet.Segmenter.JiebaSegmenter();
- output.JiebaText = string.Join(" ", jiebaSegmenter.Cut(input.Text));
- }
- }
- }
最后我们新建了两个对象进行实际预测:
- // 预测 1
- MeetingInfo sampleStatement1 = new MeetingInfo { Text = "支委会." };
- var predictionresult1 = predEngine.Predict(sampleStatement1);
- Console.WriteLine($"{sampleStatement1.Text}:{predictionresult1.PredictedLabel}");
- // 预测 2
- MeetingInfo sampleStatement2 = new MeetingInfo { Text = "开展新时代中国特色社会主义思想三十讲党员答题活动." };
- var predictionresult2 = predEngine.Predict(sampleStatement2);
- Console.WriteLine($"{sampleStatement2.Text}:{predictionresult2.PredictedLabel}");
预测结果如下:
四, 调试
上一篇文章提到, 当我们运行 Transform 方法时, 会对所有记录进行转换, 转换后的数据集是什么样子呢, 我们可以写一个调试程序看一下.
- var predictions = trainedModel.Transform(testData);
- DebugData(mlContext, predictions);
- private static void DebugData(MLContext mlContext, IDataView predictions)
- {
- var trainDataShow = new List<PredictionResult>(mlContext.Data.CreateEnumerable<PredictionResult>(predictions, false, true));
- foreach (var dataline in trainDataShow)
- {
- dataline.PrintToConsole();
- }
- }
- public class PredictionResult
- {
- public string JiebaText { get; set; }
- public float[] Features { get; set; }
- public bool PredictedLabel;
- public float Score;
- public float Probability;
- public void PrintToConsole()
- {
- Console.WriteLine($"JiebaText={JiebaText}");
- Console.WriteLine($"PredictedLabel:{PredictedLabel},Score:{Score},Probability:{Probability}");
- Console.WriteLine($"TextFeatures Length:{Features.Length}");
- if (Features != null)
- {
- foreach (var f in Features)
- {
- Console.Write($"{f},");
- }
- Console.WriteLine();
- }
- Console.WriteLine();
- }
- }
通过对调试结果的分析, 可以看到整个数据处理管道的工作流程.
五, 资源获取
源码下载地址: https://github.com/seabluescn/Study_ML.NET
工程名称: BinaryClassification_TextFeaturize
点击查看机器学习框架 ML.NET 学习笔记系列文章目录
来源: https://www.cnblogs.com/seabluescn/p/10914829.html