交叉验证——对数据集的划分

写在前面:

  • 为什么划分数据集?
    以我们的比赛为例,赛方提供有标签的训练数据和无标签的测试数据,要求我们提交测试数据的预测标签值,如果我们不划分数据集,直接用所有的数据进行训练,最后直接对无标签的测试数据预测,我们很难预测我们模型的好坏。以我的理解来看,对于数据集划分形成的验证集,相当于是平时学习中的小考,而测试数据可以看成是期末考或者高考,我们想通过数据集的划分,在验证集上达到评估我们学习能力学习效果的作用,最后为高考或者期末考做准备。

    “划分数据集”其实就等同于“交叉验证”

    交叉验证的基本思想是在某种意义下将原始数据(dataset)进行分组,一部分做为训练集(train set),另一部分做为验证集(validation set or test set),首先用训练集对分类器进行训练,再利用验证集来测试训练得到的模型(model),以此来做为评价分类器的性能指标

  • Sklearn中对于数据集的划分有很多的方法,借着比赛,对该方法做个系统的总结。另,sklearn更新之前交叉验证在cross_validation模块里面,更新之后在model_selection里面

OUTLINE

  • train_test_split()
  • K折交叉验证
  • 留一法和随机划分

train_test_split()

功能
给定数据集X和类别标签y,将数据集按一定比例随机切分为训练集和验证集

调取方法:

  • from sklearn.model_selection import train_test_split(sklearn更新之后的版本,以该方法为准)
  • from sklearn.cross_validation import train_test_split(老版本)

调用:

训练集的特征列,验证集的特征列,训练集的label列,验证集的label列 = train_test_split(数据集的特征列,数据集的label列,期望划分的验证集的大小,划分的随机种子值,是否打乱,分层抽样)

x_train,x_test,y_train,y_test = train_test_split(X,Y,test_size=a,random_state=b,shuffle=False,stratify=label列)

返回的是一个列表:

train_test_split([0,1,2,3,4], shuffle=False)
# 输出:
[[0, 1, 2], [3, 4]]

“stratify”延伸:
这篇文章讲得很清楚,

stratify是为了保持split前类的分布。比如有100个数据,80个属于A类,20个属于B类。如果train_test_split(…test_size=0.25, stratify = y_all), 那么split之后数据如下:

training:75个数据,其中60个属于A类,15个属于B类。
testing: 25个数据,其中20个属于A类,5个属于B类。

用了stratify参数,training集和testing集的类的比例是 A:B=4:1,等同于split前的比例(80:20)。通常在这种正负样本分布不平衡的情况下会用到stratify。

K折交叉验证

K折交叉验证:KFold,GroupKFold,StratifiedKFold

Kfold:

原理:将所有的样例划分为 k 个组,称为折叠 (fold) (如果 k = n, 这等价于 Leave One Out(留一) 策略),都具有相同的大小(如果可能)。预测函数学习时使用 k - 1 个折叠中的数据,最后一个剩下的折叠会用于测试。所以会进行K次

调用:

from sklearn.model_selection import KFold
kf = KFold(n_splits=3, shuffle=False, random_state=None)
from sklearn.model_selection import KFold

kf = KFold(n_splits=2)
X = ["a", "b", "c", "d"]
for index,(train,test) in enumerate(kf.split(X)):
    print(index)
    print((train,test))
    print("*"*20)

这里kf.split(X)返回的是X中进行分裂后train和test的索引值,令X中数据集的索引为0,1,2,3;第一次分裂,先选择test,索引为0和1的数据集为test,剩下索引为2和3的数据集为train;第二次分裂,先选择test,索引为2和3的数据集为test,剩下索引为0和1的数据集为train。

StratifiedKFold:
原理:不仅要分k fold,同时还要保证分的每一份fold里面的正负样本比例和原数据的相同。
调用:

import numpy as np
from sklearn.model_selection import StratifiedKFold
X=np.array([[1,2],[3,4],[5,6],[7,8],[9,10],[11,12]])
y=np.array([1,1,1,2,2,2])
skf=StratifiedKFold(n_splits=3)

for train_index,test_index in skf.split(X,y):
    print("Train Index:",train_index,",Test Index:",test_index)
    X_train,X_test=X[train_index],X[test_index]
    y_train,y_test=y[train_index],y[test_index]
# 输出:
Train Index: [1 2 4 5] ,Test Index: [0 3]
Train Index: [0 2 3 5] ,Test Index: [1 4]
Train Index: [0 1 3 4] ,Test Index: [2 5]

留一法和随机划分

留一法
(或 LOO) 是一个简单的交叉验证。每个学习集都是通过除了一个样本以外的所有样本创建的,测试集是被留下的样本。 因此,对于 n 个样本,我们有 n 个不同的训练集和 n 个不同的测试集。这种交叉验证程序不会浪费太多数据,因为只有一个样本是从训练集中删除掉的

作为一般规则,大多数作者和经验证据表明, 5- 或者 10- 交叉验证应该优于 LOO

留P法
它通过从整个集合中删除 p 个样本来创建所有可能的 训练/测试集

随机划分
将会生成一个用户给定数量的独立的训练/测试数据划分。样例首先被打散然后划分为一对训练测试集合。这跟第一个train_test_split()是差不多的

关于交叉验证讲解得不错的网站:

猜你喜欢

转载自blog.csdn.net/qq_32618817/article/details/80610383