KNN分类算法的MATLAB实现以及可视化

一、KNN简介

KNN算法,即K-Nearest Neighbors,是一种常用的监督学习算法,可以用于分类问题,并且在实际应用中取得了广泛的成功。

二、KNN算法的基本原理

对于给定的测试样本,KNN算法首先计算它与训练集中所有样本的距离。然后,根据这些距离,选择最近的K个邻居进行投票。对于分类任务,通常取前K个样本中类别最多的作为预测结果。

2.1、距离的定义

2.2、K的取值

K的取值比较重要,那么该如何确定K取多少值好呢?答案是通过交叉验证(将样本数据按照一定比例,拆分出训练用的数据和验证用的数据,比如8:2拆分出部分训练数据和验证数据),从选取一个较小的K值开始,不断增加K的值,然后计算验证集合的准确率,最终找到一个比较合适的K值。 和K-means不一样,当K值更大的时候,错误率会更高。这也很好理解,比如说你一共就35个样本,当你K增大到30的时候,KNN基本上就没意义了。且K值一般取奇数,这样可以保证能够取到标签的众数。在下图中K值很明显取K = 3。

三、KNN是一种非参的,惰性的算法模型

非参的意思并不是说这个算法不需要参数,而是意味着这个模型不会对数据做出任何的假设,与之相对的是线性回归(我们总会假设线性回归是一条直线)。也就是说KNN建立的模型结构是根据数据来决定的,这也比较符合现实的情况,毕竟在现实中的情况往往与理论上的假设是不相符的。惰性又是什么意思呢?想想看,同样是分类算法,逻辑回归需要先对数据进行大量训(tranning),最后才会得到一个算法模型。而KNN算法却不需要,它没有明确的训练数据的过程,或者说这个过程很快。

四、KNN算法的优缺点

不对数据分布做出假设,完全基于距离度量对样本特征进行提取;不需要提前进行训练,直接可以进行分类;思想简单,应用广泛。然而,它也有一些缺点,如过度依赖距离度量函数和K值的选择、计算量大、所需内存大、可解释性差、预测速度慢等。

五、自己编写KNN算法的MATLAB实现并可视化

clear;clc;clf;
% 假设我们有一些训练数据和测试数据
train_data = [1.0,1.2;
    1.2,1.2;
    1.35,1.8;
    1.3,1.6;
    1.33,1.5;
    1.7,2.0;
    2.2,2.0;
    2.1,2.5;
    2.3,4.3;
    2.5,4.1;
    2.7,3.0;
    3.2,4.4;
    3.5,4.1;
    4.1,5.0;
    3.9,4.2;
    3.7,4.4;
    3.5,4.0;
    4.2,1.2;
    4.3,1.3;
    5.0,2.6;
    5.6,3.6;
    5.4,4.0;]; % 训练数据的特征矩阵
train_labels = [0;0;0;0;0;0;0;0;0;0;0;1;1;1;1;1;1;2;2;2;2;2]; % 训练数据的标签向量
test_data = [ 5.8,3.6;
    3.0,3.0;
    1.1,2.3;
    1.0,1.0;
    1.2,4.0;
    5.2,2.0;
    3.7,4.0;]; % 测试数据的特征矩阵
K = [3,5,7,9,11];
accuracy_value = zeros(1,5);
rng(111) %固定随机数种子
for j = 1:5
    % 假设 X 是你的特征矩阵,大小为 [NxD],其中 N 是样本数,D 是特征数
    % 假设 Y 是你的标签向量,大小为 [Nx1]
    % 设定k折交叉验证的k值
    k = K(j); 
    % 创建k折交叉验证的分区
    cvp = cvpartition(size(train_data, 1), 'KFold', k);
    % 初始化用于存储结果的变量
    accuracy = zeros(1, k); % 用于存储每次迭代的准确率
    % 循环进行k次训练和测试
    for i = 1:cvp.NumTestSets
        % 训练集和测试集的索引
        trainingIdx = training(cvp, i);
        testIdx = test(cvp, i);
        % 从原始数据中分离训练和测试数据
        XTrain = train_data(trainingIdx, :);
        YTrain = train_labels(trainingIdx);
        XTest = train_data(testIdx, :);
        YTest = train_labels(testIdx);
        % 假设你已经有了预测标签,存储在变量 predictedLabels 中
        predictedLabels =  knn_classifier(XTrain,YTrain,XTest,k);
        % 计算准确率
        correct = sum(predictedLabels == YTest);
        accuracy(i) = correct / length(YTest);
    end
    % 计算平均准确率
    meanAccuracy = mean(accuracy);
    accuracy_value(j) = meanAccuracy;
