一、准备样本

接上一篇文章提到的问题:根据一个人的身高、体重来判断一个人的身材是否很好。但我手上没有样本数据,只能伪造一批数据了,伪造的数据比较标准,用来学习还是蛮合适的。

下面是我用来伪造数据的代码:

           string Filename = "./figure_full.csv";
StreamWriter sw = new StreamWriter(Filename, false);
sw.WriteLine("Height,Weight,Result"); Random random = new Random();
float height, weight;
Result result; for (int i = ; i < ; i++)
{
height = random.Next(, );
weight = random.Next(, ); if (height > && weight < )
result = Result.Good;
else
result = Result.Bad; sw.WriteLine($"{height},{weight},{(int)result}");
} enum Result
{
Bad=,
Good=
}

制造成功后的数据如下:

用记事本打开:

二、源码

数据准备好了,我们就用准备好的数据进行学习了,先贴出全部代码,然后再逐一解释:

namespace BinaryClassification_Figure
{
class Program
{
static readonly string DataPath = Path.Combine(Environment.CurrentDirectory, "Data", "figure_full.csv");
static readonly string ModelPath = Path.Combine(Environment.CurrentDirectory, "Data", "FastTree_Model.zip"); static void Main(string[] args)
{
TrainAndSave();
LoadAndPrediction(); Console.WriteLine("Press any to exit!");
Console.ReadKey();
} static void TrainAndSave()
{
MLContext mlContext = new MLContext(); //准备数据
var fulldata = mlContext.Data.LoadFromTextFile<FigureData>(path: DataPath, hasHeader: true, separatorChar: ',');
var trainTestData = mlContext.Data.TrainTestSplit(fulldata,testFraction:0.2);
var trainData = trainTestData.TrainSet;
var testData = trainTestData.TestSet; //训练
IEstimator<ITransformer> dataProcessPipeline = mlContext.Transforms.Concatenate("Features", new[] { "Height", "Weight" })
.Append(mlContext.Transforms.NormalizeMeanVariance(inputColumnName: "Features", outputColumnName: "FeaturesNormalizedByMeanVar"));
IEstimator<ITransformer> trainer = mlContext.BinaryClassification.Trainers.FastTree(labelColumnName: "Result", featureColumnName: "FeaturesNormalizedByMeanVar");
IEstimator<ITransformer> trainingPipeline = dataProcessPipeline.Append(trainer);
ITransformer model = trainingPipeline.Fit(trainData); //评估
var predictions = model.Transform(testData);
var metrics = mlContext.BinaryClassification.Evaluate(data: predictions, labelColumnName: "Result", scoreColumnName: "Score");
PrintBinaryClassificationMetrics(trainer.ToString(), metrics); //保存模型
mlContext.Model.Save(model, trainData.Schema, ModelPath);
Console.WriteLine($"Model file saved to :{ModelPath}");
} static void LoadAndPrediction()
{
var mlContext = new MLContext();
ITransformer model = mlContext.Model.Load(ModelPath, out var inputSchema);
var predictionEngine = mlContext.Model.CreatePredictionEngine<FigureData, FigureDatePredicted>(model); FigureData test = new FigureData();
test.Weight = ;
test.Height = ; var prediction = predictionEngine.Predict(test);
Console.WriteLine($"Predict Result :{prediction.PredictedLabel}");
}
} public class FigureData
{
[LoadColumn()]
public float Height { get; set; } [LoadColumn()]
public float Weight { get; set; } [LoadColumn()]
public bool Result { get; set; }
} public class FigureDatePredicted : FigureData
{
public bool PredictedLabel;
}
}

三、对代码的解释

1、读取样本数据

        string DataPath = Path.Combine(Environment.CurrentDirectory, "Data", "figure_full.csv");
MLContext mlContext = new MLContext(); //准备数据
var fulldata = mlContext.Data.LoadFromTextFile<FigureData>(path: DataPath, hasHeader: true, separatorChar: ',');
var trainTestData = mlContext.Data.TrainTestSplit(fulldata,testFraction:0.2);
var trainData = trainTestData.TrainSet;
var testData = trainTestData.TestSet;

LoadFromTextFile<FigureData>(path: DataPath, hasHeader: true, separatorChar: ',')用来读取数据到DataView

FigureData类是和样本数据对应的实体类,LoadColumn特性指示该属性对应该条数据中的第几个数据。

    public class FigureData
{
[LoadColumn()]
public float Height { get; set; } [LoadColumn()]
public float Weight { get; set; } [LoadColumn()]
public bool Result { get; set; }
}

path:文件路径

hasHeader:文本文件是否包含标题

separatorChar:用来分割数据的字符,我们用的是逗号,常用的还有跳格符‘\t’

TrainTestSplit(fulldata,testFraction:0.2)用来随机分割数据,分成学习数据和评估用的数据,通常情况,如果数据较多,测试数据取20%左右比较合适,如果数据量较少,测试数据取10%左右比较合适。

如果不通过分割,准备两个数据文件,一个用来训练、一个用来评估,效果是一样的。

2、训练 

            //训练
IEstimator<ITransformer> dataProcessPipeline = mlContext.Transforms.Concatenate("Features", new[] { "Height", "Weight" })
.Append(mlContext.Transforms.NormalizeMeanVariance(inputColumnName: "Features", outputColumnName: "FeaturesNormalizedByMeanVar"));
IEstimator<ITransformer> trainer = mlContext.BinaryClassification.Trainers.FastTree(labelColumnName: "Result", featureColumnName: "FeaturesNormalizedByMeanVar");
IEstimator<ITransformer> trainingPipeline = dataProcessPipeline.Append(trainer);
ITransformer model = trainingPipeline.Fit(trainData);

IDataView这个数据集就类似一个表格,它的列(Column)是可以动态增加的,一开始我们通过LoadFromTextFile获得的数据集包括:Height、Weight、Result这几个列,在进行训练之前,我们还要对这个数据集进行处理,形成符合我们要求的数据集。

Concatenate这个方法是把多个列,组合成一个列,因为二元分类的机器学习算法只接收一个特征列,所以要把多个特征列(Height、Weight)组合成一个特征列Features(组合的结果应该是个float数组)。

NormalizeMeanVariance是对列进行归一化处理,这里输入列为:Features,输出列为:FeaturesNormalizedByMeanVar,归一化的含义见本文最后一节介绍。

数据集就绪以后,就要选择学习算法,针对二元分类,我们选择了快速决策树算法FastTree,我们需要告诉这个算法特征值放在哪个列里面(FeaturesNormalizedByMeanVar),标签值放在哪个列里面(Result)。

链接数据处理管道和算法形成学习管道,将数据集中的数据逐一通过学习管道进行学习,形成机器学习模型。

有了这个模型我们就可以通过它进行实际应用了。但我们一般不会现在就使用这个模型,我们需要先评估一下这个模型,然后把模型保存下来。以后应用时再通过文件读取出模型,然后进行应用,这样就不用等待学习的时间了,通常学习的时间都比较长。

3、评估 

            //评估
var predictions = model.Transform(testData);
var metrics = mlContext.BinaryClassification.Evaluate(data: predictions, labelColumnName: "Result");
PrintBinaryClassificationMetrics(trainer.ToString(), metrics);

评估的过程就是对测试数据集进行批量转换(Transform),转换过的数据集会多出一个“PredictedLabel”的列,这个就是模型评估的结果,逐条将这个结果和实际结果(Result)进行比较,就最终形成了效果评估数据。

我们可以打印这个评估结果,查看其成功率,一般成功率大于97%就是比较好的模型了。由于我们伪造的数据比较整齐,所以我们这次评估的成功率为100%。

