入门机器学习(西瓜书+南瓜书)模型的选择与评估总结(python代码实现)

一、理论总结

1.1 什么是机器学习?

机器学习是什么东西?简单来说,就是根据我们生活中根据经验阅历对未发生的事件做出预判的所谓“智能”,对机器本身通过计算手段,利用经验改善系统自身的性能。即使得计算机从数据中产生“模型”的算法。
比较形象的类比如下图所示,很直观形象的反映了机器学习的思想。
在这里插入图片描述

1.2 基本术语

在这里插入图片描述

数据集(data_set):就是一个存储数据的集合,一般有图片或者包含数字的表格。如上图所示,一个表格就可以代表一个数据集。
样本(sample):可以理解为一行数据,或者一张图片。就是组成数据集的单元。比如第二行的数据就是一个样本,也就是一个西瓜的数据。
属性(attribute)或特征(feature):就是一行数据可能包含的不同类型的数据,比如西瓜的“根蒂”,“纹理”,”颜色“等,这些组成了属性或者说特征。数据集中的所有属性个数也被称作维数。就是上面数据集的列
属性值(attribute value):直观说就是西瓜的属性有哪些取值,比如颜色这个属性有“青绿”,“乌黑”,这些就是称为属性值。就是一列中所有取值的集合
样本空间(sample space):把数据集中的所有属性作为坐标轴,所有可能的属性的取值就包含在了样本空间中。就是数据集所有可能取值的集合。
训练(training) 或 学习(learning):从数据中学习模型,这里的模型可以简单理解为一个数学公式。也可以简单理解对于一个包含未知变量的方程,通过带入(自变量【数据】,因变量【标签】)来确定这一个公式,进一步利用公式,对于一个自变量【数据】,获得未知的因变量【标签】。
测试(testing):简单来说训练就是平时刷题总结知识点,考试出一套试卷,让你做,然后得出试卷成绩,从而判断你的学习效果。
有监督学习(supervised learning):每个【数据】都包括【标签】,就是说每道题都有答案,你可以根据自己做题的情况来调整自己的学习方向。代表算法为分类和回归。大白话说分类也叫逻辑回归,就是两种数据找一条线或面划开,一边是一类。回归可以理解,给你一堆点,用一条直线或曲线平滑的连起来。
无监督学习(unsupervised learning):只有数据没有标签,根据数据本身特征进行总结归纳,了解数据的内在规律,代表算法为聚类。
独立同分布(indenpendent and identically,简称iid):通常假设样本空间(就是样本组成的空间,类似坐标系)中全体样本服从一个未知的“分布(distribution)”,我们获得的每个样本都是独立地从这个分布获得地,即“独立同分布”。很容易理解,我们获得地样本越多,就越有可能通过学习获得具有泛化能力的模型。
具体细节请详见西瓜书2页,南瓜书第1页。

1.3 模型评估与选择

1.3.1 机器学习的模型

机器学习基于数据,从数据中学得的模型的过程称为“学习(learning)”或“训练(training)”。学得模型对应了关于数据的的某种内在规律,因此亦称“假设(hypothesis)”,这个假设大白话说就是你用数据学到的知识。而这种潜在规律自身,则称为“真相”或“真实(ground-truth)”,这里的真相就是数据本身具有的规律。我们现在做的就是用数据学到这些规律,当然不会很容易就学明白,也就是你用数据学到的知识和数据本身具有的规律相同。所以我们要尽可能的逼近真相。这个学到的知识就是模型(model),他可以是一个公式,也可以是几个公式。模型也叫“学习器(leaner)”.

1.3.2 过拟合与欠拟合

模型训练的怎么样呢?首先介绍两个概念,就是“过拟合”和“欠拟合”。
欠拟合:就是模型没有学到训练集中的数据特征,在训练集上的效果就很差,最主要的原因就是学习率太低或模型学习能力太差。
过拟合:模型拟合数据能力过强,也就是可以完美了拟合训练数据,但是过于追求完美,使得模型复杂度很高,而使得在测试集效果不好,也就是说使得模型泛化能力下降。解决这一问题可以加入更多的数据或者加入正则化项约束模型

1.3.3 评估方法