end
figure(1)
plot(K,accuracy_value,'LineWidth',1.5,'Marker','*')
xlabel('k')
ylabel('accuracy')
[L,I] = max(accuracy_value);
K = K(I);
% 调用KNN分类器函数
predicted_labels = knn_classifier(train_data, train_labels, test_data, K);
% 显示预测结果
disp(predicted_labels);
figure(2)
indices1 = find(train_labels==0);
indices2 = find(train_labels==1);
indices3 = find(train_labels==2);
h1 = scatter(train_data(indices1,1),train_data(indices1,2),25,"red","filled");
hold on
h2 = scatter(train_data(indices2,1),train_data(indices2,2),25,"blue","filled");
h3 = scatter(train_data(indices3,1),train_data(indices3,2),25,"green","filled");
indices11 = find(predicted_labels==0);
indices22 = find(predicted_labels==1);
indices33 = find(predicted_labels==2);
h11 = scatter(test_data(indices11,1),test_data(indices11,2),"red","o",'LineWidth',1.5);
h22 = scatter(test_data(indices22,1),test_data(indices22,2),"blue","o",'LineWidth',1.5);
h33 = scatter(test_data(indices33,1),test_data(indices33,2),"green","o",'LineWidth',1.5);
% % 创建网格以可视化决策边界   
xMin = min(train_data(:,1));  
xMax = max(test_data(:,1));  
yMin = min(test_data(:,2));  
yMax = max(train_data(:,2));
h = 0.02;  
[xx, yy] = meshgrid(xMin:h:xMax, yMin:h:yMax);  
% 预测网格点的标签  
labels = knn_classifier(train_data, train_labels,[xx(:), yy(:)],K);  
labels = reshape(labels, size(xx));
alpha = 0.2;
contourf(xx, yy, labels, 'LineWidth',1.5,'FaceAlpha',alpha); % 绘制决策边界  
title(['KNN Decision Boundary (K = ' num2str(K) ')']);  
xlabel('Feature 1');  
ylabel('Feature 2'); 
box on

function label = knn_classifier(train_data, train_labels, test_data, K)
% train_data: 训练数据的特征矩阵,大小为 [NxD],其中N是样本数,D是特征维度
% train_labels: 训练数据的标签向量,大小为 [Nx1]
% test_data: 测试数据的特征矩阵,大小为 [MxD]
% K: 最近邻居的数量
% label: 测试数据的预测标签向量,大小为 [Mx1]
%——————————————————————————————————————————————————————————————
% 初始化预测标签向量
label = zeros(size(test_data, 1), 1);
% 遍历测试数据集中的每个样本
for i = 1:size(test_data, 1)
    % 计算测试样本到所有训练样本的距离
    % 距离函数d(x,y)需要满足三个条件:
    % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    % d(x,y)>=0,d(x,y)==0<=>x==y(正定性)
    % d(x,y)==d(y,x)(对称性)
    % d(x,y)<=d(x,z)+d(z,y)(三角不等式)
    %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    distances = sum((train_data - test_data(i, :)).^2, 2); %欧氏距离
%   distances = sum(abs(train_data - test_data(i, :)),2); %曼哈顿距离
    % 获取距离排序后的索引
    [~,sortedDistIndices] = sort(distances); %默认升序排列
    % 找出最近的K个邻居的索引
    neighbors_indices = sortedDistIndices(1:K);
    % 提取这K个邻居的标签
    neighbors_labels = train_labels(neighbors_indices);
    % 统计并找出最常见的标签
    [most_common_label, ~] = mode(neighbors_labels); %众数
    % 将最常见的标签赋给测试样本
    label(i) = most_common_label;
end
end

分别运用欧氏距离和曼哈顿距离的运行结果如下图:

 六、KNN算法的适用范围:

  1. 数据特征明确且重要:当数据的特征空间具有清晰的边界,且特征对分类结果有显著影响时,KNN算法通常能表现出色。这是因为KNN直接基于特征空间中的距离来进行分类,所以特征的选择和表示对于算法性能至关重要。

  2. 样本数量适中:对于中等大小的数据集,KNN算法通常是一个有效的选择。然而,当数据集非常大时,KNN的计算成本可能会显著增加,因为需要计算每个查询点与所有训练点之间的距离。在这种情况下,可能需要考虑使用更高效的算法或数据结构来加速距离计算。

  3. 数据分布不均匀:KNN算法对数据的分布没有严格的假设,因此它适用于那些不符合正态分布或其他特定分布的数据集。特别是在数据分布不均匀或存在多个类别的情况下,KNN算法能够很好地处理这些复杂情况。

  4. 类别决策边界复杂:当类别的决策边界非常复杂或不规则时,KNN算法可能是一个好选择。由于KNN算法是基于实例的,它可以很好地捕捉数据中的局部结构和模式,从而在处理复杂决策边界时表现出色。

  5. 实时更新:KNN算法在需要实时更新分类模型的情况下非常有用。由于它不需要显式的训练阶段,只需存储训练数据即可,因此当新的数据点出现时,可以很容易地将其纳入分类过程中。

