• 机器学习框架ML.NET学习笔记【3】文本特征分析


    一、要解决的问题

    问题:常常一些单位或组织召开会议时需要录入会议记录,我们需要通过机器学习对用户输入的文本内容进行自动评判,合格或不合格。(同样的问题还类似垃圾短信检测、工作日志质量分析等。)

    处理思路:我们人工对现有会议记录进行评判,标记合格或不合格,通过对这些记录的学习形成模型,学习算法仍采用二元分类的快速决策树算法,和上一篇文章不同,这次输入的特征值不再是浮点数,而是中文文本。这里就要涉及到文本特征提取。

    为什么要进行文本特征提取呢?因为文本是人类的语言,符号文字序列不能直接传递给算法。而计算机程序算法只接受具有固定长度的数字矩阵特征向量(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学习笔记系列文章目录

  • 相关阅读:
    Node.js——fs常用API
    Node.js——Stream
    Node.js——Buffer
    Node.js——post方式提交的图片如何保存
    CSS——BFC
    Node.js——body方式提交数据
    Node.js——基本服务开启
    Node.js——url模块
    Node.js——render封装
    Node.js——开放静态资源原生写法
  • 原文地址:https://www.cnblogs.com/seabluescn/p/10914829.html
Copyright © 2020-2023  润新知