模式识别 matlab实现K近邻

135 阅读2分钟

​本文已参与「新人创作礼」活动,一起开启掘金创作之路。

关于K近邻的基础知识看这位优秀博主的文章:模式识别(Pattern Recognition)学习笔记(二十五)--最近邻法_eternity1118_的博客-CSDN博客

这里只讲实现:

贴下代码:

注:

数据的处理:我这里是从已知样本中各选取一半,一半用来做测试样本,即Iris_test,一半用来做训练,即Iris_xun,而且训练样本前25个是第一类,26-50是第二类,51-75是第三类。请看代码时时刻记得。

K近邻:只是在那个for循环里面,里面还夹杂着画图等等语句。

%% k近邻  
clear;clc;
fid = fopen('Iris.txt','r','n','UTF-8');
test1 = fopen('Iris.txt');
T2=textscan(test1,'%f%f%f%f%f','Delimiter',{':',';'});
Iris_Matri = [T2{1,2},T2{1,3},T2{1,4},T2{1,5}];
Iris_xun = [Iris_Matri(1:25,:);Iris_Matri(51:75,:);Iris_Matri(101:125,:)];
Iris_test =[Iris_Matri(26:50,:);Iris_Matri(76:100,:);Iris_Matri(126:150,:)];
k =1;
temp_vect = zeros(75,1);
temp = 0; temp_index = 0;score = zeros(k,1);
temp_vect_sort = zeros(75,1);
error = 0;label_data = zeros(75,1);
for i =1:75   %i表示第几个测试样本
    for j =1:75  %j代表了训练样本的下标
        if(j<=25)
            label_data(j,1) = 1;
        elseif(j<=50)
            label_data(j,1) = 2;
        else
            label_data(j,1) = 3;
        end
        temp_vect(j,1) =sqrt( ( Iris_test(i,1)-Iris_xun(j,1) )^2   + ( Iris_test(i,2)-Iris_xun(j,2) )^2 +( Iris_test(i,3)-Iris_xun(j,3) )^2   + ( Iris_test(i,4)-Iris_xun(j,4) )^2 );
    end
    [B,temp_index]  = sort(temp_vect,'ascend'); %B是排序,index是原位置
    resultlable = label_data(temp_index(1:k));
    w1_num = length(find(resultlable==1));w2_num =length( find(resultlable==2));
    w3_num =length( find(resultlable==3)); %a表示K近邻中判断是第一类的个数,b,c类似类似
    policy_vec = [w1_num,w2_num,w3_num];[x,inde_fin]=max(policy_vec);
    fprintf('第%d个样本是第%d类\n',i,inde_fin);
    if(label_data(i) ~= inde_fin)
        error =error+1;
        flag = 1;
    end   
    if(flag)
         plot( Iris_test(i,4), Iris_test(i,3),'rs' );
         flag =0;
    else
        % 训练样本蓝点,测试样本红,错误的黑色框
        if(inde_fin == 1)
            plot( Iris_xun(i,4), Iris_xun(i,3),'ro' );
            plot( Iris_test(i,4), Iris_test(i,3),'ro' );
        elseif(inde_fin == 2)
            plot( Iris_xun(i,4), Iris_xun(i,3),'go-' );
            plot( Iris_test(i,4), Iris_test(i,3),'go-' );
        else
            plot( Iris_xun(i,4), Iris_xun(i,3),'bo' );
            plot( Iris_test(i,4), Iris_test(i,3),'go' );
        end
    end
    
    hold on;
end
fprintf('             %d近邻测试\n',k);
fprintf('共测试了%d个数据   训练了%d个数据\n',i,j);
fprintf('错误的个数为:%d,   错误率为 %f%%',error,error*100/i);

看下结果:

最近邻:

一近邻样本分布图:

3近邻:

15近邻:

29近邻:

include:

①:从样本分布图中可以看出,第二类和第三类其实没有很明显的界限,而判别方式只是简单的根据测试样本距离已知样本的距离判断测试样本该属于哪一类。

②:从错误率的增加我们可以看出,随着K的增大,对于测试样本的打分的权重越来越重要,去距离测试样本近的前K个,但是最近的那个和最远的那个的判断的权重不应该一样(上面代码是一样的),最近的话语权相对肯定最大些。