1. 程式人生 > >用K折交叉驗證估計KNN演算法中的K值

用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=3的時候正確率是最高的。