训练集、验证集和测试集

训练集 vs 测试集

引入

既不能通过直接将泛化误差作为了解模型泛化能力的信号,因为在部署环境和训练模型之间往复,代价很高,也不能使用模型对训练数据集的拟合程度来作为了解模型泛化能力的信号,因为我们获得的数据往往不干净。
更好的方式就是将数据分割成两部分:训练集和测试集。我们可以使用训练集的数据来训练模型,然后用测试集上的误差作为最终模型在应对现实场景中的泛化误差。有了测试集,我们想要验证模型的最终效果,只需将训练好的模型在测试集上计算误差,即可认为此误差即为泛化误差的近似,我们只需让我们训练好的模型在测试集上的误差最小即可。
不同的模型与模型之间的对比
我们将数据集划分为训练集和测试集,我们让模型在训练集上进行训练,然后在测试集上来近似模型的泛化能力。我们如果想要挑选不同的模型的话,可以让两个模型分别在训练集上训练,然后将两个训练好的模型分别在测试集上进行测试,由于我们把测试集上的误差近似近似为泛化误差,所以我们自然可以选择在测试集上误差小的模型作为最终我们要选择的泛化能力强的模型。

训练集、测试集划分tips

  • 通常将数据集的80%作为训练集,20%作为测试集;
  • 通常需要在开始构建模型之前把数据集进行划分,防止数据窥探偏误,也就是说我们避免了解太多关于测试集中的样本特点,防止我们认为的挑选有助于测试集数据的模型,这样的结果会过于乐观,但是实际上并没有预期的那样优秀;
  • 通常我们在构建模型的时候需要将数据进行处理,包括一些数据的清洗,数据的特征缩放(标准化或者归一化),此时我们只需要在训练集上进行这些操作,然后将其在训练集上得到的参数应用到测试集中,也就是说,在工作流程中,你不能使用在测试数据集上计算的得到的任何结果。比如:我们得到的属性中可能有缺失值,因为在这些操作之前,我们已经把数据集分成了训练集合测试集,通常的做法是通过计算属性值的中位数来填充缺失值,注意此时计算属性值的中位数是通过训练集上的数据进行计算的,当我们得到一个模型的时候,如果想要测试模型的测试误差来近似泛化误差的时候,可能此时的测试集也会有一些缺失值,此时对应属性的缺失值是通过训练集计算的中位数来进行填充的;
  • 由于测试集作为对泛化误差的近似,所以训练好模型,最后在测试集上近似估计模型的泛化能力。此时假设有两个不同的机器学习模型,犹豫不决的时候,可以通过训练两个模型,然后对比他们在测试数据上的泛化误差,选择泛化能力强的模型。

训练集、测试集划分 coding

纯随机的采样方式

采用纯随机的采样方式,这种方式对于大量数据集以及对于目标值分布均匀的情况是可行的

from sklearn.model_selection import train_test_split
#data:需要进行分割的数据集#random_state:设置随机种子,保证每次运行生成相同的随机数#test_size:将数据分割成训练集的比例
train_set, test_set = train_test_split(data, test_size=0.2, random_state=42)
分层划分

比如对于分类任务,我们训练一个二值分类器,可能数据中包含大量的正例样本,仅仅包含10%的反例样本,此时的标签分布很不均匀,如果我们通过随机采样的方式,极端情况下可能将正例样本都划分到训练集上,而反例样本恰好都分到测试集,这样训练出来的模型,效果一定不会太好,所以我们需要采用分层采样的方式进行划分数据集,也就是说保证训练集中既包含一定比例的正例样本又要包含一定比例的负例样本。

from sklearn.model_selection import StratifiedShuffleSplit
import numpy as np
X = np.array([[1, 2], [3, 4], [1, 2], [3, 4]])
y = np.array([0, 0, 1, 1])
split = StratifiedShuffleSplit(n_splits=3, test_size=0.5, random_state=0)
print(split) 
for train_index, test_index in split.split(X, y):
    print('TRAIN:', train_index, 'TEST:', test_index)
    X_train, X_test = X[train_index],X[test_index]
    y_train, y_test = y[train_index],y[test_index]
    print(len(X_train),len(X_test))

