用K折交叉驗證估計KNN演算法中的K值
阿新 • • 發佈:2018-12-31
前幾天用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的時候正確率是最高的。