前几天用KNN对自己的数据进行了分类,对于KNN中的K值,之前一直是靠缘分来试的,试的时候感觉K=3的效果挺好的。之后看了好多优快云的博客,发现一般大家除了靠缘分去试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的时候正确率是最高的。
本文介绍了如何利用K折交叉验证方法来选择KNN算法中的K值。通过在MATLAB中使用crossvalind函数,将数据集划分为K个子集,轮流将其中一个作为测试集,其余作为训练集,最后计算所有测试结果的平均分类率,以确定最佳的K值。实验证明,当K=3时,分类正确率最高。
1027





