K近邻算法的 MATLAB 实践

使用背景:

基于 KNN 的相关算法,已成功应用于手写体识别、数字验证识别、文本识别、聚类分析、预测分析、模式识别、图像处理等。


操作步骤:

对于如何实现 K N N KNN KNN 算法,针对传统 K N N KNN KNN 算法,可分为 7 7 7 步。

  1. 初始化距离值为最大值,便于在搜索过程中迭代掉。
  2. 计算待分类样本和每个训练样本的距离 d i s t dist dist
  3. 得到目前 k k k 个最邻近样本中的最大距离 m a x d i s t maxdist maxdist
  4. 如果 d i s t dist dist 小于 m a x d i s t maxdist maxdist,则将该训练样本作为 k k k 最邻近样本。
  5. 重复步骤 2 2 2 3 3 3 4 4 4,直到未知样本和所有训练样本的距离都算完。
  6. 统计 k k k 邻近样本中每个类标号出现的次数。
  7. 选择出现频率最大的类标号作为未知样本的类标号。

实例分析:

假设,有一个具体应用为区分某一电影为动作片还是武侠片。首先,需要建立已知标签的样本,通过人工统计或数字图像处理技术统计众多电影中打斗镜头和接吻镜头数,并对相应的电影进行标签标注。之后,如果有一部未看过的电影,如何通过机器计算的方式判断其为动作片还是爱情片。此时,就可以使用 K N N KNN KNN 算法解决。


解决方案:

为了方便起见,对于有标签的数据样本通过 M A T L A B MATLAB MATLAB 随机生成,其主要利用两个随机高斯分布生成两类数据(假设打斗镜头数、接吻镜头数可为小数),并对第一类数据(假设为动作片)标记为 1 1 1,另一类数据(假设为爱情片)标记为 2 2 2

待测样本分别为接吻镜头数 3 ∼ 7 3\sim7 37 遍历和打斗镜头数 3 ∼ 7 3\sim7 37 遍历产生的 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矩阵,每一列以22为均值,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,这个矩阵中的每个元素为2030之间连续均匀分布的随机数
K=3;%KNN算法中K的取值
cK = fitcknn(Sample,Training,Group,K);
gscatter(Sample(:,1),Sample(:,2),cK,'rc','os');

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值