1.交叉验证的目的

在机器学习的相关研究中,如果是有监督的算法,需要将原始数据集分为训练集测试集两个集合。训练集中的数据带有标签,用这些数据来训练出一个模型,告诉机器什么样的数据可以分成哪一类,然后用这个模型来预测测试集中数据的标签。然后用预测得到的标签跟真实的标签作比对,就可以得到这个模型的预测准确率,其实是考察这个模型的generalization ability(泛化能力),即,从训练集中总结出来的规律能不能用到别的数据上去。

那么,怎样分训练集和测试集呢?需要考虑两个问题:

1. 训练集中的数据要足够多,一般要大于原始数据集的一般,否则总结出来的规律太小众

2. 两组集合必须是原始集合的均匀取样,否则比如说,训练集选择都是1类数据,测试集都是2类数据,训练之后模型知道1类数据的特点,用它来分别2类数据,这好难。。。

于是,cross validation的目的就是:科学地统计训练模型的泛化能力。

 


2.交叉验证的分类

简单交叉验证、K-折交叉验证、留一交叉验证

 

2.1 简单交叉验证

将原始数据随机分为两组,一组做为训练集,一组做为验证集,利用训练集训练分类器,然后利用验证集验证模型,记录最后的分类准确率为此分类器的性能指标。

 

优点:

处理简单,只需随机把原始数据分为两组即可

缺点:

但没有达到交叉的思想,由于是随机的将原始数据分组,所以最后验证集分类准确率的高低与原始数据的分组有很大的关系,得到的结果并不具有说服性。

 

2.2 K-折交叉验证

将原始数据分成K组(一般是均分),将每个子集数据分别做一次验证集,其余的K-1组子集数据作为训练集,这样会得到K个模型,用这K个模型最终的验证集的分类准确率的平均数作为此K-CV下分类器的性能指标。K一般大于等于2,实际操作时一般从3开始取,只有在原始数据集合数据量小的时候才会尝试取2。

 

应用最多,K-CV可以有效的避免过拟合与欠拟合的发生,最后得到的结果也比较具有说服性。

 

Eg:十折交叉验证

1.     将数据集分成十份,轮流将其中9份作为训练数据,1份作为测试数据,进行试验。每次试验都会得出相应的正确率。

2.     10次的结果的正确率的平均值作为对算法精度的估计,一般还需要进行多次10折交叉验证(例如10次10折交叉验证),再求其均值,作为对算法准确性的估计

 

此外:

(1)多次 k 折交叉验证再求均值,例如:10 次10 折交叉验证,以求更精确一点。

(2)划分时有多种方法,例如对非平衡数据可以用分层采样,就是在每一份子集中都保持和原始数据集相同的类别比例。

(3)模型训练过程的所有步骤,包括模型选择,特征选择等都是在单个折叠 fold 中独立执行的。

 

2.3 留一交叉验证(Leave-One-Out Cross Validation记为LOO-CV)

在数据缺乏的情况下使用,如果设原始数据有N个样本,那么LOO-CV就是N-CV,即每个样本单独作为验证集,其余的N-1个样本作为训练集,故LOO-CV会得到N个模型,用这N个模型最终的验证集的分类准确率的平均数作为此下LOO-CV分类器的性能指标。

优点:

(1)每一回合中几乎所有的样本皆用于训练模型,因此最接近原始样本的分布,这样评估所得的结果比较可靠。

(2)实验过程中没有随机因素会影响实验数据,确保实验过程是可以被复制的。

缺点:

计算成本高,需要建立的模型数量与原始数据样本数量相同。当数据集较大时几乎不能使用。

 
3.交叉验证matlab实现
 
3.1 简单交叉验证
自主将数据分成两类,一类作训练集,一类作验证集。
 
3.2 K-折交叉验证
 

Data = rand(9,3);%创建维度为9×3的随机矩阵样本
indices = crossvalind('Kfold', 9, 3);%将数据样本随机分割为3部分
for i = 1:3 %循环3次,分别取出第i部分作为测试样本,其余两部分作为训练样本
test = (indices == i);
train = ~test;
trainData = Data(train, :);
testData = Data(test, :);
end

 

程序解读:1、创建9X3的矩阵

     2、把矩阵按将9行数据分成3个类

     3、拿出每一类的数据拿出来进行验证

     例如,最后运行的是第三类,可以看到分类中,1,5,9行为第三类数据,原始数据中的1,5,9行的数据为test_trian (检验数据),剩下的数据为测试数据。test对应的测试集数据逻辑值为1,train对应的训练集数据逻辑值为1。

函数解释:Indices = crossvalind('Kfold', N, K)

       1、参数'Kfold'表明为了K折十字交叉验证,把数据集N随机分成平均的(或近似评价的)K份,Indices中为每个样本所属部分的索引(从1到K)
       2、因为是随机分,因此重复调用会产生不同分法。
       3、在K折十字交叉验证中,K-1份被用做训练,剩下的1份用来测试,这个过程被重复K次。

 

3.3 留M交叉验证

load carbig x = Displacement;

y = Acceleration; % x为轿车形状的大小,y为轿车轿车速度从0到60公里所用时间

N = length(x); % N为x长度=406

sse = 0;

for i = 1:100

[train,test] = crossvalind('LeaveMOut',N,1);

yhat = polyval(polyfit(x(train),y(train),2),x(test));

sse = sse + sum((yhat - y(test)).^2);

end

CVerr = sse / 100

% sse=353.10

CVerr交叉验证误差为sse/100=3.5310

CVerr = 4.9750

函数解释:

[Train, Test] = crossvalind('LeaveMOut', N, M), where M is an integer, returns logical index vectors for cross-validation ofN observations by randomly selectingM of the observations to hold out for the evaluation set.M
defaults to1 when omitted. Using 'LeaveMOut' cross-validation within a loop does not guarantee disjointed evaluation sets. To guarantee disjointed evaluation sets, use'Kfold' instead.

M是整数,返回交叉索引逻辑索引向量,其中N个观测值,从N个观测值中随机选取M个观测值保留作为验证集,其余作为训练集。省略时,M默认为1,即留一法交叉验证。
在一个循环中使用LeaveMOut交叉验证不保证不连贯的验证集.为保证非连贯的验证集,使用K-fold方法替换。

 

参考文献:

[1] https://blog.csdn.net/weixin_40475450/article/details/80578943

[2] https://blog.csdn.net/whucv/article/details/8959460?utm_medium=distribute.pc_aggpage_search_result.none-task-blog-2~all~first_rank_v2~rank_v25-4-8959460.nonecase&utm_term=matlab%E4%BA%A4%E5%8F%89%E9%AA%8C%E8%AF%81%E6%95%B0%E6%8D%AE%E9%9B%86%E7%9A%84%E6%96%B9%E6%B3%95

[3] https://ww2.mathworks.cn/help/bioinfo/ref/crossvalind.html

posted on 2020-09-03 11:54  安宁莞尔  阅读(1382)  评论(0)    收藏  举报