深入浅出Python机器学习11——模型的评估与优化

1、使用交叉验证进行模型评估
  • scikit-learn 中的交叉验证

        在统计学中,交叉验证法是一种非常常用的对于模型泛化性能进行评估的方法。和之前用的 train_test_split 方法所不同的是,交叉验证法会反复地拆分数据集,并用来训练多个模型。所以我们说这种方法更加粗暴。
       在 scikit-learn 中默认使用的交叉验证法是 K折叠交叉验证法 ( k-fold cross validation )。这种方法将数据集拆分成 k 个部分,再用 k 个数据集对模型进行训练和评分。
       此外,交叉验证法中还有其他的方法,例如 “ 随机拆分交叉验证法 ” ( shuttle-split cross validation)和 “ 挨个试试 ”(leave-one-out)法。
       下面演示一下交叉验证法的使用方法:
show-cross-validation
       上述程序中,先导入了 scikit_learn 的交叉验证评分类,然后使用 SVC 对酒的数据集进行分类,在默认情况下,cross_val_score 会使用 3 个 折叠,因此上面的到的是 3 个分数。
       我们一般选取 3 个得分的平均分。如下:
mean.score
       可以看出,在酒的数据集中,交叉验证平均分为 0.928 分。
       如果要将数据集拆分为 6 个部分来评分,只要修改 cross_val_score 的 cv 参数就可以了。
cv6
       然后使用 score.mean() 来获得分数平均值,
cv6-mean
       这时候模型平均得分为 0.944,说明模型表现还是不错的。需要注意的是,在scikit-learn 中,cross_val_score 对于分类模型默认使用的是 k 折叠交叉验证,而对于分类模型则默认使用分层 k 交叉验证法。
       进一步解释什么是分层 k 折叠交叉验证:
k-fold
       从结果可以看出,如果用不分层的 k 折叠的交叉验证法,那么在拆分数据集的时候,有可能每个子集中都是同一个标签,这样的话模型评分都不会太高。而分层 k 折叠交叉验证法的优势在于,它会在每个不同分类中进行拆分,确保每个子集中都有数量基本一致的不同分类标签。例如在一个人口性别数据集中,其中有 80% 的男性和 20% 的女性,分层 k 折叠交叉验证法就会保证在你的每个子集中,都有80% 的男性和 20% 的女性。

  • 随机拆分和 “ 挨个试试 ”

       随机拆分的原理是,先从数据集中随机抽一部分数据集作为训练集,再从其余的部分随机抽一部分作为测试集,进行评分后再迭代,重复上一步的动作,直到把我们希望迭代的次数全部跑完。如下试验:
shufflesplit
       上述中把每次迭代的测试集设置为数据集的 20%,而训练集设置为数据集的 70%,并且把整个数据集拆分成 10 个子集。ShuffleSplit 一共为 SVC 模型进行了 10 次评分。而模型最终的得分也就是 10 个分数的平均值。

       “ 挨个试试 ” 有点像 k 折叠交叉验证,不同的是,它把每一个数据点都当成一个测试集,所以数据集里有多少样本,它就要迭代多少次。如果数据集太大的话,这个方法还是挺耗时的。但是如果数据集小的话,它的评分准确度是最高的。例如下面的实验:
leaveoneout
       由于样本有178个,这意味着要迭代 178 次,最后给出的评分是 0.955。

  • 为什么要使用交叉验证法

       既然有了 train_test_split 为何还要使用交叉验证法,毕竟交叉验证法最后对模型进行的评分也只是一个平均数而已!
       原因是,当我们使用 train_test_split 方法进行数据集拆分时,train_test_split 用的是随机拆分的方法,万一我们拆分的时候,测试集中都是比较容易进行分类或者回归的数据,而训练集中都比较难,那么模型的得分就会偏高,反之模型的得分就会偏低。我们又不太可能把所有的 random_state 遍历一遍。而交叉验证法正好弥补了这个缺陷,它的工作原理导致它要对多次拆分进行评分再取平均值,这样就不会出现前面所说的问题。
       此外,train_test_split 总是按照 25%~75%的比例来拆分训练集和测试集(默认情况下),但是我们使用交叉验证法的时候,可以更加灵活的指定训练集和测试集的大小,例如当 cv=10 的时候,训练集就会占整个数据集的 90%,测试集占 10%;cv=20,训练集的占比就会达到 95%,而测试集占比 5%,这意味着训练集会更大,对于模型的准确率也有促进作用。
       不过交叉验证法往往比 train_test_split 更加消耗计算资源。

