k折交叉验证(matlab和python程序实现)

参考链接

 

 

 一、例子

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对应的测试集数据逻辑值为1train对应的训练集数据逻辑值为1

 

    

 

 

 

 

 

 

 

 二、k-重交叉验证(k-fold crossValidation):

[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);

  

 三、利用十折交叉验证计算错误分类率

   3.1代码部分

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     %查询错误分类率

 

  fisheriris为鸢尾花数据集:有meas和species两部分

 

 

 

   3.2相关函数解释

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

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

   3.2.2cp = classperf(truelabels)

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

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

   3.2.3class = classify(sample,training,group)  

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

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

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

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

    3.2.4classperf(cp, classout, testidx)

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

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

四、10折交叉验证例子  

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

  我们会将500名篮球运动员和500名非篮球运动员分到每个桶中。每个桶当中放入了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%的数据来训练分类器。
 五、Pyton程序

def KFoldCV(D, A, k):
"""
k-fold 交叉验证

参数说明:
D:给定数据集
A:学习函数
k:折数
"""
np.random.shuffle(D)
dataset = np.split(D, k)
acc_rate = 0
for i in range(k):
train_set = dataset.copy()
test_set = train_set.pop(i)
train_set = np.vstack(train_set)
A.train(train_set[:,:-1], train_set[:,-1]) # 每次的训练集
labels = A.fit(test_set[:,:-1]) # 每次的测试集
acc_rate += np.mean(labels==test_set[:,-1]) # 计算平均误差
return acc_rate/k

  

 

posted @ 2020-06-07 21:10  蛮好不太坏  阅读(9950)  评论(0编辑  收藏  举报