交叉验证法 —— 机器学习 5/7
测试模型的更好方法
在本课中,你将学习如何用交叉验证的方法来更好的衡量模型的表现。
简介
- 机器学习是一个迭代的过程。
- 你将会面临以下问题:用哪些变量来做预测,使用什么模型,模型的参数如何赋值等等。到目前为止,你是在使用验证数据集(或提供的数据集)验证模型质量的方法做出的选择。
- 但是这种方法也有一定的弊端,试想一下,你有一个5000行的数据集,你自然会选择20%的数据作为验证集,也就是1000行,但是这就为模型的评估造成了随机性。那就是,这个模型有可能在你选的1000行的数据集中表现很好,而在另外一个1000行的数据集中,精确度会很差。
- 一个极端的情况,你可以想象只有一行数据做验证集,如果你用它来比较多个可选的模型,那么哪一个模型在这一行数据中能做出做准确的预测纯粹是看脸。
- 总之,在我们测试模型时,更大的数据集意味着会有更小的随机性(又称“噪音”),那么最终得到的模型会更加可靠。很不幸,我们要想获得更大的验证集,我们的训练集就会更小,这就会直接影响模型的质量。
什么是交叉验证?
- 在交叉验证中,我们将模型运行在不同的数据子集上,以此来获得多重模型测试结果。
- 例如,我们可以将数据集分成5段,每份占20%,那么我们称我们将数据分成5“份”。
- 然后,我们每一份上运行一次实验。
- 第一次实验中 我们将第一份作为验证集,将其余的部分作为训练集,这就为我们提供了一个基于总数据集20的测试结果。
- 第二次实验中 我们将第二份作为验证集,也将其余的部分作为训练集,第二份数据就会被用来进行第二次测试。
- 我们一直重复这个过程,将每一份数据都做一次验证集。合计100%的数据集在某时刻都被用来测试模型,那么我们就得到了一个基于整个数据集的模型测试结果(即使我们没有同时都用到者100%的数据)。
什么时候要使用交叉验证呢?
- 交叉验证为我们提供了一个更精准的测试模型的方法,这在你要做很多模型决策的时候十分关键。但是它耗时也更长,因为他要测试多个模型(每份各一个)。
- 那么,衡量利弊,什么时候用交叉验证呢?
- 针对于小型数据集,当额外的计算负担不是那么大时,你应该使用交叉验证。
- 针对于大型数据集,单个验证集已经足够了。你的代码会跑的更快,而且你的数据集已经足够大,不需要再去重复从中抽取做验证。
- 大小数据集的界限没有那么明显。但是如果你的模型几分钟甚至更快可以跑完,那么你或许可以尝试交叉验证。
- 或者,你可以直接使用交叉验证,看看达到的结果是否相近。如果各个测试得到的结果都一样,那么就说明单一数据集就足够了。
案例
- 我们将继续使用前几次课程中的数据。同样加载X和有的过程省略了。
- 下面我们定义一个管道来填补丢失值,并且训练一个随机森林模型做预测。
- 虽然说不使用管道技术来做交叉验证是可能的,但是太复杂了。使用管道技术代码会变得清晰明了。
from sklearn.ensemble import RandomForestRegressor
from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer
my_pipeline = Pipeline(steps=[
('preprocessor', SimpleImputer()),
('model', RandomForestRegressor(n_estimators=50, random_state=0))
])
- 我们将使用scikit-learn的
cross_val_score()
函数来获得交叉验证的结果。通过参数cv
来指定份数。
from sklearn.model_selection import cross_val_score
# Multiply by -1 since sklearn calculates *negative* MAE
scores = -1 * cross_val_score(my_pipeline, X, y,
cv=5,
scoring='neg_mean_absolute_error')
print("MAE scores:\n", scores)
MAE scores:
[301628.7893587 303164.4782723 287298.331666 236061.84754543 260383.45111427]
scoring
参数表明使用那种衡量标准,本例中我们使用负平均绝对误差(MAE)。scikit-learn的官方文档提供了一系列其他选择。- 这里很奇怪的是他们居然使用的是负平均绝对误差。scikit-learn有一个传统,所有的度量标准都遵循一个值越大指标越好的传统,使用负值让他们保留了这种传统,即便这种用法在其他地方真的很少见。
- 我们想看单一的模型质量报告,来跟别的模型作比较,那我们对测试结果取平均值。
print("Average MAE score (across experiments):")
print(scores.mean())
Average MAE score (across experiments):
277707.3795913405
总结
使用交叉验证能够更好的评估模型的质量,而且还能使得代码更简洁:不知道你注意到没有,我么不再关注分割训练集和验证集了。所以,尤其是对于小型数据集来说,这是件好事。