2、使用网格搜索优化模型参数

       在之前提到的算法模型中,基本上是通过逐个尝试不同的参数对于模型泛华表现的影响,这种方法固然有效果,不过我们还可以使用一点小技巧,能够让我们一次性找到相对更优的参数设置。

  • 简单网格搜索

       例如下面的 lasso 算法实现了不同正则化系数 alpha 和 不同最大迭代次数 max_iter 中寻找最优:
diff-lasso
       可以看出,利用网格搜索法,很快就找到了模型的最高分,以及其对应的参数。
       这种方法有一定的局限性,因为我们所得到的 16 次评分都是基于同一个训练集合测试集,这只能代表模型在该训练集合测试集的得分情况,不能反映出新的数据集的情况,例如修改一下 train_test_split 的 random_state 参数如下:
change-value
       可以看出,稍微对 train_test_split 拆分数据集的方式做一点变更,模型的最高得分就降低到了 0.83,而此时 lasso 模型的最佳 alpha 参数也由 0.01 变成了 0.1。为了解决这个问题,可以使用前面介绍的交叉验证法和网格搜索法结合起来寻找最优参数。

  • 与交叉验证结合的网格搜索

       下面用实例学习如何将交叉验证法与网格搜索法结合起来找到模型的最优参数。

cross-mesh
       这里就只用先拆好的 X_train 来进行交叉验证,以便于我们找到最佳参数后,再用来拟合 X_test 来看一下模型的得分。

best-model
       得分为 0.819,模型变坏,不过这并不是参数的问题,而是 lasso 算法对样本的特征进行正则化,导致一些特征的系数变成 0,也就是说抛弃了一些特征值。对于酒的数据集来说,特征数量并不多,因此使用 lasso 来进行分类的话,得分相对低一些。
       下面我们使用 scikit-learn 中的一个内置类 GridSearchCV,有了这个类,我们进行参数调优的过程就会稍微简单一些。例如上面这个例子:
GridSearchCV
       可以看到程序更加简洁,在使用 GridSearchCV 得到的结果和我们之前使用 cross_val_score 结合网格搜索得到的结果是一样的。但需要说明的是,在 GridSearchCV 中还有一个属性称为 best_score_,这个属性会存储模型在交叉验证中所得的最高分,而不是测试数据集上的得分:
CV-best
       回顾之前使用 cross_val_score 进行评分的步骤,会发现得分与其相一致。这说明 GridSearchCV 本事是将交叉验证和网格搜索封装在一起的方法。这样的话,我们完全可以采用这种方法来对参数进行调节。
       GridSearchCV 虽然是个非常强悍的功能,但由于需要反复建模,因此需要的计算时间往往更长。

3、分类模型的可信度评估

       分类算法的目标是为目标数据的预测结果是离散型的数值,但实际上算法在分类过程中,会认为某个数据点有“80%”的可能性属于分类1,而有“20%”的可能性属于分类0,那么在最终的结果中,模型会依据“可能性”比较大的范式来分配分类标签。其实就是谁发生的概率大就选谁

  • 分类模型中的预测准确率

       在scikit-learn中,很多用于分类的模型都有一个predict_proba功能,这个功能就是用于计算模型在数据集分类时,每个样本属于不同分类的可能性多少。我们用make_blobs来制作数据集,以及将样本数据方差设置高点(cluster_std=5),可以得到下面的结果。
proba
       如果紫色的表示“好”,而绿色的表示“不好”,那么中间重合部分就可以表示成“还好”。下面是使用高斯朴素贝叶斯来进行分类,
       结果表明,在predict——proba属性中存储了50个数组(也就是测试数据集的大小),每个数组中有两个元素。
proba.shape
       打印前5个结果,