需要注意的是,虽然KNN算法在某些情况下表现良好,但它也有一些局限性。例如,它对特征的缩放和噪声敏感,可能需要进行特征预处理和参数调优以获得最佳性能。此外,KNN算法的计算成本随着数据集的增长而增加,因此在处理大型数据集时可能不够高效。在选择是否使用KNN算法进行分类时,需要综合考虑这些因素。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/529187.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MySQL-用户与权限管理:用户管理、权限管理、角色管理

用户与权限管理 用户与权限管理1.用户管理1.1 登录MySQL服务器1.2 创建用户1.3 修改用户1.4 删除用户1.5 设置当前用户密码1.6 修改其它用户密码 2. 权限管理2.1 权限列表2.2 授予权限的原则2.3 授予权限2.4 查看权限2.5 收回权限 访问控制连接核实阶段请求核实阶段 3. 角色管理…

拯救鲨鱼!Helping wireshark!wireshark未响应解决方法

前言 做题的的时候 在用wireshark解密tls秘钥的时候 我的小鲨鱼突然未响应了 然后我多次尝试无果 并且殃及池鱼 我电脑上所有的流量包都打不开了&#xff1f;&#xff01;&#xff01;&#xff01; 于是乎 尝试删了重下 还是未响应 开始怀疑电脑 重启电脑两次 还是打…

Ngnix常用配置及和基本功能讲解

Nginx已经广泛应用于J-one和Jdos的环境部署上&#xff0c;本文对Nginx的常用的配置和基本功能进行讲解&#xff0c;适合Nginx入门学习。 1 核心配置 找到Nginx安装目录下的conf目录下nginx.conf文件&#xff0c;Nginx的基本功能配置是由它提供的。 1.1 配置文件结构 Nginx的…

Xinstall:专业的App下载量统计工具,让推广效果可衡量

在移动互联网时代&#xff0c;App的下载量是衡量一个应用受欢迎程度的重要指标。然而&#xff0c;很多开发者和广告主在推广App时&#xff0c;都面临着一个共同的问题&#xff1a;如何准确统计App的下载量&#xff1f;这不仅关系到推广效果的评估&#xff0c;还直接影响到广告R…

lombok详解

一&#xff1a;概述 lombok是一种java使用的开发工具&#xff0c;可以帮助我们快速开发java中pojo实体类&#xff0c;通过注解消除java的冗余的java代码。 官网&#xff1a;projectlombok.org 原理&#xff1a;通过JDK6提供的新特性&#xff0c;在javac编译期间处理注解&…

Django admin日志记录模块的使用,拓展LogEntry日志记录跳转改动详情页,日志搜索等功能

1、django admin日志记录引入 在使用django admin开发后台管理系统时&#xff0c;可以在admin模块中将django admin自带的操作日志记录模块注册到管理面板 from django.contrib.admin.models import LogEntry 可以看到引入后django admin的菜单栏新增出了一条日志记录的按钮 …

QT windeployqt打包出现无法正常启动问题

QT 通过windeployqt 打包后出现的问题 原因QT构建选择的是64位的 但是windows下运行的却是32位的 步骤打开32的所在路径 一般在上一级目录会有安装好的64位的MSVC工具 运行打包即可

秋招复习笔记——八股文部分:操作系统

笔试得刷算法题&#xff0c;那面试就离不开八股文&#xff0c;所以特地对着小林coding的图解八股文系列记一下笔记。 这一篇笔记是图解系统的内容。 硬件结构 CPU执行程序 计算机基本结构为 5 个部分&#xff0c;分别是运算器、控制器、存储器、输入设备、输出设备&#xf…

梵宁教育课程深度解析:设计技能提升,从这里开始

在当今数字化快速发展的时代&#xff0c;设计技能已成为个人职业发展的重要一环。无论是从事广告、媒体、UI设计还是其他相关领域&#xff0c;拥有扎实的设计技能都意味着拥有了更多的职业机会和发展空间。梵宁教育&#xff0c;作为业界知名的教育机构&#xff0c;以其专业的课…

