使用背景:
基于 KNN 的相关算法,已成功应用于手写体识别、数字验证识别、文本识别、聚类分析、预测分析、模式识别、图像处理等。
操作步骤:
对于如何实现 K N N KNN KNN 算法,针对传统 K N N KNN KNN 算法,可分为 7 7 7 步。
- 初始化距离值为最大值,便于在搜索过程中迭代掉。
- 计算待分类样本和每个训练样本的距离 d i s t dist dist。
- 得到目前 k k k 个最邻近样本中的最大距离 m a x d i s t maxdist maxdist。
- 如果 d i s t dist dist 小于 m a x d i s t maxdist maxdist,则将该训练样本作为 k k k 最邻近样本。
- 重复步骤 2 2 2、 3 3 3、 4 4 4,直到未知样本和所有训练样本的距离都算完。
- 统计 k k k 邻近样本中每个类标号出现的次数。
- 选择出现频率最大的类标号作为未知样本的类标号。
实例分析:
假设,有一个具体应用为区分某一电影为动作片还是武侠片。首先,需要建立已知标签的样本,通过人工统计或数字图像处理技术统计众多电影中打斗镜头和接吻镜头数,并对相应的电影进行标签标注。之后,如果有一部未看过的电影,如何通过机器计算的方式判断其为动作片还是爱情片。此时,就可以使用 K N N KNN KNN 算法解决。
解决方案:
为了方便起见,对于有标签的数据样本通过 M A T L A B MATLAB MATLAB 随机生成,其主要利用两个随机高斯分布生成两类数据(假设打斗镜头数、接吻镜头数可为小数),并对第一类数据(假设为动作片)标记为 1 1 1,另一类数据(假设为爱情片)标记为 2 2 2。
待测样本分别为接吻镜头数 3 ∼ 7 3\sim7 3∼7 遍历和打斗镜头数 3 ∼ 7 3\sim7 3∼7 遍历产生的 25 25 25 个数据,通过 K N N KNN KNN 算法,对电影类别的判断如下图所示,其中“·”表示动作片,“*”表示爱情片。
代码如下:
KNN_Self.m
clear all;
close all;
clc;
%%利用高斯分布,生成动作片数据和标签
aver1=[8 3]; %均值
covar1=[2 0;0 2.5]; %2维数据的协方差
data1=mvnrnd(aver1,covar1,100); %产生高斯分布数据
for i=1:100 %另高斯分布产生数据中的复数为0
for j=1:2 %因为打斗镜头数和接吻镜头数不能为负数
if data1(i,j)<0
data1(i,j)=0;
end
end
end
label1=ones(100,1); %将该类数据的标签定义为1
plot(data1(:,1),data1(:,2),'+'); %用+绘制出数据
axis([-1 12 -1 12]); %设定两坐标轴范围
xlabel('打斗镜头数'); %标记横轴为打斗镜头数
ylabel('接吻镜头数'); %标记纵轴为接吻镜头数
hold on;
%%利用高斯分布,生成爱情片数据和标签
aver2=[3 8];
covar2=[2 0;0 2.5];
data2=mvnrnd(aver2,covar2,100); %产生高斯分布数据
for i=1:100 %另高斯分布产生数据中的复数为0
for j=1:2 %因为打斗镜头数和接吻镜头数不能为负数
if data2(i,j)<0
data2(i,j)=0;
end
end
end
plot(data2(:,1),data2(:,2),'ro'); %用o绘制出数据
label2=label1+1; %将该类数据的标签定义为2
data=[data1;data2];
label=[label1;label2];
K=11; %两个类,一般K取奇数有利于测试数据属于那个类
%测试数据,KNN算法看这个数属于哪个类,测试数据共计25个
%打斗镜头数遍历3-7,接吻镜头书也遍历3-7
for movenum=3:1:7
for kissnum=3:1:7
test_data=[movenum kissnum]; %测试数据,为5X5矩阵
%%下面开始KNN算法,显然这里是11NN。
%求测试数据和类中每个数据的距离,欧式距离(或马氏距离)
distance=zeros(200,1);
for i=1:200
distance(i)=sqrt((test_data(1)-data(i,1)).^2+(test_data(2)-data(i,2)).^2);
end
%选择排序法,只找出最小的前K个数据,对数据和标号都进行排序
for i=1:K
ma=distance(i);
for j=i+1:200
if distance(j)<ma
ma=distance(j);
label_ma=label(j);
tmp=j;
end
end
distance(tmp)=distance(i); %排数据
distance(i)=ma;
label(tmp)=label(i); %排标签
label(i)=label_ma;
end
cls1=0; %统计类1中距离测试数据最近的个数
for i=1:K
if label(i)==1
cls1=cls1+1;
end
end
cls2=K-cls1; %类2中距离测试数据最近的个数
if cls1>cls2
plot(movenum,kissnum, 'k.'); %属于类1(动作片)的数据画小黑点
else
plot(movenum,kissnum, 'g*'); %属于类2(爱情片)的数据画绿色*
end
label=[label1;label2]; %更新label标签排序
end
end
KNN_Mat.m
% %Matlab 自带KNN算法函数knnclassify实现
clc
close all;
clear
%生成200个样本数据
Training = [mvnrnd([2 2],eye(2), 100); mvnrnd([-2 -2], 2*eye(2), 100)];
%mvnrnd([2 2],eye(2),100)表示随机生成多元正态分布100X2矩阵,每一列以2,2为均值,eye(2)为协方差
%200个样本数据前100标记为标签1,后100个标记为标签2
Group = [ones(100,1); 2*ones(100,1)];
%绘制出离散的样本数据点
gscatter(Training(:,1),Training(:,2),Group,'rc','*x');
hold on;
% 生成待分类样本20个
Sample = unifrnd(-2, 2, 20, 2);
%产生一个100X2,这个矩阵中的每个元素为20 到30之间连续均匀分布的随机数
K=3;%KNN算法中K的取值
cK = fitcknn(Sample,Training,Group,K);
gscatter(Sample(:,1),Sample(:,2),cK,'rc','os');