lead5
       反映的是所有测试集中前5个样本的分类准确率,例如第一个数据点,有98.8%的概率属于第一个分类,而只有不到1.2%的概率属于第二个分类。
       可以用图像更加直观的反映 predict_proba 在分类过程中的表现:

proba-picture       从结果可以看出,半透明的深色圆点和浅色圆点代表的是测试集中的样本数据。浅色区域代表第一个分类,而深色区域代表另一个分类,在两个区域中间有一部分渐变色的区域,处于这个区域中的数据点便是模型觉得 “ 还可以 ” 的那一部分。
       注意:并不是每个分类算法都有 predict_proba 属性,不过我们还可以使用另外一种方式来检查分类的可信度,就是决定系数 decision_function。

  • 分类模型中的决定系数

       和预测准确率类似,决定系数 decision_function 也会给我们返回一些数值,告诉我们模型认为某个数据点处于某个分类的 “ 把握 ” 有多大。不同的是,在二元分类任务中,它只会返回一个值,如果是正数,则代表该数据点属于分类 1;如果是负数,则代表属于分类 2。由于高斯朴素贝叶斯没有 decision_function 属性,这里用支持向量机 SVC 算法来进行建模:
SVC

       从结果中可以看出,5 个数据点中,有 4 个 decision_function 数值为正数,1 个为负数。这说明 decision_function 为正的 4 个数据点属于分类 1,而 decision_function 为负的那 1 个数据点属于分类 2。
       下面图形化的方式演示一下 decision_function 工作原理:

SVC-picture
        可以发现,SVC 的 decision_function 和 GaussianNB 的 predict_proba 有相似的地方,但也有很大的差异。在上图中,分类同样是用浅色和深色区域来表示,如果某个数据点所处的区域浅色越明显,说明模型越确定这个数据点属于分类 1,反之则属于分类 2,而那些处于渐变色区域的数据点,则是模型觉得 “ 模棱两可 ” 的数据点,也就是之前说的 “ 还可以 ” 那种。

       注意:这里使用的都是只有两个分类的数据集,即二元分类任务,但是 predict_proba 和 decision_function 同样适用于多元分类任务,可以调整 make_blobs 的 centers 参数进行试验。

4、.score 给模型评分的方法
       对于分类模型来说,默认情况下 .score 给出的评分是模型分类的准确率 ( accuracy ),而对于回归模型来说,默认情况下 .score 给出的是回归分析中 $R^{2}$ 分数,在中文当中有翻译成可决定系数,或者拟合优度。 $R^{2}$ 分数的计算方法是用 “ 回归平方和 ”(explain sum of squares,ESS)除以 “ 总变差 ” (total sum of squares,TSS),计算公式为

R 2 = 1 − ∑ ( y − y ^ ) 2 ∑ ( y − y ‾ ) 2 R^2 = 1 - \frac{\sum(y-\hat{y})^2}{\sum(y-\overline{y})^2} R2=1(yy)2(yy^)2

       除了上面所说的准确率和 R 2 R^{2} R2 分数,还可以使用其他的方法来对模型进行评分,如精度(Precision)、召回率(Recall)、f1 分数(f1-score)、ROC(Receiver Operating Characteristic Cruve)、AUC(Area Under Curve)。在实践当中,这几种评分方法也都非常常用,它们和网格搜索法经常配合在一起使用。
       在 scikit-learn 中,使用网格搜索 GridSearchCV 类时,如果要改变评分的方式,只需修改 scoring 参数即可。例如,我们要对随机森林分类进行评分,我们可以如下写程序:

#修改 scoring 参数为 roc_auc
grid = GridSearchCV(RandomForestClassifier(), param_grid = param_grid, scoring = 'roc_auc') 

       这样模型评分的方式就是 roc_auc 方式了。
       在真实世界中,大部分数据集都不像实验中的数据集那样规范,因此模型评估和参数调节的方法可能是数据科学家们必备的知识之一。而不同的方法适合不同的数据集,所以先了解数据集才是至关重要的。

       小编机器学习学的一般,只是日常做做比记加深一下印象,望读者不吝赐教,谢谢!

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值