4.9作业

1、完善对话框&#xff0c;点击登录对话框&#xff0c;如果账号和密码匹配&#xff0c;则弹出信息对话框&#xff0c;给出提示”登录成功“&#xff0c;提供一个Ok按钮&#xff0c;用户点击Ok后&#xff0c;关闭登录界面&#xff0c;跳转到其他界面 如果账号和密码不匹配&…

推进数智化财务管理体系,助力企业降本提效

在数字经济快速发展的今天&#xff0c;数字化能力早已成为企业发展的核心竞争力。在开放、融合的数字经济大背景下&#xff0c;企业该如何将科技深度赋能业务&#xff0c;打造出高质量发展的新引擎&#xff1f;当财务管理缺乏精准化、精确化、及时性的问题逐渐显露&#xff0c;…

关于51单片机TMOD定时器的安全配置

定时器介绍&#xff1a; -------------------------------------------------------------------------------------------------------------------------- 首先配置的是控制寄存器 TCON 说直白点&#xff0c;这个寄存器就是用来计数的&#xff0c;打开计时器&#xff0c;关…

基于51单片机轮胎胎压监测系统—数码管显示

基于51单片机轮胎胎压监测系统 &#xff08;仿真&#xff0b;程序&#xff0b;设计报告&#xff09; 功能介绍 具体功能&#xff1a; 1.MPX4115压力传感器胎压检测&#xff1b; 2.ADC0832进行模数转换后&#xff0c;51单片机处理控制&#xff1b; 3.数码管显示胎压&#xff…

ST Motor Control Workbench生成工程报错PDSC version is not supported解决办法

文章目录 前言一、报错相关信息二、解决办法 前言 使用 ST Motor Control Workbench 5.4.4 FOC 电机开发工具和 stm32cubemx 6.1.1 生成的工程报错&#xff0c;记录一下解决的办法。 一、报错相关信息 报错信息如下&#xff1a; 2024-04-09 18:35:28,527 ERROR [LineInfo_to…

【Linux】虚拟化技术docker搭建SuitoCRM系统及汉化

CRM系统 CRM&#xff08;Customer Relationship Management&#xff0c;客户关系管理&#xff09;系统是一种用于管理和优化企业与客户关系的软件工具。在商业竞争激烈的现代社会中&#xff0c;CRM系统已成为许多企业提高销售、增强客户满意度和实现持续增长的重要工具。本文将…

FME学习之旅---day21

我们付出一些成本&#xff0c;时间的或者其他&#xff0c;最终总能收获一些什么。 教程&#xff1a;AutoCAD 变换 相关的文章 为您的 DWG 赋予一些样式&#xff1a;使用 DWGStyler、模板文件、块等 FME数据检查器在显示行的方式上受到限制。它只能显示线条颜色&#xff0c;而…

一文讲清如何用BI进行商品分析之返货品画像分析

01 什么是商品画像&#xff0c;怎样进行商品分析 “用户画像对于小伙伴们来说并不陌生&#xff0c;那有小伙伴知道商品画像吗&#xff1f;其实它和用户画像一样&#xff0c;可以简单理解成是商品海量数据的标签。” 商品画像的意义在于可以对商品进行精准的定位&#xff0c;让…

Linux初学(十七)防火墙

一、防火墙简介 1.1 防火墙的类别 安全产品 杀毒&#xff1a; 针对病毒&#xff0c;特征篡改系统中的文件杀毒软件针对处理病毒程序防火墙&#xff1a; 针对木马&#xff0c;特征系统窃取防火墙针对处理木马 防火墙分为两种 硬件防火墙软件防火墙 硬件防火墙 各个网络安全…

鸿蒙、如何使用@ohos.contact 接口,实现对联系人的增删查改功能

介绍 本示例使用ohos.contact 接口&#xff0c;实现了对联系人的增删查改功能。 效果预览 使用说明 1.点击 按钮&#xff0c;跳转添加联系人界面&#xff0c;输入联系人信息&#xff0c;点击 √&#xff0c;确认添加联系人&#xff0c;并返回首页&#xff1b; 2.点击联系人…

关于阿里云centos系统下宝塔面板部署django/中pip install mysqlclient失败问题的大总结

python版本3.12.0 问题1 解决方案 sudo vim /etc/profile export MYSQLCLIENT_CFLAGS"-I/usr/include/mysql" export MYSQLCLIENT_LDFLAGS"-L/usr/lib64/mysql" Esc退出编辑模式 &#xff1a;wq退出并且保存 问题二 说是找不到 mysql.h头文件 CentOS ‘…