注意:评估过程不会提升现有的模型能力,只是对现有模型的一种检测。

4、保存模型 

//保存模型
string ModelPath = Path.Combine(Environment.CurrentDirectory, "Data", "FastTree_Model.zip");
mlContext.Model.Save(model, trainData.Schema, ModelPath);
Console.WriteLine($"Model file saved to :{ModelPath}");

这个没啥好解释的。

5、读取模型并创建预测引擎 

           //读取模型
var mlContext = new MLContext();
ITransformer model = mlContext.Model.Load(ModelPath, out var inputSchema); //创建预测引擎
var predictionEngine = mlContext.Model.CreatePredictionEngine<FigureData, FigureDatePredicted>(model);

创建预测引擎的功能和Transform是类似的,不过Transform是处理批量记录,这里只处理一条数据,而且这里的输入输出是实体对象,定义如下:

   public class FigureData
{
[LoadColumn()]
public float Height { get; set; } [LoadColumn()]
public float Weight { get; set; } [LoadColumn()]
public bool Result { get; set; }
} public class FigureDatePredicted : FigureData
{
public bool PredictedLabel;
}

由于预测结果里放在“PredictedLabel”字段中,所以FigureDatePredicted类必须要包含PredictedLabel属性,目前FigureDatePredicted 类是从FigureData类继承的,由于我们只用到PredictedLabel属性,所以不继承也没有关系,如果继承的话,后面要调试的话会方便一点。

6、应用 

            FigureData test = new FigureData
{
Weight = ,
Height =
}; var prediction = predictionEngine.Predict(test);
Console.WriteLine($"Predict Result :{prediction.PredictedLabel}");

这部分代码就比较简单,test是我们要预测的对象,预测后打印出预测结果。

四、附:数据归一化

机器学习的算法中一般会有很多的乘法运算,当运算的数字过大时,很容易在多次运算后溢出,为了防止这种情况,就要对数据进行归一化处理。归一化的目标就是把参与运算的特征数变为(0,1)或(-1,1)之间的浮点数,常见的处理方式有:min-max标准化、Log函数转换、对数函数转换等。

我们这次采用的是平均方差归一化方法。

五、资源

源码下载地址:https://github.com/seabluescn/Study_ML.NET

工程名称:BinaryClassification_Figure

点击查看机器学习框架ML.NET学习笔记系列文章目录

机器学习框架ML.NET学习笔记【2】入门之二元分类的更多相关文章

  1. 机器学习框架ML.NET学习笔记【4】多元分类之手写数字识别

    一.问题与解决方案 通过多元分类算法进行手写数字识别,手写数字的图片分辨率为8*8的灰度图片.已经预先进行过处理,读取了各像素点的灰度值,并进行了标记. 其中第0列是序号(不参与运算).1-64列是像 ...

  2. 机器学习框架ML.NET学习笔记【5】多元分类之手写数字识别(续)

    一.概述 上一篇文章我们利用ML.NET的多元分类算法实现了一个手写数字识别的例子,这个例子存在一个问题,就是输入的数据是预处理过的,很不直观,这次我们要直接通过图片来进行学习和判断.思路很简单,就是 ...

  3. 机器学习框架ML.NET学习笔记【1】基本概念与系列文章目录

    一.序言 微软的机器学习框架于2018年5月出了0.1版本,2019年5月发布1.0版本.期间各版本之间差异(包括命名空间.方法等)还是比较大的,随着1.0版发布,应该是趋于稳定了.之前在园子里也看到 ...

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

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

  5. 机器学习框架ML.NET学习笔记【6】TensorFlow图片分类

    一.概述 通过之前两篇文章的学习,我们应该已经了解了多元分类的工作原理,图片的分类其流程和之前完全一致,其中最核心的问题就是特征的提取,只要完成特征提取,分类算法就很好处理了,具体流程如下: 之前介绍 ...

  6. 机器学习框架ML.NET学习笔记【7】人物图片颜值判断

    一.概述 这次要解决的问题是输入一张照片,输出人物的颜值数据. 学习样本来源于华南理工大学发布的SCUT-FBP5500数据集,数据集包括 5500 人,每人按颜值魅力打分,分值在 1 到 5 分之间 ...

  7. 机器学习框架ML.NET学习笔记【8】目标检测(采用YOLO2模型)

    一.概述 本篇文章介绍通过YOLO模型进行目标识别的应用,原始代码来源于:https://github.com/dotnet/machinelearning-samples 实现的功能是输入一张图片, ...

  8. 机器学习框架ML.NET学习笔记【9】自动学习

    一.概述 本篇我们首先通过回归算法实现一个葡萄酒品质预测的程序,然后通过AutoML的方法再重新实现,通过对比两种实现方式来学习AutoML的应用. 首先数据集来自于竞赛网站kaggle.com的UC ...

  9. ML.NET学习笔记 ---- 系列文章

    机器学习框架ML.NET学习笔记[1]基本概念与系列文章目录 机器学习框架ML.NET学习笔记[2]入门之二元分类 机器学习框架ML.NET学习笔记[3]文本特征分析 机器学习框架ML.NET学习笔记 ...

随机推荐

  1. Wireshark抓包常见问题解析

    1.   tcp out-of-order(tcp有问题) 解答: 1).    应该有很多原因.但是多半是网络拥塞,导致顺序包抵达时间不同,延时太长,或者包丢失,需要重新组合数据单元 因为他们可能是 ...

  2. MySQL Sending data导致查询很慢的问题详细分析

    这两天帮忙定位一个MySQL查询很慢的问题,定位过程综合各种方法.理论.工具,很有代表性,分享给大家作为新年礼物:) [问题现象] 使用sphinx支持倒排索引,但sphinx从mysql查询源数据的 ...

  3. ss3

    1)执行如下命令,进行安装shadowsocks(命令需要一条条的输入,然后回车,执行完一条,在执行下一条命令),过程中可能会让你选择确认的地方,直接输入"y"回车即可: yum ...

  4. cdh 安装组件 异常总结

    hive 启动 要 把mysql的jar包放到/opt/cloudera/parcels/CDH-5.9.3-1.cdh5.9.3.p0.4/lib/hive/lib 下 假设有3个节点就要放3次

  5. struts 文件上传示例

    import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io ...

  6. DOM 中 Property 和 Attribute 的区别(转)

    property 和 attribute非常容易混淆,两个单词的中文翻译也都非常相近(property:属性,attribute:特性),但实际上,二者是不同的东西,属于不同的范畴. property ...

  7. 【总结整理】javascript的函数在if中调用时是否加括号---与.net的不同之处

    javascript的函数调用时是否加括号 if(event.preventDefault){ event.preventDefault(); if判断条件里面不要加括号,不加括号是应该以属性形式,i ...

  8. 任务调度TimerTask&Quartz的 Java 实现方法与比较

    文章引自--https://www.ibm.com/developerworks/cn/java/j-lo-taskschedule/ 前言 任务调度是指基于给定时间点,给定时间间隔或者给定执行次数自 ...

  9. 5.Windows应急响应:挖矿病毒

    0x00 前言 随着虚拟货币的疯狂炒作,挖矿病毒已经成为不法分子利用最为频繁的攻击方式之一.病毒 传播者可以利用个人电脑或服务器进行挖矿,具体现象为电脑CPU占用率高,C盘可使用空间骤降, 电脑温度升 ...

  10. .NET 中文件嵌套,例如:cshtml文件下面嵌套css和js【机器翻译】

    越来越多的我发现自己在我的一些较大的Web项目中丢失了文件.有很多内容要处理 - HTML视图,几个派生CSS页面,页面级CSS,脚本库,应用程序范围的脚本和页面特定的脚本文件等等.幸运的是,我使用R ...