KNN算法Matlab实现
简介:
KNN全称K-Nearest Neighbors,源于20世纪70年代。属于有监督学习的传统机器学习算法,既可以解决回归问题也可解决分类问题。本文章只研究K-NN的分类问题,其核心思想是离样本A距离最近的K个样本的类别代表了A的类别。放一个经典案例图:
在这个问题中,需要考虑三个核心要素:1)K值如何得到 2)样本间的距离如何定义 3)投票机制。
K值如何得到
答案是K折交叉验证法,此算法就是任意将训练数据集切分为K份,(K-1)份作为训练数据集,1份用于性能评估,其常被用到机器学习模型超参数调优上,此不详细赘述。
样本间的距离如何定义
包括但不限于如下:
- 曼哈顿距离
d 12 = ∑ k = 1 n ∣ x 1 k − x 2 k ∣ d_{12}=\sum^n_{k=1}|x_{1k}-x_{2k}| d12=k=1∑n∣x1k−x2k∣ - 欧几里得距离
d 12 = ∑ k = 1 n ∣ x 1 k − x 2 k ∣ d_{12}=\sqrt{\sum^n_{k=1}|x_{1k}-x_{2k}|} d12=k=1∑n∣x1k−x2k∣ - 马氏距离
D ( X i , X j ) = ( X i − X j ) T S − 1 ( X i − X j ) D(X_i,X_j)=\sqrt{(X_i-X_j)^TS^{-1}(X_i-X_j)} D(Xi,Xj)=(Xi−Xj)TS−1(Xi−Xj) - 闵可夫斯基距离
d 12 = ∑ k = 1 n ∣ x 1 k − x 2 k ∣ p p d_{12}=\sqrt[p]{\sum^n_{k=1}|x_{1k}-x_{2k}|^p} d12=pk=1∑n∣x1k−x2k∣p
最常用的是欧氏距离
投票机制
- 少数服从多数
- 距离加权投票(最常用)
代码实现
选用iris数据集作为训练测试的数据集,距离使用欧氏距离,投票机制使用少数服从多数。
iris=xlsread("iris.csv");
iris=iris(:,2:6);
K_Max=50;
acc_avg_history=[];
for k=1:K_Max
%K交叉验证
N=5;%K交叉验证的份数
rawrank=randperm(size(iris,1));%打乱顺序
rand_iris=iris(rawrank,:);
cell_iris=mat2cell(rand_iris,150/N*ones(1,N));%分为N份
for n=1:N
cell_iris=circshift(cell_iris,1);%移位一次
train_set=cell2mat(cell_iris(1:N-1));%取N-1份做训练集
test_set=cell_iris{N};%取N份做测试集
pre_label=knn(test_set(:,1:4),train_set,k);%KNN预测花卉种类
accuracy(n)=sum(pre_label==test_set(:,5))/(150/N);%求正确率
end
acc_average=mean(accuracy);%求平均正确率
acc_avg_history=[acc_avg_history acc_average];%保存不同K值下的正确率
end
plot(acc_avg_history);xlabel('K');ylabel('准确率');title('交叉验证(N=5)选择K值')
function out=knn(test_set,train_set,K)
[n ,~]=size(test_set);
[m,~]=size(train_set);
for i=1:n
for j=1:m
%求距离
distance(j)=sqrt(sum((test_set(i,:)-train_set(j,1:4)).^2));
end
[~,index]=sort(distance,'ascend');
label=train_set(index,5);%按照距离大小排序
out(i)=mode(label(1:K));%取前K个标签里出现次数最多的那个标签
end
out=out';
end
运行结果:不同K值对应的准确率
机器学习观止核心原理与实践,林学森著