导读:ML.NET系列文章

本文将基于ML.NET v0.2预览版,介绍机器学习中的分类和回归两个重要概念,并实现白葡萄酒品质预测。

本系列前面的文章也提到了一些,经典的机器学习最主要的特点就是模拟,具体来说就是定义出一个y=f(x)函数,x就是我们定义的特征值(它可能是一个/组标量,也可能是一个/组向量),y就是目标值,这个函数的目标是要无限满足所有(x, y)都出现在函数y=f(x)在坐标轴上经过的地方,这有时候也叫函数逼近。试想,只要这个函数是模拟出了对某类问题的输入和输出值(x, y)的运算过程,那再来一个新的输入值x,是不是就可以求解出输出值y是什么了!基于这个道理,机器学习才有了预知未来的能力。那么,对未来的预知最常见的两种情况:一个是为了分类,一个是为了回归。“分类”的概念容易理解,它要解决的目标值是标签类的数据,比如属于什么物种,是否是垃圾邮件,什么类型的电影之类的问题,而“回归”的概念需要一点想像力,它要解决的目标值是纯粹的实数的数据,比如下一场考试得多少分,今年世界杯冠军是进几个球获胜,那个小伙能吸引到周边妹子的魅力值有多高等等。是不是一下子觉得很神奇,兴致就来了?!

再容我多说几句,分类预测与回归预测,同样是建模,解决的问题“可以是”不一样的(注意这个——可以是),简单地来看,分类要预测一个离散的标签,多个标签互相之间没有关系,目的是要选其中最恰当的一个;而回归是预测一个连续变化的数,且必须是在一定范围内有延续关系的数,预测的结果值是变化过程中的其中一个。分类和回归其实也能说有一些相同的地方,分类算法也是有预测到一个连续的值,但是这些连续值对应的是一个类别在概率上不同的面而已;而回归算法照样可以预测离散值,但是以整数形式预测离散值的,本质上是把类别下的每一个子类都按字典形式找一个数值对应上罢了。于是,得出一个奇妙的结论,分类和回归问题能够以合适的手段进行转换。这个结论的作用,就是说当以分类或回归之一进行机器学习找不到合适的算法训练出模型时,不妨尝试转换到另一个方向去寻求突破。

好了,胡诌了一些晕乎乎的理论后,本文继续使用ML.NET带来一个回归模型的案例,根据白葡萄酒的各项酿制成分参数来预测其品质好坏。这次的数据集取自著名的竞赛网站——Kaggle.com的其中一个考题UCI Wine Quality Dataset,数据内容类似如下:

fixed.acidity,volatile.acidity,citric.acid,residual.sugar,chlorides,free.sulfur.dioxide,total.sulfur.dioxide,density,pH,sulphates,alcohol,quality,id
6.5,0.28,0.35,15.4,0.042,55,195,0.9978,3.23,0.5,9.6,6,3900
7.3,0.19,0.49,15.55,0.058,50,134,0.9998,3.42,0.36,9.1,7,3901
6.4,0.16,0.32,8.75,0.038,38,118,0.99449,3.19,0.41,10.7,5,3902
7.4,0.19,0.3,12.8,0.053,48.5,229,0.9986,3.14,0.49,9.1,7,3903
...

各个字段说明是这样:

成分
1 - fixed acidity 非挥发性酸
2 - volatile acidity 挥发性酸度
3 - citric acid 柠檬酸
4 - residual sugar 剩余糖分
5 - chlorides 氯化物
6 - free sulfur dioxide 游离二氧化
7 - total sulfur dioxide 总二氧化硫
8 - density 密度
9 - pH 酸碱度
10 - sulphates 硫酸盐
11 - alcohol 酒精 输出标签 (品酒师的感受值):
12 - 品质(分值0-10) 其它:
13 - id (样本序号)

首先创建训练和预测用的数据结构:

public class WineData
{
[Column(ordinal: "")]
public float FixedAcidity;
[Column(ordinal: "")]
public float VolatileAcidity;
[Column(ordinal: "")]
public float CitricACID;
[Column(ordinal: "")]
public float ResidualSugar;
[Column(ordinal: "")]
public float Chlorides;
[Column(ordinal: "")]
public float FreeSulfurDioxide;
[Column(ordinal: "")]
public float TotalSulfurDioxide;
[Column(ordinal: "")]
public float Density;
[Column(ordinal: "")]
public float PH;
[Column(ordinal: "")]
public float Sulphates;
[Column(ordinal: "")]
public float Alcohol;
[Column(ordinal: "", name: "Label")]
public float Quality;
[Column(ordinal: "")]
public float Id;
} public class WinePrediction
{
[ColumnName("Score")]
public float PredictionQuality;
}

训练部分,这次使用了一个对象叫ColumnDropper,可以用来在训练开始前舍弃掉不需要的字段,比如id,对结果没有任何影响,因此可以去掉。

