您的位置:首页 > 其它

K-折交叉验证(k-fold crossValidation)

2017-12-25 18:41 549 查看
k-重交叉验证(k-fold crossValidation):

定义: 

在机器学习中,将数据集A分为训练集B(training set)和测试集C(test set),在样本量不充足的情况下,为了充分利用数据集对算法效果进行测试,将数据集A随机分为k个包,每次将其中一个包作为测试集,剩下k-1个包作为训练集进行训练。
[M,N]=size(data);//数据集为一个M*N的矩阵,其中每一行代表一个样本
indices=crossvalind('Kfold',data(1:M,N),10);//进行随机分包
for k=1:10//交叉验证k=10,10个包轮流作为测试集
test = (indices == k); //获得test集元素在数据集中对应的单元编号
train = ~test;//train集元素的编号为非test元素的编号
train_data=data(train,:);//从数据集中划分出train样本的数据
train_target=target(:,train);//获得样本集的测试目标,在本例中是实际分类情况
test_data=data(test,:);//test样本集
test_target=target(:,test);
[HammingLoss(1,k),RankingLoss(1,k),OneError(1,k),Coverage(1,k),Average_Precision(1,k),Outputs,Pre_Labels.MLKNN]=MLKNN_algorithm(train_data,train_target,test_data,test_target);//要验证的算法
end
//上述结果为输出算法MLKNN的几个验证指标及最后一轮验证的输出和结果矩阵,每个指标都是一个k元素的行向量
1
2
3
4
5
6
7
8
9
10
11
12


indices=crossvalind('Kfold',x,k);

来实现随机分包的操作,其中x为一个N维列向量(N为数据集A的元素个数,与x具体内容无关,只需要能够表示数据集的规模),k为要分成的包的总个数,输出的结果indices是一个N维列向量,每个元素对应的值为该单元所属的包的编号(即该列向量中元素是1~k的整随机数),利用这个向量即可通过循环控制来对数据集进行划分。例:

[M,N]=size(data);//数据集为一个M*N的矩阵,其中每一行代表一个样本

indices=crossvalind('Kfold',data(1:M,N),10);//进行随机分包

fork=1:10//交叉验证k=10,10个包轮流作为测试集

test = (indices == k); //获得test集元素在数据集中对应的单元编号

train = ~test;//train集元素的编号为非test元素的编号

train_data=data(train,:);//从数据集中划分出train样本的数据

train_target=target(:,train);//获得样本集的测试目标,在本例中是实际分类情况

test_data=data(test,:);//test样本集

test_target=target(:,test);

今天用到crossvalind. 这个适用于Cross validation。中文应该叫做交叉验证。我主要想说说这个函数怎么用的。举个简单的例子;
P_train=[1 2 3 4 5 6 7 8 ]'

P_train =

     1
     2
     3
     4
     5
     6
     7
     8

Indices=crossvalind('Kfold',8,4)

Indices =
     2
     3
     4
     1
     4
     1
     3
     2

看到Incides了吗,这个是问题的关键,他把所有的点分成4类。数字一样的是一类,Indices=crossvalind('Kfold',8,4)中‘8’代表元素的个数,‘4’代表分成几类,因为有四类,每类应该有8/4两个元素,看indices中,每个相同的数字有两个元素,这样就能完成分类了。
正常都是需要循环4次,这里的‘4’和crossvalind中的参数‘4’是一样的。比如第一次循环令i=1;

得到indicies中是‘1’的,把其中的相应的设置为‘1’,其余的为零。
val_set_index=(Indices==1)
这个是对于test的(validation)验证
val_set_index =
     0
     0
     0
     1
     0
     1
     0
     0

 train_set_index=~val_set_index
这个是train的(训练分类器)
train_set_index =
     1
     1
     1
     0
     1
     0
     1
     1

这两个结果加在一起是一个全为1的向量。
若果我想提取其中的test,用下面语句:

>>val_ma=P_train(val_set_index,:);%val_set_index=[0 0 0 1 0 1 0 0]'
>> val_ma
val_ma =

     4
     6