我们对模型训练是否好?总要有一个评判标准,就是你学到的,和真实的是否一致?就是说你不是要逼近真相吗?逼近到哪里了?
这里介绍三种方法:
(1)留出法
最简单也最常用的方法,也就是根据比例随机分配训练集和测试集。比如要求训练集和测试集的比例为8:2.那么就从数据集中随机选取80%的数据做训练集,用来训练模型,20%的数据用来测试模型的性能,常见的做法为将大约 2 3 \frac {2}{3} 32~ 4 5 \frac {4}{5} 54
(2)交叉验证法
也叫K折交叉验证法(K-fold cross validation)。就是把数据集分为K分,把K份按照顺序依次选取一份作为测试集。其余数据作为训练集测试模型结果,将K分结果求和求均值,进而获得模型的性能指标。
(3)自助法
从m个样本的数据集又放回的选取m个样本,其中出去重复的样本,从而获得理论上获得 2 3 \frac {2}{3} 32的数据来训练,其余数据用作测试。这种方法在数据集较小,难以有效划分训练、测试集时很有用,此外,自助法能从数据集中产生不同的训练集,这对集成学习有很大好处,到那时它该改变了数据集的初始分布,会引入估计误差。

1.3.4 奥卡姆剃刀(Occam‘s razor)

我们之前说到,对于同一批次的数据,我们学习算法必须有某种偏好,就是线性与非线性,回归与分类等。才可以学习到对应的东西。那回归来说,如图所示,同样的数据,两条不同地拟合曲线。,我该信谁呢?总要给个理由吧,而且这俩都完美的拟合了我给的数据,那个更好呢?答案是A,你也许会为啥?答案是:错怕了。因为B太放飞自我了,太个性化了,这样的曲线要么非常好而且概率很低,要么很差。而A相对稳定,有误差的话也不会太大。因此,我们还是选稳重可靠的A,这样的特点,机器学习中叫做鲁棒性
在这里插入图片描述
那么是不是意味着,A一定B好呢?不一定,我们看下图,黑点是我给的数据,而白点是我没给地数据。在(a)图中,A好于B,但在(B)图中,B地个性化完美符合数据。则B好于A.
有趣的是,这个结论对任何算法都成立,就是说我训练好模型,用模型上的点说这就是我没给的数据,这样别人的模型再怎么厉害,也没你的模型厉害。这就导致一个结论:凡事皆有可能(Nothing is impossible),官方叫法叫做没有免费午餐定理。这样是不是就意味着“所有算法的性能和随机乱猜差不多”那还有什么好学呢?其实不然,因为我们的算法,往往是一个具体的问题,这里本身就排除了很多的其他模型的可能。
在这里插入图片描述

1.4 调参

大多数的学习算法具有超级参数,就是说需要人为调节,这些数值的选取往往根据经验来进行。那对于训练的模型内部参数可以再从数据集中划分一个验证集,来对模型的训练方向进行指导。基于验证集上的性能进行选择和调参。

1.5 损失函数

也可以被称为误差函数,也就是模型的预测和实际真实值之前的差距,我们自然需要他们之间的差距越小越好。所以需要构建损失函数,来计算差距,反应模型训练的效果。
常见的损失函数有均方误差、均方根误差、平均绝对误差。

均方误差 M S E = 1 n ∑ i = 1 n ( p i − p i ) 2 MSE = \frac{1}{n}\sum_{i=1}^{n}(p^{i}-p^{i})^{2} MSE=n1i=1n(pipi)2
均方根误差 R M S E = 1 n ∑ i = 1 n ( y i − p i ) 2 RMSE = \sqrt{\frac{1}{n}\sum_{i=1}^{n}(y_{i}-p_{i})^2} RMSE=n1i=1n(yipi)2
平均绝对误差 M A E = 1 n ∑ i = 1 n ∣ y i − p i ∣ MAE = \frac{1}{n}\sum_{i=1}^{n} |y^i-p^i| MAE=n1i=1nyipi

1.6 评价指标

1.6.1 经验误差

最好想也最容易理解的就是正确率和错误率,对于一个模型学完以后我要看他学的如何?对于我给的数据,让他给结果,看是否与结果一样或相类似。
就是那模型学到的,对我给的数据进行预测结果。看你预测的是否对?错了几个,除以总共给了多少个就是错误率。其实跟考试差不多。你不是nb吗?你这模型考多少分啊?
这里有个问题,就是我给模型测试的都是我给过的问题?正如《卖车》小品里的脑筋急转弯,我给他都是打过的问题,他再次回答当然更可能对了。可是我给他新问题,他或许就不会了?
那这该怎么办呢,我们可以给他新的数据,让他预测,这就好比,平时做做模拟卷,考试在做一考试卷子?这俩很大程度是不同的,但是知识点差不多。就看模型是不是把知识点搞透了,可以举一反三。

1.6.2 模型的评估方法

