问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

一文彻底理解:训练集,验证集,测试集,交叉验证

创作时间:
作者:
@小白创作中心

一文彻底理解:训练集,验证集,测试集,交叉验证

引用
1
来源
1.
https://xiaozhuanlan.com/topic/9023648751

训练集(train set),验证集(validation set),测试集(test set)这三个名词在机器学习领域极其常见,但很多人并不是特别清楚,尤其是后两个经常被混用。
交叉验证很多教材和文章概念也不统一,本文我们深度研究一下。
通过本文,您将学会:

  • 训练集、验证集、测试集的概念和用法
  • 交叉验证在不同教材及 sklearn 中的概念区别
  • sklearn 交差验证方法划分数据集语法、参数解析、用法
  • 不同数据条件下如何选择交差验证方法
  • 运用交叉验证进行模型评估(语法、参数解析、用法)

训练集,验证集,测试集

在机器学习预测任务中,我们需要对模型泛化误差进行评估,选择最优模型。如果我们把所有数据都用来训练模型的话,建立的模型自然是最契合这些数据的,测试表现也好。但换了其它数据集测试这个模型效果可能就没那么好了。为了防止过拟合,就需要将数据集分成训练集、验证集、测试集。

很多机器学习的竞赛中,组织方一般会提供一个标注的数据集(作为训练集)以及一个没有标注的作为测试集,那么我们做模型的时候,通常会人工从训练集中划分一个验证集出来。


图片来源:Ripley, B.D(1996)

它们的作用分别是:

  • 训练集:用来训练模型
  • 验证集:评估模型预测的好坏及调整对应的参数
  • 测试集:测试已经训练好的模型的推广能力

有一个比喻十分形象,训练集就像高三学生的练习册,验证集就像高考模拟卷,测试集就是最后真正的考试。

交叉验证

交叉验证(Cross Validation)用来验证学习器性能的一种统计分析方法,基本思想是重复的使用数据,把得到的样本数据进行切分,组合为不同数据集,某次训练集中的某样本在下次可能成为测试集中的样本,即所谓“交叉”。

交叉验证在很多教材和文章中概念有些乱。主要有三种说法:

  1. 李航老师的《统计学习方法》中模型选择方法分为两类,一个是正则化,一个是交差验证,交叉验证又分为简单交叉验证、s折交叉验证、留一交叉验证。

  2. 周志华老师的《机器学习》中,模型评估有三种方式,留出法、交叉验证(分为 k 折交叉验证和留一法)、自助法。

  3. sklearn 官方文档中,train_test_split 作为留出法的实现方式,而交叉验证进行数据集划分(迭代器)又分为K折(KFold)、p 次 k 折交(RepeatedKFold)、留一(LeaveOneOut )、留 p(LeavePOut)、随机(ShuffleSplit)等等

看定义,简单交差验证和留出法应该是同一件事。

下面我们重点看一下比较常用的几个,不常用的大家可以自行探索。

留出法/简单交叉验证

留出法是最简单的数据集划分方式,随机的将样本数据分为两部分(比如:70% 的训练集,30% 的测试集),然后用训练集来训练模型,在测试集上选择模型及参数。然后再把样本打乱,重新选择训练集和测试集,继续训练数据和检验模型。最后选择损失函数评估最优的模型和参数。


image

留出法/简单交叉验证可以通过 sklearn.cross_validation 中的 train_test_split 实现。

语法:

X_train,X_test, y_train, y_test =
cross_validation.train_test_split(train_data,train_target,test_size=0.3, random_state=0)  

参数解析:

  • train_data:所要划分的样本特征集
  • train_target:所要划分的样本结果
  • test_size:样本占比,如果是整数就是样本的数量
  • random_state:随机数的种子

使用方法:

import numpy as np
from sklearn.model_selection import train_test_split
from sklearn import datasets
iris = datasets.load_iris()
X_train, X_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size=0.4, random_state=0)  

k 折交叉验证

对于需要进行超参评估的模型,留出法还需要划分出验证集,这会使训练集进一步变小;另外,模型也会随着我们选择的训练集和验证集不同而不同。所以我们引入了 k 折交叉验证。

k 折交叉验证把样本数据随机的分成k份,每次随机的选择 k-1 份作为训练集,剩下的1份做测试集。当这一轮完成后,重新随机选择 k-1 份来训练数据。若干轮(小于 k)之后,选择损失函数评估最优的模型和参数。k 一般取 10,数据量大的时候,k可以设置的小一些;数据量小的时候,k 可以设置得大一些。

周志华《机器学习》

k 折交叉验证通过 sklearn 中的 KFold 实现。

语法:

sklearn.model_selection.KFold(n_splits=5, shuffle=False, random_state=None)  

