《scikit-learn》交叉验证

本文介绍了在机器学习中,数据集通常被划分为训练集和测试集,但这种方式存在随机性和过拟合风险。为解决此问题,引入了验证集,进一步提出了交叉验证方法,特别是K折交叉验证,通过多次训练和评估模型来提高模型泛化能力。代码示例展示了如何使用Scikit-learn的cross_val_score进行交叉验证,并讨论了如何利用交叉验证结果的平均值作为模型性能指标。最后,提到了通过平均多个子模型的预测结果来提高预测稳定性。

当我们训练模型的时候,首先得要有数据进行训练。
我们拥有一定的数据集的时候,我们不会用所有数据去训练,因为这样我们会不知道训练出的模型的繁华能力如何,而是习惯于划分为训练数据集和测试数据集,在训练集上训练处模型,拿到测试集去做测试。而这种方式也不一定是最好的,因为,这种方式选择数据集是随机的,也许我们调的参数只是该训练集下是最优的,或许只是在特定的训练集和测试集是最有的,换了个样本集,或者是划分出的训练集就不是。
在这里插入图片描述

为了避免这种因样本选择带来的随机性影响,我们需要额外设置一个验证集,当模型训练完成以后,先在验证集上对模型进行评估,然后选择评估分数最高的模型,再在测试集上进行最终的测试
在这里插入图片描述

这是比较标准的模型评估过程,但是这也不是最优的办法。虽然验证集的设置可以有效避免测试集出现过度拟合的情况,但是现在元数据被分为 3 部分:训练集、验证集和测试集,训练集的数据量会大大减少,这可能造成训练模型的效果很差。另外,由于验证集和测试集是一次选择,所以最后的模型评估结果有很大的随机性。

于是我们便引入了交叉验证(Cross-validation)
交叉验证(Cross-validation)多次选择测试集做评估,有效避免了随机性带来的误差。而且交叉验证不需要选择验证集,这样就避免了数据的浪费,使训练集中有足够的样本数量。
交叉验证最基本的方法是 K折交叉验证(K-fold Cross Validation),原理如图

在这里插入图片描述

黑色是测试数据集,白色是训练数据集合。

它将原始数据分成K组(K-Fold),将每个子集数据分别做一次验证集,其余的K-1组子集数据作为训练集,这样会得到K个模型。这K个模型分别在验证集中评估结果,最后的误差MSE(Mean Squared Error)加和平均就得到交叉验证误差。

测试代码如下:
交叉验证唯一的缺点就是计算代价相对较高。实现交叉验证可以调用 Scikit 中提供的 cross_val_score 辅助函数。

from sklearn.datasets import load_boston
from sklearn.model_selection import cross_val_score
from sklearn.tree import DecisionTreeRegressor

boston = load_boston()  # 这里使用boston数据集
regressor = DecisionTreeRegressor(random_state=0)
res = cross_val_score(regressor, boston.data, boston.target, cv=10)  # 默认是R平方分数
print(res)
print(res.mean())  # 一般用这些模型score的平均值来作为总的k折交叉验证评价

regressor2 = DecisionTreeRegressor(random_state=0)
res = cross_val_score(regressor2, boston.data, boston.target, cv=10,
                      scoring="neg_mean_squared_error")  # 指定为负的均方差分数
print(res)
print(res.mean())  # 一般用这些模型score的平均值来作为总的k折交叉验证评价

当我们把测试数据分成10分的时候,会有10个评估分数,默认是R平方分数,可以自己指定成负的均方差。一般把这K个结果的平均值作为评估的指标。

也就是说,当我们有了一部分数据集,划分出了训练集和测试集,辛辛苦苦调了一些参数,比如超参数这些,最大深度,最小划分节点啊,评估方式啊之类的。在训练集和测试集上表现很好也可能是过拟合了,也许换了个数据集和划分集合就表现很差,为了打消这种由于样本划分导致的随机性,我们一般使用交叉验证,经过多次不同的划分,训练出多个参数模型,取它的平均值作为参数模型的衡量指标,更具有说服力。之后的博文会讲解使用交叉验证来选择最优的参数。

至于训练处的K个模型嘛,可以做一些简单的结果合成,我们可以对每个子模型做平均,取多数等操作,这样会更加稳定。如下实例:

from sklearn.datasets import load_boston
from sklearn.model_selection import cross_validate
from sklearn.tree import DecisionTreeRegressor
import numpy as np

cv_N = 10
boston = load_boston()  # 这里使用boston数据集
regressor = DecisionTreeRegressor(random_state=0)
cv_results = cross_validate(estimator=regressor, X=boston.data, y=boston.target, cv=cv_N
                            , return_estimator=True)
print(cv_results['test_score'])

# print(boston.target)
result = np.zeros(len(boston.data))
for i in range(cv_N):
    reg = cv_results['estimator'][i]
    result += reg.predict(boston.data)

result = result / cv_N  # 取多个模型预测的平均值
print(result - boston.target)  # 看看预测的差异,大部分应该是非常接近于0

这段代码展示了通过交叉验证得到了K个子模型,分别对数据进行预测,便可以得到一个整体评估的结果。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值