交叉验证stratified k-fold cv与shuffle等常用cv方法

本文参考:
https://scikit-learn.org/stable/modules/cross_validation.html#stratified-k-fold
与《python机器学习基础教程》
好,开始今天的cv学习!
本文需要有一些CV的基础概念之后看会更有收获。
在开始之前,我们要先明确一点:
交叉验证不是一种构建可应用于新数据的模型的方法。交叉验证不会返回一个模型。在调用cv时,内部虽然会构建多个模型,但交叉验证的目的只是评估在给定算法在特定数据集上训练后的泛化性能好坏。
补充:上面的话没有问题,但是在一些ML比赛中会用CV的内部模型来预测,也就是说内部模型有被用到的可能。

我认为CV的学习路线应该是这样的:
要知道k-folds(k层交叉验证)与stratified k-folds cv(分层k折cv)两种重要的方式,然后至于shufflesplit只是一种采用方式,即随机采样的方式,或者叫上面那两种基本方式的点缀。当然,还有留一法,分组cv的方式,但在这里我只讨论上面的k-folds(k层交叉验证)与stratified k-folds cv(分层k折cv)。

最最基本的k折交叉验证:
在这里插入图片描述
可以看到。对于训练集,它做了5等分,注意是按顺序分的。强调这个,就是因为这样分有不妥的时候,后面会提及。之后对于每一次,都会有4份做训练集,剩下一分做验证集或者叫训练集。
所以5个模型就会有5个结果:

>>> from sklearn.model_selection import cross_val_score
>>> clf = svm.SVC(kernel='linear', C=1)
>>> scores = cross_val_score(clf, iris.data, iris.target, cv=5)
>>> scores                                              
array([0.96..., 1.  ..., 0.96..., 0.96..., 1.        ])

  
  
  • 1
  • 2
  • 3
  • 4
  • 5

看起来这样做CV挺好的,问题是什么呢?
问题就在于它是按顺序划分的。或者看这张图:
在这里插入图片描述
这是sklearn官网的一张图,从图中可以看到,很可能一折中的每等分都是同样的种类,也就是说没有意义了。所以有了shufflesplit与分层stratified交叉验证两种方式。先看shuffle:

from sklearn.model_selection import ShuffleSplit
X = np.arange(10)
ss = ShuffleSplit(n_splits=5, test_size=0.25,
    random_state=0)
for train_index, test_index in ss.split(X):
    print("%s %s" % (train_index, test_index))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

输出:

[9 1 6 7 3 0 5] [2 8 4]
[2 9 8 0 6 7 4] [3 5 1]
[4 5 1 0 6 9 7] [2 3 8]
[2 7 5 8 0 3 4] [6 1 9]
[4 1 0 6 8 9 3] [5 2 7]

 
 
  • 1
  • 2
  • 3
  • 4
  • 5

可以看到这次的分组绝无顺序可言,是打乱顺序的5次cv。
在这里插入图片描述
官网也说ss是传统k折的一个很好的替代。同时,他可避免种类的干扰,但是因为他是随机的,也完全有可能产生与k折类似的结果,那怎么办?假如说我就要求k折里面的训练集测试集种类class要尽量均匀呢?
stratified来了。stratified直译也就是分层的意思。
在这里插入图片描述
这张图清楚地说明了标准K折的不足,可以看到,每次训练集都只有一个种类,而测试集都是另外两种,这怎么可能预测的出来呢?
反观stratified。就不会出现这个问题,它保证了每个折中类别之间的比例与整个数据集中的比例相同。
再给出官网关于stratified的代码与图:
在这里插入图片描述
当然这个图的意思和我上个图意思一样的,我认为上一张更容易理解一些。
代码:

from sklearn.model_selection import StratifiedKFold
X = np.ones(10)
y = [0, 0, 0, 0, 1, 1, 1, 1, 1, 1]
skf = StratifiedKFold(n_splits=3)
for train, test in skf.split(X, y):
    print("%s %s" % (train, test))

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
[2 3 6 7 8 9] [0 1 4 5]
[0 1 3 4 5 8 9] [2 6 7]
[0 1 2 4 5 6 7] [3 8 9]

 
 
  • 1
  • 2
  • 3

最后的最后。用书中一句话作为总结:
使用分层k折交叉验证而不是普通k折交叉验证来评估一个分类器,通常是一个好主意(可以在stratified的基础上再用用shufflesplit)。
对于回归问题,scikit-learn默认使用标准k折交叉验证。关于回归问题,有些也是需要使用stratified的,看具体要求而定吧。例如,我最近在参加的一个比赛中发现,对于这个竞赛,stratified是一种绝佳的选择,并且这个比赛是一个回归问题。

                                </div>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值