看见没,得到相应的测试元素

十折交叉验证

(1)英文名叫做10-fold cross-validation,用来测试算法准确性,是常用的测试方法。

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

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

 

例子:利用十折交叉验证计算错误分类率

(Matlab内置了由Fisher在1936年发布的关于iris的数据集,鸠尾花的分类,详见UCI链接;载入该数据集,包括means和species,分别是四维的150个样本和对应的类别)

 

load fisheriris

indices = crossvalind('Kfold',species,10); 

cp = classperf(species); 

for i = 1:10

      test = (indices == i); train = ~test;    %分别取第1、2、...、10份为测试集,其余为训练集

      class = classify(meas(test,:),meas(train,:),species(train,:));

      classperf(cp,class,test);

end

cp.ErrorRate     %查询错误分类率

 

 相关函数解释:

Indices = crossvalind('Kfold', N, K)

1)参数'Kfold'表明为了K折十字交叉验证,把数据集N随机分成平均的(或近似评价的)K份,Indices中为每个样本所属部分的索引(从1到K)

2)因为是随机分,因此重复调用会产生不同分法。

3)在K折十字交叉验证中,K-1份被用做训练,剩下的1份用来测试,这个过程被重复K次。

 

cp = classperf(truelabels)

1)classperf是评估分类器性能(Evaluate performance of classifie)函数。

2)truelabels中为每个样本对应的真实类别,创建并初始化一个空的分类器性能对象CP。

3)classperf provides an interface to keep track of the performance during the validation of classifiers. classperf creates and, optionally, updates a classifier performance object, CP, which accumulates the results of the classifier.

 

class = classify(sample,training,group)

1)classify是判别分析(Discriminant Analysis)函数。

2)若事先已经建立类别,则使用判别分析;若事先没有建立类别,则使用聚类分析。一般地,若已有给定的若干总体的(即若干类别)的观测资料,希望构造一个或多个判别函数,能由此函数对新的位置其所属总体的样品作出判断,从而决定其应属于哪个总体,这就是判别分析问题。

3)判别分析是利用原有的分类信息,得到判别函数(判别函数关系式,一般是与分类相关的若干个指标的线性关系式),然后利用 该函数去判断未知样品属于哪一类。因此,这是一个学习与预测的过程。常用的判别分析法有距离判别法、费歇尔判别法、贝叶斯判别法等。

4)matlab中语法:class = classify(sample,training,group) ,默认线性判别分析,将sample的每个样本进行判别,分到trainning指定的类中,返回该类表作为分类结果。还可以用参数type指定判别分析法。

 

classperf(cp, classout, testidx)

1)根据分类结果,更新分类器性能对象CP。

2)在十折交叉验证法中,就是重复10次,可累积得到总的错误分类率。

10折交叉验证的例子

第1步,将数据等分到10个桶中。

 





我们会将50名篮球运动员和50名非篮球运动员分到每个桶中。每个桶当中放入了100人的信息。

第2步,下列步骤重复10次。

(1)每一次迭代中留存其中一个桶。第一次迭代中留存桶1,第二次留存桶2,其余依此类推。

(2)用其他9个桶的信息训练分类器(第一次迭代中利用从桶2到桶10的信息训练分类器)。

(3)利用留存的数据来测试分类器并保存测试结果。在上例中,这些结果可能如下:

35个篮球运动员被正确分类;

29个非篮球运动员被正确分类。

第3步,对上述结果汇总。

通常情况下我们会将结果放到与下表类似的表格中:

 

 
分成篮球运动员
分成非篮球运动员
实际为篮球运动员
372
128
实际为非篮球运动员
220
280
在所有500名篮球运动员中,有372人被正确分类。可能需要做的一件事是将右下角的数字也加上去,也就是说1000人当中有652(372+280)人被正确分类。因此得到的精确率为65.2%。与2折或3折交叉验证相比,基于10折交叉验证得到的结果可能更接近于分类器的真实性能。之所以这样,是因为每次采用90%而不是2折交叉验证中仅仅50%的数据来训练分类器。

 



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: