既不能通过直接将泛化误差作为了解模型泛化能力的信号,因为在部署环境和训练模型之间往复,代价很高,也不能使用模型对训练数据集的拟合程度来作为了解模型泛化能力的信号,因为我们获得的数据往往不干净。
更好的方式就是将数据分割成两部分:训练集和测试集。我们可以使用训练集的数据来训练模型,然后用测试集上的误差作为最终模型在应对现实场景中的泛化误差。有了测试集,我们想要验证模型的最终效果,只需将训练好的模型在测试集上计算误差,即可认为此误差即为泛化误差的近似,我们只需让我们训练好的模型在测试集上的误差最小即可。
不同的模型与模型之间的对比
我们将数据集划分为训练集和测试集,我们让模型在训练集上进行训练,然后在测试集上来近似模型的泛化能力。我们如果想要挑选不同的模型的话,可以让两个模型分别在训练集上训练,然后将两个训练好的模型分别在测试集上进行测试,由于我们把测试集上的误差近似近似为泛化误差,所以我们自然可以选择在测试集上误差小的模型作为最终我们要选择的泛化能力强的模型。
采用纯随机的采样方式,这种方式对于大量数据集以及对于目标值分布均匀的情况是可行的
del_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%的反例样本,此时的标签分布很不均匀,如果我们通过随机采样的方式,极端情况下可能将正例样本都划分到训练集上,而反例样本恰好都分到测试集,这样训练出来的模型,效果一定不会太好,所以我们需要采用分层采样的方式进行划分数据集,也就是说保证训练集中既包含一定比例的正例样本又要包含一定比例的负例样本。
del_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]''del_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:设置随机种子;
使用随机采样方式划分数据集
#使用随机采样方式划分数据集
del_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))
使用分层采样的方式分割数据集
#使用分层采样的方式分割数据集:
del_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个类别所占的比例很接近。
我们使用测试集作为泛化误差的近似,所以不到最后是不能将测试集的信息泄露出去的,就好比考试一样,我们平时做的题相当于训练集,测试集相当于最终的考试,我们通过最终的考试来检验我们最终的学习能力,将测试集信息泄露出去,相当于学生提前知道了考试题目,那最后再考这些提前知道的考试题目,当然代表不了什么,你在最后的考试中得再高的分数,也不能代表你学习能力强。而如果通过测试集来调节模型,相当于不仅知道了考试的题目,学生还都学会怎么做这些题了(因为我们肯定会人为的让模型在测试集上的误差最小,因为这是你调整超参数的目的),那再拿这些题考试的话,人人都有可能考满分,但是并没有起到检测学生学习能力的作用。原来我们通过测试集来近似泛化误差,也就是通过考试来检验学生的学习能力,但是由于信息泄露,此时的测试集即考试无任何意义,现实中可能学生的能力很差。所以,我们在学习的时候,老师会准备一些小测试来帮助我们差缺补漏,这些小测试也就是要说的验证集。我们通过验证集来作为调整模型的依据,这样不至于将测试集中的信息泄露。
我们将数据划分训练集、验证集和测试集。在训练集上训练模型,在验证集上评估模型,一旦找到的最佳的参数,就在测试集上最后测试一次,测试集上的误差作为泛化误差的近似。
关于验证集的划分可以参考测试集的划分,其实都是一样的,这里不再赘述。
吴恩达老师的视频中,如果当数据量不是很大的时候(万级别及以下下)的时候将训练集、验证集以及测试集划分为6:2:2;
若是数据很大,可以将训练集、验证集、测试集比例调整为98:1:1;但是当可用的数据很少的情况下也可以使用一些高级的方法,比如留出方,K折交叉验证等。
本文发布于:2024-02-08 19:51:43,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170739323468507.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |