算法思想
这是一个分类算法,这个算法的基础非常简单容易理解,首先你需要若干个已经分类标记好的数据(假设n个已分类样本),然后就可以对新输入的一个数据进行分类判别。判别流程是在n个已分类样本中找到距离新数据最近的K个样本(所以叫K近邻嘛)。然后统计K个样本的分类(就是找出K个样本的标签出现最多的是哪个标签),然后新样本分类得到的标签就是最多的哪一类的标签(得到标签了就分类完成啦)。
数据准备
使用MNIST数据集进行手写数字分类。
MNIST数据集下载:MNIST数据集CSDN下载。
实现
MATLAB代码如下,我代码中的标记数据是100个,分类效果不是很理想(注,代码写错了,修正后效果还是可以,比随机分类效果高了不少,说明算法还是有效果),可以修改代码多搞一点数据。在分类中是直接将28×28的图片按行连接作为1×784的特征样本。代码第二段是将样本重新组成28×28的图片并显示,可以删除掉。
data = csvread("f:/Dataset/MNIST/mnist_train_100.csv");
for i=1:100
p = reshape(data(i,2:end), [28, 28]);
l = data(i, 1)
imshow(p');title(num2str(l));
figure;
end
count = 0;
[n m] = size(data); % n是数据个数,m是样本维度+1
for i=1:100
if(Kneighbor(data, data(i,:), 30) == data(i,1))
count = count+1;
end
end
["分类正确率:", num2str(count/100)] %正确率仅0.14,略高于随机分类,(代码修正后正确率0.54),可以用多个已分类样本试一下。
function label = Kneighbor(ldata, data, K)
%ldata:表示已有标记的数据,ldata的第一列是标签数据
%data:需要进行分类的数据
% 算法的思想就是,从ldata中找出离data最近的K
% 个样本,看K个样本中最多的是哪一类,就将data
% 分归为哪一类%
%% 求出data到所有样本的距离
[n, ~] = size(ldata); % n个数据,m个维度
ndata = (ones([n, 1]))*data(2:end);
%distance = sum((ldata(:,2:end) - ndata).^2);
%distance = sum((ldata(:,2:end) - ndata).^2, 2);
%% 得到最近的K个样本
[~, I] = mink(distance, K);
% 统计K个样本中最多的是哪一类
classes = ldata(I,1);
label = mode(classes);
end