# doctest: +ELLIPSIS# StratifiedShuffleSplit(n_splits=3, random_state=0, ...)
'''StratifiedShuffleSplit(n_splits=3, random_state=0, test_size=0.5,train_size=None)TRAIN: [1 2] TEST: [3 0]TRAIN: [0 2] TEST: [1 3]TRAIN: [0 2] TEST: [3 1]''

from sklearn.model_selection import StratifiedShuffleSplit
split = StratifiedShuffleSplit(n_splits = 1,test_size = 0.2,random_state = 42)
#根据mnist['target']来进行分层采样
for train_index,test_index in split.split(data,data[:,-1]):
    train_set = data[train_index,:]
    test_set = data[test_index,:]
    print(len(train_set),len(test_set))

n_splits:分割迭代的次数,如果我们要划分训练集和测试集的话,将其设置为1即可;
test_size:分割测试集的比例;
random_state:设置随机种子;

例子

使用随机采样方式划分数据集

#使用随机采样方式划分数据集
from sklearn.model_selection import train_test_split
import numpy as np
data = np.hstack((x_data,y_data))
#先将数据集进行拼接,要不然我们只针对样本进行采样的话,会找不到对应的标签的
train_set,test_set = train_test_split(data,test_size = 0.2,random_state = 42)
print(len(train_set),len(test_set))

使用分层采样的方式分割数据集

#使用分层采样的方式分割数据集:
from sklearn.model_selection import StratifiedShuffleSplit
split = StratifiedShuffleSplit(n_splits = 1,test_size = 0.2,random_state = 42)
#根据mnist['target']来进行分层采样
for train_index,test_index in split.split(data,data[:,-1]):
    train_set = data[train_index,:]
    test_set = data[test_index,:]
    print(len(train_set),len(test_set))

划分数据集查看数据样本分层情况

#将分割后的训练数据转换为DataFrame
#这里的参数data可以是分割之后的训练集或者测试集
train_data = pd.DataFrame(train_set)
#快速查看对数据的描述
train_data.info()
#查看各个类别的比例
print(train_data[784].value_counts()/len(train_data))
# 分层采样出的10个类别所占的比例和原数据中的10个类别所占的比例很接近。

验证集

  • 但是我们要做的不仅是不同的模型与模型之间的对比,很多时候我们需要对模型本身进行选择,假如我们有两个模型,线性模型和神经网络模型,我们知道神经网络的泛化能力要比线性模型要强,我们选择了神经网络模型,但是神经网络中还有很多的需要人工进行选择的参数,比如神经网络的层数和每层神经网络的神经元个数以及正则化的一些参数等等,我们将这些参数称为超参数。这些参数不同选择对模型最终的效果也很重要,我们在开发模型的时候总是需要调节这些超参数
  • 现在我们需要调节这些超参数来使得模型泛化能力最强。我们使用测试集来作为泛化误差估计,而我们最终的目的就是选择泛化能力强的模型,那么我们可以直接通过模型在测试集上的误差来调节这些参数不就可以了。可能模型在测试集上的误差为0,但是你拿着这样的模型去部署到真实场景中去使用的话,效果可能会非常差。

信息泄露

我们使用测试集作为泛化误差的近似,所以不到最后是不能将测试集的信息泄露出去的,就好比考试一样,我们平时做的题相当于训练集,测试集相当于最终的考试,我们通过最终的考试来检验我们最终的学习能力,将测试集信息泄露出去,相当于学生提前知道了考试题目,那最后再考这些提前知道的考试题目,当然代表不了什么,你在最后的考试中得再高的分数,也不能代表你学习能力强。而如果通过测试集来调节模型,相当于不仅知道了考试的题目,学生还都学会怎么做这些题了(因为我们肯定会人为的让模型在测试集上的误差最小,因为这是你调整超参数的目的),那再拿这些题考试的话,人人都有可能考满分,但是并没有起到检测学生学习能力的作用。原来我们通过测试集来近似泛化误差,也就是通过考试来检验学生的学习能力,但是由于信息泄露,此时的测试集即考试无任何意义,现实中可能学生的能力很差。所以,我们在学习的时候,老师会准备一些小测试来帮助我们差缺补漏,这些小测试也就是要说的验证集。我们通过验证集来作为调整模型的依据,这样不至于将测试集中的信息泄露。

训练集划分

我们将数据划分训练集、验证集和测试集。在训练集上训练模型,在验证集上评估模型,一旦找到的最佳的参数,就在测试集上最后测试一次,测试集上的误差作为泛化误差的近似。

关于验证集的划分可以参考测试集的划分,其实都是一样的,这里不再赘述。
吴恩达老师的视频中,如果当数据量不是很大的时候(万级别及以下下)的时候将训练集、验证集以及测试集划分为6:2:2
若是数据很大,可以将训练集、验证集、测试集比例调整为98:1:1;但是当可用的数据很少的情况下也可以使用一些高级的方法,比如留出方,K折交叉验证等。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值