模式识别与机器学习(五):knn及MATLAB实现

1.数据划分(使用k折交叉验证)

rawrank=randperm(size(data4,1));%打乱顺序
rand_data=data4(rawrank,:);
cell_data=mat2cell(rand_data,[42 42 42 42 40]);%分为N份
    for n=1:N
        cell_data=circshift(cell_data,1);%移位一次
        train_set=cell2mat(cell_data(1:N-1));%取N-1份做训练集
        test_set=cell_data{N};%取N份做测试集
    end

2.knn

KNN
选择算法
递增排序
计算距离
选取k个点
确定出现频率
返回频率最高的类别
欧氏距离
欧几里得距离

我们把KNN算法写进名为knn的函数之中,便于我们训练

function out=knn(test_set,train_set,K)
    [n ,~]=size(test_set);
    [m,~]=size(train_set);
    distance=ones(1,m);
    out=ones(1,n);
    for i=1:n
        for j=1:m
            %求欧式距离
            % distance(j)=sqrt(sum((test_set(i,1:end-1)-train_set(j,1:end-1)).^2));
            % 求曼哈顿距离
            distance(j)=sum(abs(test_set(i,1:end-1)-train_set(j,1:end-1)));
            % 求欧几里得距离
            % distance(j)=sqrt(sum(abs(test_set(i,1:end-1)-train_set(j,1:end-1))));
            % 求马氏距离
            % distance(j)=sqrt((test_set(i,1:end-1)-train_set(j,1:end-1))'*cov([test_set(i,1:end-1)' train_set(j,1:end-1)'])*(test_set(i,1:end-1)-train_set(j,1:end-1)));
            
        end
        sum1=0;
        sum2=0;
        [d,index]=sort(distance,'ascend');
        d1=d(1:K)./(sum(d(1:K)));
        label=train_set(index(1:K),end);%按照距离大小排序
        for k=1:K
            if(label(k)==1)
                sum1=sum1+d1(k);
            else
                sum2=sum2+d1(k);
            end
        end
        if(sum2>sum1)
            out(i)=2;
        else
            out(i)=1;
        end        
    end   
    out=out';
end

knn最重要的是选择k和计算距离的算法

2.1欧几里得距离

在这里插入图片描述

2.2欧氏距离1

由上图可知我们选择k为1,准确率较高。

3.结果

3.1欧氏距离

在这里插入图片描述

3.2欧几里得距离

在这里插入图片描述

4.代码

clc;clear;
rng(1)
% 读数据
data=readtable("sonar.csv");
data1=table2array(data(:,1:60));
data2=table2array(data(:,61));
% 标签二值化
labels=ones(208,1);
for i=1:208
    if(data2{i}=='R')
        labels(i)=1;
    else
        labels(i)=2;
    end
end
data4=[data1 labels];
% 设置参数
K_Max=1;%k的最大值
N=5;%K交叉验证的份数
accuracy=ones(N,1);
acc=ones(K_Max,1);
n1=0;
n2=0;
n3=0;
n4=0;

% 开始训练
for k=1:K_Max
    % K交叉验证
    rawrank=randperm(size(data4,1));%打乱顺序
    rand_data=data4(rawrank,:);
    cell_data=mat2cell(rand_data,[42 42 42 42 40]);%分为N份
    for n=1:N
        cell_data=circshift(cell_data,1);%移位一次
        train_set=cell2mat(cell_data(1:N-1));%取N-1份做训练集
        test_set=cell_data{N};%取N份做测试集
        pre_label=knn(test_set,train_set,k);%KNN预测
        accuracy(n)=sum(pre_label==test_set(:,end))/length(test_set(:,end));%求正确率
        n1=n1+length(find(test_set(pre_label==1,end)==1));
        n2=n2+length(find(test_set(pre_label==1,end)==2));
        n3=n3+length(find(test_set(pre_label==2,end)==1));
        n4=n4+length(find(test_set(pre_label==2,end)==2));
    end
    acc_average=mean(accuracy);%求平均正确率
    acc(k)=acc_average;
    
end

% plot(acc,'k.-','Linewidth',1,'MarkerSize',10);xlabel('K');ylabel('准确率');title('交叉验证(N=5)选择K值')

ConfMat = [n1,n2;n3,n4];
ProbMat = round(ConfMat/sum(ConfMat(:))*100,2);
imagesc(ConfMat)
my=colorplus([1,3]);
colormap(my)
% 设置坐标
xticks([1,2])
xticklabels({'T','N'})
yticks([1,2])
yticklabels({'T','N'})

% 填写信息
T = 30;
g = 0.2;
text(1-g,1,{'True Neg';num2str(ConfMat(1));strcat(num2str(ProbMat(1)),'%')},...
    'Color',[1,1,1]*double(ProbMat(1)>T))
text(1-g,2,{'False Pos';num2str(ConfMat(2));strcat(num2str(ProbMat(2)),'%')},...
    'Color',[1,1,1]*double(ProbMat(2)>T))
text(2-g,1,{'False Neg';num2str(ConfMat(3));strcat(num2str(ProbMat(3)),'%')},...
    'Color',[1,1,1]*double(ProbMat(3)>T))
text(2-g,2,{'True Pos';num2str(ConfMat(4));strcat(num2str(ProbMat(4)),'%')},...
    'Color',[1,1,1]*double(ProbMat(4)>T))
set(gcf,'color',[1,1,1])
set(gca,'linewidth',1.5)
set(gca,'FontSize',12,'Fontname', 'Times New Roman');
function out=knn(test_set,train_set,K)
    [n ,~]=size(test_set);
    [m,~]=size(train_set);
    distance=ones(1,m);
    out=ones(1,n);
    for i=1:n
        for j=1:m
            %求欧式距离
            % distance(j)=sqrt(sum((test_set(i,1:end-1)-train_set(j,1:end-1)).^2));
            % 求曼哈顿距离
            %distance(j)=sum(abs(test_set(i,1:end-1)-train_set(j,1:end-1)));
            % 求欧几里得距离
            distance(j)=sqrt(sum(abs(test_set(i,1:end-1)-train_set(j,1:end-1))));
            % 求马氏距离
            % distance(j)=sqrt((test_set(i,1:end-1)-train_set(j,1:end-1))'*cov([test_set(i,1:end-1)' train_set(j,1:end-1)'])*(test_set(i,1:end-1)-train_set(j,1:end-1)));
            
        end
        sum1=0;
        sum2=0;
        [d,index]=sort(distance,'ascend');
        d1=d(1:K)./(sum(d(1:K)));
        label=train_set(index(1:K),end);%按照距离大小排序
        for k=1:K
            if(label(k)==1)
                sum1=sum1+d1(k);
            else
                sum2=sum2+d1(k);
            end
        end
        if(sum2>sum1)
            out(i)=2;
        else
            out(i)=1;
        end        
    end   
    out=out';
end
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

从零开始的奋豆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值