机器学习之交叉验证汇总及其Python代码

交叉验证是什么?
在模型建立中,通常有两个数据集:训练集(train)和测试集(test)。训练集用来训练模型;测试集是完全不参与训练的数据,仅仅用来观测测试效果的数据。

一般情况下,训练的结果对于训练集的拟合程度通常还是挺好的,但是在测试集总的表现却可能不行。比如下面的例子:


 图一的模型是一条线型方程。 可以看到,所有的红点都不在蓝线上,所以导致了错误率很高,这是典型的不拟合的情况
图二 的蓝线则更加贴近实际的红点,虽然没有完全重合,但是可以看出模型表示的关系是正确的。
图三,所有点都在蓝线上,这时候模型计算出的错误率很低,(甚至将噪音都考虑进去了)。这个模型只在训练集中表现很好,在测试集中的表现就不行。 这是典型的‘过拟合’情况。

总结思想:进行交叉验证目的是为了充分利用训练数据,最大程度利用训练数据,以获得一个较好的模型,防止模型欠拟合或者过拟合。 

交叉验证:就是在训练集中选一部分样本用于测试模型。
保留一部分的训练集数据作为验证集/评估集,对训练集生成的参数进行测试,相对客观的判断这些参数对训练集之外的数据的符合程度。
 

留一验证(LOOCV,Leave one out cross validation )
只从可用的数据集中保留一个数据点,并根据其余数据训练模型。此过程对每个数据点进行迭代,比如有n个数据点,就要重复交叉验证n次。例如下图,一共10个数据,就交叉验证十次。

 优点:
适合小样本数据集
利用所有的数据点,因此偏差将很低
缺点:
重复交叉验证过程n次导致更高的执行时间
测试模型有效性的变化大。因为针对一个数据点进行测试,模型的估计值受到数据点的很大影响。如果数据点被证明是一个离群值,它可能导致更大的变化
 

总结:实际中基本不用 

LOOCC是保留一个数据点,同样的你也可以保留P个数据点作为验证集,这种方法叫LPOCV(Leave P Out Cross Validation)
下面给出LPOCV代码:

from sklearn.model_selection import LeavePOut
lpo = LeavePOut(p=200)
for k, (train_index, test_index) in enumerate(lpo.split(train)):
    train_data, test_data, train_target, test_target = train.iloc[
        train_index], train.iloc[test_index], target[train_index], target[
            test_index]

普通交叉验证:
交叉验证的步骤如下:

保留一个样本数据集, (取出训练集中20%的样本不用)
使用数据集的剩余部分训练模型 (使用另外的80%样本训练模型)
使用验证集的保留样本。(完成模型后,在20%的样本中测试)
如果模型在验证数据上提供了一个肯定的结果,那么继续使用当前的模型。
 

优点: 简单方便。直接将训练集按比例拆分成训练集和验证集,比如50:50。


缺点: 没有充分利用数据, 结果具有偶然性。如果按50:50分,会损失掉另外50%的数据信息,因为我们没有利用着50%的数据来训练模型。

Python 使用train_test_split  案例:

# 切分数据 训练数据80% 验证数据20%
train_all, test_all, train_target, test_target = train_test_split(
    traindf, target, test_size=0.2, random_state=0)

K折交叉验证(k-fold cross validation)

针对上面通过train_test_split划分,从而进行模型评估方式存在的弊端,提出Cross Validation 交叉验证。
Cross Validation:简言之,就是进行多次train_test_split划分;每次划分时,在不同的数据集上进行训练、测试评估,从而得出一个评价结果;如果是5折交叉验证,意思就是在原始数据集上,进行5次划分,每次划分进行一次训练、评估(每次都是一个普通的交叉验证),最后得到5次划分后的评估结果,一般在这几次评估结果上取平均得到最后的 评分。k-fold cross-validation ,其中,k一般取5或10。

 

 优点:
适合大样本的数据集
经过多次划分,大大降低了结果的偶然性,从而提高了模型的准确性。
对数据的使用效率更高。train_test_split,默认训练集、测试集比例为3:1。如果是5折交叉验证,训练集比测试集为4:1;10折交叉验证训练集比测试集为9:1。数据量越大,模型准确率越高。
缺点:未考虑类别的影响
对数据随机均等划分,不适合包含不同类别的数据集。比如:数据集有5类数据(ABCDE各占20%),抽取出来的也正好是按照类别划分的5类,第一折全是A,第二折全是B……这样就会导致,模型学习到测试集中数据的特点,用BCDE训练的模型去测试A类数据、ACDE的模型测试B类数据,这样准确率就会很低。

 Python 使用cross_val_score或者KFold:(下面用KFold)

from sklearn.datasets import load_digits
from sklearn.model_selection import KFold
import pandas as pd
# 加载测试专用数据集
train, target = load_digits(return_X_y=True)
train = pd.DataFrame(train)
target = pd.DataFrame(target)
# K折交叉验证 K-fold CV
# 5折交叉验证
kf = KFold(n_splits=5)

for k, (train_index, test_index) in enumerate(kf.split(train)):
    train_data, test_data, train_target, test_target = train.iloc[
                                                           train_index], train.iloc[test_index], target.iloc[train_index], \
                                                       target.iloc[
                                                           test_index]

 分层交叉验证 (Stratified k-fold cross validation)

分层是重新将数据排列组合,使得每一折都能比较好地代表整体。
比如下面这个例子:在一个二分类问题上,原始数据一共有两类(F和M),F:M的数据量比例大概是 1:3;划分了5折,每一折中F和M的比例都保持和原数据一致(1:3)。

这样就避免了随机划分可能产生的的情况,像是一折全是F,其他3折都是M。
 

下图是标准交叉验证和分层交叉验证的区别:
标准交叉验证(即K折交叉验证):直接将数据分成几折;
分层交叉验证:先将数据分类(class1,2,3),然后在每个类别中划分三折。
 

 

 总结:

StratifiedKFold用法类似Kfold,但是它是分层采样,确保训练集,验证集中各类别样本的比例与原始数据集中相同。因此一般使用StratifiedKFold。
 

from sklearn.model_selection import StratifiedKFold

kf = StratifiedKFold(n_splits=5)
for k, (train_index, test_index) in enumerate(kf.split(train, target)):
    train_data, test_data, train_target, test_target = train.iloc[
        train_index], train.iloc[test_index], target[train_index], target[
            test_index]

  • 6
    点赞
  • 59
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值