static PredictionModel<WineData, WinePrediction> Train()
{
var pipeline = new LearningPipeline();
pipeline.Add(new Microsoft.ML.Data.TextLoader(DataPath).CreateFrom<WineData>(useHeader: true, separator: ',', trimWhitespace: false));
pipeline.Add(new ColumnDropper() { Column = new[] { "Id" } });
pipeline.Add(new ColumnConcatenator("Features", "FixedAcidity", "VolatileAcidity", "CitricACID", "ResidualSugar", "Chlorides", "FreeSulfurDioxide", "TotalSulfurDioxide", "Density", "PH", "Sulphates", "Alcohol"));
pipeline.Add(new FastTreeRegressor());
var model = pipeline.Train<WineData, WinePrediction>();
return model;
}

评估部分,要注意三个值 ,Rmsj是均方根值,用来展示有效度的,LossFn是损失值,顾名思义损失的程度嘛,当然越低越好了,RSquared是误差值,用来反映拟合度好坏的,如果接近0甚至负数,说明训练出来的模型已瞎,还不如人眼了。

static void Evaluate(PredictionModel<WineData, WinePrediction> model)
{
var testData = new Microsoft.ML.Data.TextLoader(TestDataPath).CreateFrom<WineData>(useHeader: true, separator: ',', trimWhitespace: false);
var evaluator = new Microsoft.ML.Models.RegressionEvaluator();
var metrics = evaluator.Evaluate(model, testData);
Console.WriteLine("Rms=" + metrics.Rms);
Console.WriteLine("LossFn=" + metrics.LossFn);
Console.WriteLine("RSquared = " + metrics.RSquared);
}

预测部分,如上一篇那样,通过新版本的TextLoader进行加载,并且处理成集合。

static void Predict(PredictionModel<WineData, WinePrediction> model)
{
using (var environment = new TlcEnvironment())
{
var textLoader = new Microsoft.ML.Data.TextLoader(TestDataPath).CreateFrom<WineData>(useHeader: true, separator: ',', trimWhitespace: false);
var experiment = environment.CreateExperiment();
var output = textLoader.ApplyStep(null, experiment) as ILearningPipelineDataStep; experiment.Compile();
textLoader.SetInput(environment, experiment);
experiment.Run();
var data = experiment.GetOutput(output.Data);
var wineDatas = new List<WineData>();
using (var cursor = data.GetRowCursor((a => true)))
{
var getters = new ValueGetter<float>[]{
cursor.GetGetter<float>(),
cursor.GetGetter<float>(),
cursor.GetGetter<float>(),
cursor.GetGetter<float>(),
cursor.GetGetter<float>(),
cursor.GetGetter<float>(),
cursor.GetGetter<float>(),
cursor.GetGetter<float>(),
cursor.GetGetter<float>(),
cursor.GetGetter<float>(),
cursor.GetGetter<float>(),
cursor.GetGetter<float>(),
cursor.GetGetter<float>()
}; while (cursor.MoveNext())
{
float value0 = ;
float value1 = ;
float value2 = ;
float value3 = ;
float value4 = ;
float value5 = ;
float value6 = ;
float value7 = ;
float value8 = ;
float value9 = ;
float value10 = ;
float value11 = ;
float value12 = ;
getters[](ref value0);
getters[](ref value1);
getters[](ref value2);
getters[](ref value3);
getters[](ref value4);
getters[](ref value5);
getters[](ref value6);
getters[](ref value7);
getters[](ref value8);
getters[](ref value9);
getters[](ref value10);
getters[](ref value11);
getters[](ref value12); var wdata = new WineData()
{
FixedAcidity = value0,
VolatileAcidity = value1,
CitricACID = value2,
ResidualSugar = value3,
Chlorides = value4,
FreeSulfurDioxide = value5,
TotalSulfurDioxide = value6,
Density = value7,
PH = value8,
Sulphates = value9,
Alcohol = value10,
Quality = value11,
Id = value12,
};
wineDatas.Add(wdata);
}
}
var predictions = model.Predict(wineDatas); var wineDataAndPredictions = wineDatas.Zip(predictions, (wineData, prediction) => (wineData, prediction));
Console.WriteLine($"Wine Id: {wineDataAndPredictions.Last().wineData.Id}, Quality: {wineDataAndPredictions.Last().wineData.Quality} | Prediction: { wineDataAndPredictions.Last().prediction.PredictionQuality}");
Console.WriteLine();
}
}

最后调用Main函数部分。

static void Main(string[] args)
{
var model = Train();
Evaluate(model);
Predict(model);
}

好了,运行起来结果如下:

怎么样,没喝过酒咱也能当一把品酒师,专业程度照样不会差!

本案例代码和数据:下载

更多案例值得期待!

不少新入门的伙伴来问,有没有给力的学习课程,想早一点跨入机器学习的门槛,我在《机器学习课程不完全收录(持续更新)》收集了一些,都是容易学起来的课程,理论与实践都有,不论怎么说比我讲的要高出不知多少个档次了,可以按自己的喜好选择。