模型的评价方法
模型判定推荐的模型判定不推荐的
测试集中被推荐的(被检索到)True positives(TP 正类判断为正类)(搜到的也想要的)False positives(FP 负类判断为正类)(搜到的但没用的)
测试集中不被推荐的(未被检索到)False negatives(FN 正类判断为负类)(没搜到,然而实际想要的True negatives(TN 负类判定为负类)(没搜到也没用的)

这个表格就是机器学习里面最常见的混淆矩阵,用来评判模型的好坏。

1.6.3 具体例子分析

先假定一个具体场景作为例子。
假如某个班级有男生80人,女生20人,共计100人.目标是找出所有女生.
某人挑选出50个人,其中20人是女生,另外还错误的把30个男生也当作女生挑选出来了.
作为评估者的你需要来评估(evaluation)下他的工作。
我们需要先需要定义TP,FN,FP,TN四种分类情况。
按照前面例子,我们需要从一个班级中的人中寻找所有女生,如果把这个任务当成一个分类器的话,那么女生就是我们需要的,而男生不是,所以我们称女生为"正类",而男生为"负类"。

相关(Relevant),正类无关(NonRelevant),负类
被检索到(Retrieved)TP=20 true positives(TP 正类判定为正类,例子中就是正确的判定"这位是女生")FP=30 false positives(FP 负类判定为正类,“存伪”,例子中就是分明是男生却判断为女生)
未被检索到(Not Retrieved)FN=0 false negatives(FN 正类判定为负类,“去真”,例子中就是,分明是女生,这哥们却判断为男生–梁山伯同学犯的错就是这个)TN=50 true negatives(TN 负类判定为负类,也就是一个男生被判断为男生)

通过这张表,我们可以很容易得到例子中这几个分类的值:TP=20,FP=30,FN=0,TN=50。

1.6.4 显示反馈数据分析

我们可以通过计算模型分类的准确率,和召回率进来通过计算F-Measure的值来对模型分类的好坏进行评价。
下面结合例子中这几个分类的值:TP=20,FP=30,FN=0,TN=50介绍准确率,召回率,和F-measure的概念与计算方法。
1.准确率
准确率(precision)又称“精度”,“正确率”。的公式是 P = T P T P + F P P=\frac{TP}{TP+FP} P=TP+FPTP,它计算的是所有被检索到的item(TP+FP)中,“应该被检索到的item(TP)”占的比例。
在例子中就是希望知道分类得到的所有人中,正确的人(也就是女生)占有的比例.所以其precision也就是40%(20女生/(20女生+30误判为女生的男生)).
2.召回率
召回率(recall)又称“查全率”的公式是 R = T P T P + F N R=\frac{TP}{TP+FN} R=TP+FNTP ,它计算的是所有检索的item(TP)占所有"应该被检索到的item(TP+FN)"的比例。
在例子中就是希望知道此君得到的女生占本班中所有女生的比例,所以其recall也就是100%(20女生/(20女生+ 0 误判为男生的女生))
3. 准确率与召回率的关系
“精确率”与“召回率”虽然没有必然的关系(从上面公式中可以看到),然而在大规模数据集合中,这两个指标却是相互制约的。
由于“检索策略”并不完美,希望更多相关的文档被检索到时,放宽“检索策略”时,往往也会伴随出现一些不相关的结果,从而使准确率受到影响。
而希望去除检索结果中的不相关文档时,务必要将“检索策略”定的更加严格,这样也会使有一些相关的文档不再能被检索到,从而使召回率受到影响。
凡是涉及到大规模数据集合的检索和选取,都涉及到“召回率”和“精确率”这两个指标。而由于两个指标相互制约,我们通常也会根据需要为“检索策略”选择一个合适的度,不能太严格也不能太松,寻求在召回率和精确率中间的一个平衡点。这个平衡点由具体需求决定。
4.P-R图
这里怕大家迷,我有把混淆矩阵的表格拿上来了

真实情况\ 预测结果正例反例
正例TP(真正例)FN(假反例)
反例FP(假正例)TN(真反例)

查准率和查全率分别定义为:
P = T P T P + F P P=\frac{TP}{TP+FP} P=TP+FPTP
R = T P T P + F N R=\frac{TP}{TP+FN} R=TP+FNTP
观察两个公式,发现只有分母的一个数据不同是FP和FN,对于P大白话就是预测正例中有多少个正确的,R就是正例中都多少个被预测对了。这俩一般是相互矛盾的,就是此起彼伏。两个极端情况就是,我全预测正例,那么R一定是是1,因为所有的样本都被预测为正例,那么正例一定都被预测对了。但是P就很低了,因为你把反例也预测为正例了。或者你相当谨慎,生怕预测错误,预测正例相当保守,以至于一些正例你都因为不确定没有预测正例。那么你P一定很高,那么因为你没找到一些正例,因此R就要低。
刚才讲到我们让模型从数据中学到知识,然后用新题来考他,那么对于正例负例来说,模型往往会给一个0到1数值,也就是说这个数值越大,越倾向于他是正例,越小越倾向于是负例。因此我们把这些结果从大到小排序。从第一个开始,第一次就认为第一个数值最大的是正例,其余都是负例。给出P和R,然后第二次认为前两个是正例,其余是负例。给出P到R,以此类推,知道最后全是正例。这样我们就得到了一个P-R图,如图所示,A,B,C分别是三个模型的P-R图,其中有三个平衡点(Break-Even-Point,简称BEP) 就是曲线和y=x的交点,意味着P=R。
那么,这三个模型那个最好呢?
答案是A。因为A的面积大,这也就说明A模型在P和R相同的情况下,他的R或P更大。
在这里插入图片描述

5. F-Measure值
当然其实不必非要画P-R图这么麻烦,我们可以将P,R用一个公式表示代表一个指标,这就是F-Measure值。
F-Measure又称为F-Score是一种统计量,是IR(信息检索)领域的常用的一个评价标准,常用于评价分类模型的好坏。它的计算公式为 F β = ( β 2 + 1 ) P R β 2 ⋅ P + R F_{\beta}=\frac{(\beta^{2}+1)PR}{\beta^2\cdot P+R} Fβ=β2P+R(β2+1)PR,其中β是参数 , R是召回率(recall P是准确率(precision)
当参数β=1时,就是最常见的F1-Measure了: F 1 = 2 P ⋅ R R + P F_{1}=\frac{2P \cdot R}{R+P} F1=R+P2PR,此时F1综合了P和R的效果,当F1较高时则能说明试验方法比较有效。
当参数β>0时,度量了查全率对查准率的相对重要性;
当参数β>1时,查全率更重要
当参数β<1时,查准率更重要。

1.6.5 ROC与AUC

这里我们在介绍两个概念:
FPR(假正例率):预测为正例并且预测错了的数量占真实类别为反例样本的比例。
TPR(真正例率):预测为正例并且预测正确的数量占真实类别为正例样本的比例。
F P R = F P F P + T N FPR=\frac{FP}{FP+TN} FPR=FP+TNFP
T P R = T P F N + F N TPR=\frac{TP}{FN+FN} TPR=FN+FNTP
与P和R原理相同,易知假正例率与真正例率变化方向相同
我们在这里举个例子:
在这里插入图片描述
这样我们就可以根据TPR和FPR画出ROC曲线了,如图所示,因为样本点少,并不是曲线
在这里插入图片描述
当类别和阈值更多时,它将成为一个曲线,如图所示:
在这里插入图片描述
如图所示,这是两个模型的ROC曲线,与P-R曲线一样。ROC去年的面积大小也反映模型性能的好坏。而这个面积就是AUC值。关于ROC曲线和AUC的数学推导,详见南瓜书11页公式(2.20)
(1)一个模型的ROC曲线完全包住了另外一个模型的ROC曲线,则前者的性能优于后者,A优于B;
(2)AUC:ROC曲线与横轴所围成的面积,AUC越大,模型的分类性能就越高。

在这里插入图片描述
具体细节请详见西瓜书24页,南瓜书第2页。

二、python代码实现

笔者水平有限,如有错误请多指教。

2.1 sklearn 中的性能指标

accuracy_score:精度
precision_score:查准率
recall_score:查全率
f1_score:F1指标
roc_auc_score:ROC曲线AUC指标
confusion_matrix:混淆矩阵

# !/usr/bin/env python
# @Time:2022/3/15 21:20
# @Author:华阳
# @File:1.py
# @Software:PyCharm

# accuracy_score的参数
# precision_score的参数
# recall_score的参数
# y_true:为样本真实标签,类型为一维的ndarray或者list
# y_predict:为模型预测标签,类型为一维的ndarray或者list

from sklearn.metrics import accuracy_score,precision_score,recall_score,f1_score,confusion_matrix
import numpy as np
from sklearn.metrics import roc_auc_score


y_true = [0, 0, 1, 1]
y_predict = [1, 0, 1, 0]

print("正例的准确率为:",accuracy_score(y_true, y_predict))
print("查准率为:",precision_score(y_true, y_predict))
print("查全率为:",recall_score(y_true, y_predict))
print("F1指数为:",f1_score(y_true, y_predict))
print("混淆矩阵为:",confusion_matrix(y_true,y_predict))

# y_true为真实标签
# y_score为预测为Positive的概率
y_true = np.array([0, 0, 1, 1])
y_score = np.array([0.1, 0.4, 0.35, 0.8])
print("ROC曲线auc指标",roc_auc_score(y_true, y_score))


结果:


正例的准确率为: 0.5
查准率为: 0.5
查全率为: 0.5
F1指数为: 0.5
混淆矩阵为: [[1 1]
 [1 1]]
ROC曲线auc指标 0.75

三、参考文献

1.《机器学习》周志华著,清华大学出版社
2.《南瓜书》Datawhale团队著

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