参数解析:

  • n_splits:表示划分几等份
  • shuffle:若为 Falses 时,其效果等同于 random_state 等于整数,每次划分的结果相同;若为 True 时,每次划分的结果都不一样,表示经过洗牌,随机取样。

使用方法:

#K折交叉验证
kf = model_selection.KFold(n_splits=10)
digits_gen = kf.split(digits.data)
for train_idx, test_idx in digits_gen:
        X_train = digits.data[train_idx] #训练集
        X_test = digits.data[test_idx] #测试集
        y_train = digits.target[train_idx] #训练集标签
        y_test = digits.target[test_idx] #测试及标签  

留一交叉验证

它是 k 折交叉验证的特例,此时k等于样本数 N,这样对于 N 个样本,每次选择 N-1 个样本来训练数据,留一个样本来验证模型预测的好坏。此方法主要用于样本量非常少的情况,比如对于普通适中问题,N 小于 50 时,一般采用留一交叉验证。

在 sklearn 中 LeaveOneOut 来实现,其实也完全可以通过 KFold 实现。

from sklearn.model_selection import LeaveOneOut
X = [1, 2, 3, 4]
loo = LeaveOneOut()
for train, test in loo.split(X):
    print("%s %s" % (train, test))  

随机分配

sklearn 使用 ShuffleSplit 方法,可以随机地把数据打乱,然后分为训练集和测试集。它还有一个好处是可以通过 random_state 这个种子来重现我们的分配方式,如果没有指定,那么每次都是随机的。

语法:

sklearn.model_selection.ShuffleSplit(n_splits=10, test_size=None, train_size=None, random_state=None)  

参数解析:

  • n_splits:划分训练集、测试集的次数,默认为 10。
  • test_size:测试集比例或样本数量,默认 None,该值为 0~1 内的浮点数时,表示测试集占总样本的比例;该值为整型值时,表示具体的测试集样本数量;train_size 不设定具体数值时,该值取默认值 0.1,train_size 设定具体数值时,test_size 取剩余部分。
  • train_size:训练集比例或样本数量,默认 None,该值为 0~1 内的浮点数时,表示训练集占总样本的比例;该值为整型值时,表示具体的训练集样本数量;该值为 None(默认值)时,训练集取总体样本除去测试集的部分。
  • random_state:随机种子值,默认为 None。
  • ShuffleSplit 中的 get_n_splits 类方法用于返回划分训练集、测试集的次数。
  • split 类方法 split 返回值训练集、测试集索引值的迭代器。

使用方法:

ss = ShuffleSplit(n_splits=4, random_state=0, test_size=0.25)
for train_index, test_index in ss.split(X):
    print('train_index', train_index, 'test_index', test_index)  

自助法

自助法(bootstrapping)的基本思想是,对于含有 m 个样本的数据集 D,我们对它进行有放回的采样 m 次,最终得到一个含有 m 个样本的数据集 D',这个数据集 D' 会有重复的数据,我们把它用作训练数据。按照概率论的思想,在 m 个样本中,有 1/e 的样本从来没有采到,将这些样本即 D\D' 当做测试集,也就是说这保证了训练集样本数(不重复)在 2/3 左右。

image

sklearn 中没有对应的方法,可以自己构造:

#数据集X
#通过产生的随机数获得抽取样本的序号
bootstrapping = []
for i in range(len(X)):
    bootstrapping.append(np.floor(np.random.random()*len(X)))
#通过序号获得原始数据集中的数据
D_1 = []
for i in range(len(X)):
    D_1.append(X[int(bootstrapping[i])])  

如何选择数据集划分方式

数据充足时,对于不同的划分方式,我们都能获得相近的成绩以及最优参数模型,可以简单交叉验证。

数据不足且模型的测试成绩和最优参数都存在着较大的差异时,可以选择 k 折交叉验证。

如果数据总量非常少,则可以考虑使用留一法。自助法有助于使验证结果更加稳定,并且对于小型且类别不平衡的数据集尤其管用。

交叉验证进行模型评估

再看模型评估

我们训练出模型是需要对其进行评估的,不同模型由不同评价指标。

  • 回归模型评价指标主要有:RMSE(平方根误差)、MAE(平均绝对误差)、MSE(平均平方误差)、R2_score。
  • 分类模型评估指标主要有:正确率与错误率、查准率与查全率、P-R 曲线、F1 与 Fβ 度量、ROC 与 AUC。

模型的好坏就需要有定量的指标,根据指标进行参数调节,最终找出最优模型。

数据集简单划分出训练接、验证集、测试集是有问题的:

  • 第一,划分出来验证集还有测试集,那么我们的训练集会变小,会使训练出的模型性能大打折扣。
  • 第二,模型会随着我们选择的训练集和验证集不同而不同,无法对比出效果,进而无法降低测试准确率的差异。
  • 第三,简单划分是静态的,也无法高效的进行的参数优化、模型选择。
© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号