
模型参数分为 训练参数 和 超参数 ,其中前者是在训练集上训练得到的,而后者是在训练之前由用户指定的,比如学习率、迭代次数等。
机器学习中,样本集通常会被分为 训练集 、 验证集 和 测试集 ,其中训练集和测试集是必须有的。
对于一个训练好的模型,需要了解它的泛化性能(在新样本上的准确率),真正的泛化性能应该在除原样本集之外的所有潜在样本上进行计算,但实际中没法得到这些潜在样本,于是退而求其次,在原样本集上划分出了一个测试集作为近似,并将在该测试集上的泛化性能近似作为在所有样本上的泛化性能。
注意: 测试集中的样本与训练集、验证集不能有任何交集;测试集只能用于检验最终模型的泛化性能,不能用于更新模型参数。换句话说,只有最终模型才需要经过测试集检验泛化性能,或者说模型经过测试集检验泛化性能后就不能再进行任何训练或修改参数了 。如果将在测试集上得到的准确率(也就是误差)反过来作为模型进一步训练的依据,实际上是将测试集也作为训练集对待了,也就没有了测试集。
实际中,有人会这么做,当碰到最终模型在测试集上的准确率不高时,又反过来重新调整超参数或利用测试集上的误差进一步训练模型,如此重复直到模型在测试集上表现很好,但上线后发现模型的准确率很低。出现上线后准确率低的其中一种原因就是误用了测试集,上述过程实际上就没有测试集,而是将整个样本集都作为了训练集,并且调整模型使其在测试集上获得高准确率的做法还会导致模型过拟合,上线后准确率自然会很低。
理论上,如果最终模型在测试集上的表现非常差,则应该从样本数据量、样本分布、训练集和测试集划分情况、模型选择等一系列因素入手查找原因,而不是回去继续调整模型参数(虽然也有可能就是模型参数还不不够好)。
值得注意的是, 测试集上的准确率不一定越高越好 。如果样本集本身的分布就很有局限性(无法有效表征所有潜在样本的基本特征),那么测试集的分布就更有局限性,此时测试集上的高准确率就意味着严重的过拟合,模型投入实际应用后准确率一定差。因此对于不太理想的样本集而言,测试集上的准确率相对低一些,模型的真正泛化性能反而更好。如果样本集的分布足够好,能足够表征所有潜在样本的特征,那么模型在测试集上的准确率越高越好。
验证集是训练集和测试集之间的一个中间件。根据前面的定义,我们发现了一个问题,如果只有训练集和测试集,是无法在测试集之前对模型进行评价的。实际上我们更希望在最终模型确定之前,可以先对模型进行一定的评价,然后根据评价结果调整模型参数(特别是超参数),直到我们认为模型已经不错了,最后再用测试集进行测试,测试就只为了查看模型的近似泛化性能,不再继续更新模型参数。正是为了这个目的,才划分出了一个验证集。可见, 验证集一定程度上还是训练集,因为会根据验证集的结果调整模型参数 。
有了验证集,整个过程就变成了下面这样:先确定一组超参数,然后在训练集上训练,再用验证集进行检验,如果效果不好,则继续调整超参数,重新在训练集上训练,如此循环,直到模型在验证集上表现良好。 到这一步,相当于我们已经基本找到了最优的超参数,接下去可以将这组超参数对应的模型参数作为最终模型参数,也可以利用这组超参数在“训练集+验证集”上重新训练一遍,得到的结果作为最终模型参数 。最后用测试集检验最终模型参数的泛化效果,好与不好都不再单纯地调整模型参数了。
最简单的样本集划分就是只有训练集和测试集,而没有验证集。这种情况实际上前面已经说过,他无法利用验证集反过来对模型参数进行调整。只能确定一组超参数,然后训练得到训练参数,这个就算是最终结果了,然后利用测试集检验一下泛化效果就算结束了。或者更复杂点的做法,先确定几组超参数,然后分别在训练集上训练得到不同训练参数,最后利用测试集分别进行测试,最后根据测试结果选择认为最好的那组作为最终模型参数。如下图所示:
当然,不地道的做法,也可以一定程度上利用测试集的结果反过来调整模型参数,但不能过度,否则极容易过拟合。
将样本集划分为训练集、验证集和测试集,比例通常为8:1:1或6:2:2。这种情况比第一种要好,他多了一个验证集,至少让你可以根据验证集来不断调整模型参数了。
先确定一组超参数,在训练集上得到训练参数,然后在验证集上得到验证结果,根据验证结果反过来修改超参数,继续在训练集上训练,然后再验证……如此循环直到你认为训练结果在验证集上表现良好为止。到这一步,我们仅仅只是找到了相对最优的超参数,其对应的训练参数通常还不能作为最后参数。 还需要根据获得的最优超参数在“训练集+验证集”上整体做训练得到最终结果 ,最后将该“最优超参数+最终训练参数”在测试集上做测试(不再训练),结束整个过程。如下图所示,其中曲线图展示了不断尝试不同的超参数,最终确定最优超参数C0的过程(注意,这里的最优超参数C0只是当前训练集和验证集划分情况下的最优,但这并不代表它是整个样本集真正的最优超参数,详见“单一划分的缺陷”章节):
上述两种方式都有一个问题。
我们知道把一个样本集划分成训练集、(验证集)、测试集,由于每个样本可能不同,即使划分子集的样本数每次相同,最终的划分结果也不同。
事实证明, 在样本集规模较小的情况下,对于不同的子集划分,即使是完全相同的超参数,其最终的训练和测试结果也会出现很大波动 。如下图所示,同一个样本集,训练集和验证集划分不同(测试集用同一个),得到的最优超参数就不同,对应的误差曲线差异也很大。
出现上述情况的本质原因是样本集分布不够充分,导致划分后的子集更不充分,每一种划分都出现较大波动,自然训练和测试的结果也会波动较大;如果样本集足够大足够充分(足够表征全局特征),那么无论划分情况怎么变化,子集很大程度上也都足够充分,训练和测试出来的结果也就是全局结果,最优超参数和误差曲线也不会变化太大 。
前面已经说过,对于样本数量不大,样本分布不充分的样本集而言,单一验证方法会因为样本集分割变化而导致最终的训练和测试结果出现比较严重的动荡。
针对这种情况,很自然地想到,可以对训练集做K次分割(K折交叉验证),然后用同一组超参数对应训练K个模型,并在同一组测试集上测试,取最终的平均准确率作为该组超参数的最终测试结果;
然后选下一组超参数重复上述过程,这样我们就获得了不同超参数各自的平均准确率;
选择平均准确率最高的超参数作为最终超参数;
将最终超参数在“原训练集+验证集”上整体做训练得到最终结果;
最后将该“最终超参数+最终训练参数”在测试集上做测试(不再训练),结束整个过程。
上述过程可以用下图表示:
交叉验证使最终在测试集上的准确率更加可信,一定程度上摆脱了因为单一样本划分带来的分布不均衡问题;
交叉验证使训练集样本既做了训练集又做了验证集,因此,一定程度上利用了更多的样本信息;
用于调节超参数;用于选择不同模型;用于选择不同样本参数。
K折交叉验证的过程就是上图所示,不再赘述。
关于K的选择需要说明:
当 K=1 时,即所有训练样本都作为训练样本,这种情况相当于没有交叉验证,跟只有训练集和测试集的情况一样;
当 K=N 时(N是训练集的样本总数,不包括测试集),即每次只留1个样本作为验证集,N-1个作为训练集,这种方法称为留一法(LOOCV,Leave-one-out cross-validation);
LOOCV的优点:首先它不受训训练集和验证集划分(这里指将大训练集划分为训练集和验证集)的影响,因为每一个样本都单独的做过验证集,同时,其用了N-1个样本训练模型,几乎用到了所有样本信息。
LOOCV优点:计算量过大。
当 1<K<N 时,K选取实际上是偏差(bias)和方差(variance)的一个折中(trade off)。K越大,每次投入的训练样本越多,模型的Bias越小。但K越大,也意味着每次选取的训练样本的相关性越大(或者重叠性越大)(考虑最极端的例子,当K=N,也就是在LOOCV里,每次的训练样本几乎是一样的),而这种大相关性会导致最终的test error具有更大的Variance;K越小,偏差越大,方差越小。
一般来说,根据经验我们一般选择K=5或10。
下图展示了LOOCV和10折交叉验证的对比结果:
蓝色线表示真实的测试误差曲线;
黑色线表示LOOCV方法测试误差曲线;
橙色线表示10折交叉验证测试误差曲线;
可见LOOCV和10折交叉验证结果是很相似的,但是相比LOOCV,10折交叉验证的计算成本却小了很多 。
1.需要注意的是,交叉验证只是对训练集的进一步有效利用,最终还是要通过未使用过的数据(单独划分出测试集)来检验它的泛化能力;
2.我们首先要在样本集上留出一直不变的测试集,然后将剩余部分作为大测试集,然后在该的测试集上做K折交叉验证;
3.当训练集样本只有几十、几百或几千时,最好用交叉验证来保证利用尽量多的样本信息;
4.其他交叉验证方法:多次K折交叉验证(Repeated K-Fold Cross Validation)、蒙特卡洛交叉验证(Monte Carlo Cross Validation)
https://zhuanlan.zhihu.com/p/257808534
https://zhuanlan.zhihu.com/p/32627500
https://blog.csdn.net/yawei_liu1688/article/details/79138202
https://blog.csdn.net/qq_39751437/article/details/85071395
https://zhuanlan.zhihu.com/p/24825503?refer=rdatamining
https://www.cnblogs.com/wangkundentisy/p/8968316.html
https://blog.csdn.net/sysstc/article/details/103567520?utm_medium=distribute.pc_relevant.none-task-blog-2 default baidujs_baidulandingword~default-0.pc_relevant_default&spm=1001.2101.3001.4242.1&utm_relevant_index=3
https://tanxg.blog.csdn.net/article/details/109280753?spm=1001.2101.3001.6650.6&utm_medium=distribute.pc_relevant.none-task-blog-2 default BlogCommendFromBaidu Rate-6.pc_relevant_default&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2 default BlogCommendFromBaidu Rate-6.pc_relevant_default&utm_relevant_index=11
交叉验证是在机器学习建立模型和验证模型参数时常用的办法。交叉验证就是重复使用数据,把得到的样本数据进行切分,组合为不同的训练集和测试集,用训练集来训练模型,用测试集来评估模型预测的好坏。在此基础上可以得到多组不同的训练和测试集,某次训练集中的某样本在下次可能成为测试集中的样本,即所谓“交叉”。
交叉验证用在数据不是很充足的时候。比如,在日常项目中,对于普通适中问题,如果数据样本量小于一万条,我们就会采用交叉验证来训练优化选择模型。如果样本大于一万条的话,一般随机的把数据分成三份,一份为训练集(Training Set),一份为验证集(Validation Set),最后一份为测试集(Test Set)。用训练集来训练模型,用验证集来评估模型预测的好坏和选择模型及其对应的参数。把最终得到的模型再用于测试集,最终决定使用哪个模型以及对应参数。
根据切分的方法不同,交叉验证分为下面三种:
第一种,简单交叉验证。首先,随机的将样本数据分为两部分(比如:70%的训练集,30%的测试集),然后用训练集来训练模型,在测试集上验证模型及参数。接着,我们再把样本打乱,重新选择训练集合测试集,继续训练数据和检验模型。最后我们选择损失函数评估最优的模型和参数。
第二种是S折交叉验证(S-Folder Cross Validation)。和第一种方法不同,S折交叉验证会把样本数据随机的分成S份,每次随机的选择S-1份作为训练集,剩下的1份做测试集。当这一轮完成后,重新随机选择S-1份来训练数据。若干轮(小于S)之后,选择损失函数评估最优的模型和参数。
留一交叉验证(Leave-one-out Cross Validation),它是第二种情况的特例,此时S等于样本数N,这样对于N个样本,每次选择N-1个样本来训练数据,留一个样本来验证模型预测的好坏。此方法主要用于样本量非常少的情况,比如对于普通适中问题,N小于50时,一般采用留一交叉验证。
通过反复的交叉验证,用损失函数来度量得到的模型的好坏,最终可以得到一个较好的模型。
此外还有一种比较特殊的交叉验证方式,也是用于样本量少的时候,叫做自助法啊(bootstrapping)。比如有m个样本(m较小),每次在这m个样本中随机采集一个样本,放入训练集,采样完后把样本放回。这样重复采集n次,我们得到m个样本组成的训练集。当然,这m个样本中很有可能有重复的样本数据。同时,用没有被采样到的样本做测试集,这样接着进行交叉验证。由于我们的训练集有重复数据,这会改变数据的分布,因而训练结果会有估计偏差,因此,此种方法不是很常用,除非数据量很少,比如小于20个。
将拿到的数据,分为训练和验证集。以下图为例:将数据分成5份,其中一份作为验证集。然后经过5次(组)的测试,每次都更换不同的验证集。即得到5组模型的结果,取平均值作为最终结果,又称5折交叉验证。
1.首先,你需要准备一个数据集,可以从某些数据库中获取,也可以从某些文件中提取,或者自己输入。2.接下来,使用Matlab中的crossval函数对你的数据集进行交叉验证,crossval函数会将你的数据集分成K份,每一份作为验证集,其他K-1份作为训练集。
3.接下来,使用Matlab中的fitcecoc函数来训练交叉验证划分后的训练集,fitcecoc函数是一种支持向量机,可以用来分类和回归任务,它可以比较有效地利用数据集中的变量,从而提高模型的准确性。
4.最后,使用Matlab中的predict函数对验证集进行预测,并使用Matlab中的confusionmat函数来评估分类器的准确性,从而评估交叉验证拓展的数据集的质量。
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)