用K折交叉验证估计KNN算法中的K值

       前几天用KNN对自己的数据进行了分类,对于KNN中的K值,之前一直是靠缘分来试的,试的时候感觉K=3的效果挺好的。之后看了好多CSDN的博客,发现一般大家除了靠缘分去试K值之外,也会采用交叉验证的方法去近似求得K值,因此我决定自己实现一下,看看有什么效果。

       交叉验证之前老师在将数据挖掘的时候简单的介绍了一下,那时候只记得10折交叉验证,而且并没有去实验,所以早就忘得一干二净。

       K折交叉验证,在matlab中已经集成了函数crossvalind,可以直接调用。

       所谓K折交叉验证(K-foldcross validation),其过程如下:

     (1)  将全部训练集S分成K个不相交的子集,假设S中的训练样例个数为m,那么每一个子集有m/k个训练样例。

     (2)  每次从分好的子集中,选出一个作为测试集,另外k-1个作为训练集。

     (3)  根据训练集得到模型。

     (4)  根据模型对测试集进行测试,得到分类率。

     (5)  计算k次求得的分类率的平均值,作为模型的最终分类率。

     虽然计算过程比较繁琐,但是我觉得还可以,毕竟我的数据不是很多。。。。

datatrain = xlsread('traindata1.xlsx'); %读训练数据
traindata1 = datatrain(:,1:180); %训练样本
trainlabel1 = datatrain(:,181);  %训练样本对应的标签
find_params = 5;
test_K = 1:30;    %测试的K值范围
length = size(traindata1, 1);
index = 1:find_params:length;
testdata = traindata1(index,:); %获得测试数据
testlabel = trainlabel1(index,:); %获得测试标签
traindata = traindata1;
trainlabel = trainlabel1;
traindata(index,:) = [];
trainlabel(index,:) = [];
avgLosses = zeros(size(test_K));
 for K = test_K
            predict_t = knnclassify(testdata, traindata, trainlabel, K, 'Euclidean');
            %loss = ZeroOneLoss(predict_t, testlabel);
            predict_t = predict_t';
            testlabel = testlabel';
            nomatch = 0;
            [row,column] = size(testlabel);
            for i = 1:column
                if predict_t(i) == testlabel(i)
                    continue;
                else 
                    nomatch = nomatch + 1;
                end
            end
            loss = nomatch / column;
            avgLosses(K) = loss;
 end
 best = 1;
 for K = test_K
     if avgLosses(K) < best
         best = avgLosses(K);
         ret = K;
     end
 end
[row2, column2] = size(avgLosses);
 
 for i = 1:column2
     avgAccurate(i) = 1 - avgLosses(i);
 end
 hold on;
 set(gca,'xtick',[1:1:30]);
 plot(avgAccurate,'b');

       运行结果如下:

                                        用K折交叉验证估计KNN算法中的K值_第1张图片

       个人感觉这个结果很奇怪,但是可以看出K=3的时候正确率是最高的。


你可能感兴趣的:(用K折交叉验证估计KNN算法中的K值)