使用ML.NET实现白葡萄酒品质预测的更多相关文章

  1. 使用ML.NET实现NBA得分预测

    使用ML.NET实现NBA得分预测 导读:ML.NET系列文章 ML.NET已经发布了v0.2版本,新增了聚类训练器,执行性能进一步增强.本文将介绍一种特殊的回归--泊松回归,并以NBA比赛得分预测的 ...

  2. ML.NET

    ML.NET http://www.cnblogs.com/BeanHsiang/category/1218714.html 随笔分类 - 使用ML.NET实现NBA得分预测 摘要: 本文将介绍一种特 ...

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

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

  4. ML.NET指南

    ML.NET是一个免费的.开源和跨平台的机器学习框架,使您能够构建定制的机器学习解决方案,并将它们集成到您的. net应用程序.本指南提供了许多关于与ML.NET合作资源. 关于ML.NET的更多信息 ...

  5. R语言 多元线性回归分析

    #线性模型中有关函数#基本函数 a<-lm(模型公式,数据源) #anova(a)计算方差分析表#coef(a)提取模型系数#devinace(a)计算残差平方和#formula(a)提取模型公 ...

  6. 项目实战-使用PySpark处理文本多分类问题

    原文链接:https://cloud.tencent.com/developer/article/1096712 在大神创作的基础上,学习了一些新知识,并加以注释. TARGET:将旧金山犯罪记录(S ...

  7. ApacheCN C# 译文集 20211124 更新

    C# 代码整洁指南 零.前言 一.C# 代码标准和原则 二.代码审查--过程和重要性 三.类.对象和数据结构 四.编写整洁的函数 五.异常处理 六.单元测试 七.端到端系统测试 八.线程和并发 九.设 ...

  8. 使用ML.NET预测纽约出租车费

    有了上一篇<.NET Core玩转机器学习>打基础,这一次我们以纽约出租车费的预测做为新的场景案例,来体验一下回归模型. 场景概述 我们的目标是预测纽约的出租车费,乍一看似乎仅仅取决于行程 ...

  9. ML.NET 示例:回归之价格预测

    写在前面 准备近期将微软的machinelearning-samples翻译成中文,水平有限,如有错漏,请大家多多指正. 如果有朋友对此感兴趣,可以加入我:https://github.com/fei ...

随机推荐

  1. vue基础4-数据绑定

    1.v-bind 只能实现数据额单向绑定,从M到V,无法实现数据的双向绑定 改变页面输入框的值,打印数据并未改变. 2.v-model 可以实现数据的双向绑定,从M到V.V到M.  注意:v-mode ...

  2. Alpha冲刺(2/10)——2019.4.24

    作业描述 课程 软件工程1916|W(福州大学) 团队名称 修!咻咻! 作业要求 项目Alpha冲刺(团队) 团队目标 切实可行的计算机协会维修预约平台 开发工具 Eclipse 团队信息 队员学号 ...

  3. C#的排序Sort和OrderBy扩展方法

    可以实现一个IComparable接口的CompareTo方法,或者是给予List的Sort扩展方法,传入委托实现,举个例子: list.Sort((a, b) => { var o = a.s ...

  4. linux系统,关于Python多版本共存

    http://www.cnblogs.com/Yiutto/p/5962906.html 给个地址直接看八~

  5. Mac上使用jenkins+git持续集成浅析

    本文旨在让同学们明白如何让jenkis在mac笔记本上运行,并实际与一个最简单的git地址交互并执行简单的jenkins任务,如果学习本文,需要先按照https://www.cnblogs.com/x ...

  6. [HEOI2016/TJOI2016]游戏

    Description: 在2016年,佳缘姐姐喜欢上了一款游戏,叫做泡泡堂.简单的说,这个游戏就是在一张地图上放上若干个炸弹,看是否能炸到对手,或者躲开对手的炸弹.在玩游戏的过程中,小H想到了这样一 ...

  7. JS获取键盘事件

    <script type="text/javascript" language=JavaScript charset="UTF-8"> docume ...

  8. P2V后,VMWare ESX 上RedHat AS5网络不通问题的解决办法

    现象: 机器在启动eth0后,可以ping通eth0的IP,但是很快就无法访问了. 原因: red hat 5.x 默认系统安装完成后为xen内核,那么xen内核引导启动后就会有虚拟网卡(vethx. ...

  9. SpringBoot报错:nested exception is org.apache.ibatis.executor.ExecutorException: No constructor found in com.tuyrk.test.User matching [java.lang.Long, java.lang.String, java.lang.String]

    错误提示: Caused by: org.apache.ibatis.executor.ExecutorException: No constructor found in com.tuyrk._16 ...

  10. LeetCode 15 3Sum [sort] <c++>

    LeetCode 15 3Sum [sort] <c++> 给出一个一维数组,找出其中所有和为零的三元组(元素集相同的视作同一个三元组)的集合. C++ 先自己写了一发,虽然过了,但跑了3 ...