💡 建议初学者掌握KNN作为理解其他复杂算法(如SVM、决策树、神经网络)的基石。

K近邻算法(K-Nearest Neighbors, KNN)详解:原理、实践与优化

K近邻算法(K-Nearest NeighboKrs,简称KNN)是一种经典、直观且易于实现的监督学习方法,既可用于分类,也可用于回归。它“懒惰”地存储所有训练样本,直到有新样本需要预测时才临时计算,因此也被称为“懒惰学习算法”。
本文将系统介绍KNN的核心思想、算法流程、距离度量、超参数、优缺点、使用方法与完整Python实战案例,帮助读者从理论到实践全面掌握这一算法。


一、核心思想 🧠

KNN 基于以下假设:

近朱者赤,近墨者黑”:一个样本的标签很可能与其最近邻的样本标签一致。

具体流程:

  • 对新样本,计算它与训练集中所有样本的距离;

  • 选出距离最小的 K 个邻居;

  • 分类:根据邻居类别投票(通常为多数投票,但可加权);

  • 回归:返回邻居标签的平均值或加权平均值。

其中,三个核心超参数影响性能:

  • K 值

  • 距离度量方式

  • 投票或加权策略


二、算法流程(以分类为例)

  1. 准备训练集与测试集

  2. 对测试集中每个新样本,计算其与所有训练样本的距离

  3. 对距离排序,选取最近的 K 个邻居

  4. 投票或加权,输出预测类别

  5. 返回所有样本的预测值(分类/回归结果)


三、常见距离度量方法

不同的任务场景和数据类型,可能需要不同的距离度量方式:

距离类型定义适用场景
欧氏距离(L₂)∑(xi−yi)2\sqrt{\sum (x_i - y_i)^2}连续特征,标准的距离度量
曼哈顿距离(L₁)(\sumx_i - y_i
闵可夫斯基距离(Lₚ)(\left(\sumx_i - y_i
余弦相似度x⋅y∥x∥∥y∥\dfrac{x \cdot y}{\|x\|\|y\|}文本或向量空间数据的方向相似度
汉明距离不同位数数目分类特征、二进制特征或字符串比较

⚠️ 注意:使用KNN前通常需要对数据做标准化(如Z-score或Min-Max),防止量纲不同导致距离计算失真。


四、KNN的关键超参数

1. K值选择

  • K太小 → 模型复杂,容易过拟合,对噪声敏感;

  • K太大 → 模型过于平滑,可能欠拟合。

通常使用**交叉验证(GridSearchCV)**选择合适的K值。

2. 距离度量方式

根据特征类型和数据分布选择距离函数(见上表)。

3. 权重策略

  • uniform:每个邻居权重相同;

  • distance:距离越近的邻居权重越大。

4. 最近邻搜索算法

  • brute:暴力搜索,适合小规模数据;

  • kd_tree / ball_tree:适合中等维度(<30)的数据;

  • 高维/大规模数据推荐使用近似搜索库:如 Faiss、Annoy、ScaNN。


五、KNN的优缺点

✅ 优点

  • 简单直观,易于实现;

  • 无需训练,可直接使用训练数据;

  • 天然支持多分类与回归;

  • 非线性决策边界处理能力强。

❌ 缺点

  • 预测时计算量大,难以实时响应;

  • 内存消耗高,需保存全部训练样本;

  • 高维数据效果差(维度灾难);

  • 对异常值、数据不平衡敏感。


六、KNN使用方法

发挥knn作用的代码:

# 创建一个 KNN 分类器对象,设置邻居数量 k=3
knn = KNeighborsClassifier(n_neighbors=3)# 在训练集上训练模型
knn.fit(X_train, y_train)# 在测试集上进行预测
y_pred = knn.predict(X_test)# 评估预测结果的准确率
accuracy = accuracy_score(y_test, y_pred)

核心参数:

  1. n_neighbors

    • 类型:整数,默认值为 5。
    • 作用:指定用于分类的近邻数量(即 K 值)。
    • 示例n_neighbors=3表示选择最近的 3 个样本进行投票。
  2. weights

    • 类型:字符串或可调用函数,默认值为'uniform'
    • 作用:确定近邻的权重计算方式。
      • 'uniform':所有近邻权重相等。
      • 'distance':权重与距离成反比(距离越近,权重越大)。
      • 自定义函数:需接受距离数组并返回权重数组。
  3. algorithm

    • 类型:字符串,可选值为'auto''ball_tree''kd_tree''brute',默认'auto'
    • 作用:选择用于计算最近邻的算法。
      • 'auto':自动选择最合适的算法。
      • 'brute':暴力搜索(适用于小规模数据)。
      • 'kd_tree':KD 树(适用于低维数据)。
      • 'ball_tree':球树(适用于高维数据)。
  4. leaf_size

    • 类型:整数,默认值为 30。
    • 作用:控制ball_treekd_tree的叶节点大小。
    • 影响:较小的值会增加树的构建时间,但可能提高查询效率。
  5. p

    • 类型:整数,默认值为 2。
    • 作用:明可夫斯基距离(Minkowski distance)的参数。
      • p=1:曼哈顿距离(L1 范数)。
      • p=2:欧氏距离(L2 范数)。
      • 其他值:推广的 Minkowski 距离。

使用案例:

以鸢尾花数据为例(可直接导入数据)完整代码:

# 导入所需的库
from sklearn.datasets import load_iris                      # 用于加载鸢尾花数据集
from sklearn.model_selection import train_test_split        # 用于划分训练集和测试集
from sklearn.neighbors import KNeighborsClassifier          # K近邻分类器
from sklearn.metrics import accuracy_score                  # 用于评估模型准确率# 1. 加载鸢尾花数据集(Iris 数据集是一个经典的机器学习分类数据集)
iris = load_iris()          # 加载数据集
X = iris.data               # 特征数据:4个特征(花萼长度、花萼宽度、花瓣长度、花瓣宽度)
y = iris.target             # 标签数据:3个类别(0=setosa,1=versicolor,2=virginica)# 2. 将数据集划分为训练集和测试集
# test_size=0.2 表示20%作为测试集,80%作为训练集
# random_state=42 保证每次运行划分方式一致(可复现)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)# 3. 创建一个 KNN 分类器对象,设置邻居数量 k=3
knn = KNeighborsClassifier(n_neighbors=3)# 4. 在训练集上训练模型
knn.fit(X_train, y_train)# 5. 在测试集上进行预测
y_pred = knn.predict(X_test)# 6. 评估预测结果的准确率
accuracy = accuracy_score(y_test, y_pred)
print("模型在测试集上的准确率:", accuracy)


七、实践建议与优化技巧

问题类型优化建议
高维数据(维度灾难)使用 PCA、t‑SNE、UMAP 等进行降维处理
类别不平衡使用加权投票(distance)或 SMOTE 等过采样方法
大规模训练样本使用 Faiss、Annoy 等近似邻居搜索库
实时响应需求构建索引结构(KD‑Tree、Ball‑Tree)或 LSH 近似搜索
噪音点/异常值结合局部加权(如 LOF)、数据清洗与异常检测
特征不同类型混合对类别型特征采用合适距离度量(如汉明距离 + 欧氏距离组合)


八、应用场景与适用领域

KNN 虽然简单,但在以下领域仍有广泛应用:

  • 推荐系统(基于用户/物品最近邻推荐)

  • 图像检索(基于特征向量的最近邻搜索)

  • 异常检测(判断样本是否偏离常见邻居)

  • 文本分类(TF‑IDF 向量 + 余弦相似度)


九、总结与拓展

  • 优点:无训练过程、易于理解、适用性广;

  • 挑战:对计算资源依赖高、受高维影响严重;

  • 优化路径:标准化、降维、加速邻居搜索、参数调优、类别平衡处理。

KNN凭借其“无需训练,拿来即用”的特点,是机器学习中最容易理解和实现的算法之一。虽然它在高维、高频场景中存在计算瓶颈,但通过特征工程、参数调优和搜索优化,KNN依然能够在推荐系统、图像检索、异常检测、文本分类等任务中大放异彩

💡 建议初学者掌握KNN作为理解其他复杂算法(如SVM、决策树、神经网络)的基石。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/90888.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/90888.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/90888.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Qt 多线程数据库操作优化

在多线程应用中&#xff0c;数据库操作往往是性能瓶颈与稳定性风险的高发区。当多个线程同时读写数据库时&#xff0c;若处理不当&#xff0c;轻则出现查询卡顿、事务冲突&#xff0c;重则导致数据错乱、连接泄漏甚至程序崩溃。Qt作为跨平台框架&#xff0c;提供了QSql系列类支…

Qt 状态机框架:复杂交互逻辑的处理

Qt状态机框架&#xff08;Qt State Machine Framework&#xff09;是一个强大的工具&#xff0c;用于简化复杂的交互逻辑和状态管理。它基于UML状态图概念&#xff0c;提供了声明式的方式来定义对象行为&#xff0c;特别适合处理具有多种状态和转换的场景&#xff08;如GUI交互…

【docker】DM8达梦数据库的docker-compose以及一些启动踩坑

摘要&#xff1a;本文介绍了通过docker-compose配置启动达梦数据库(DM8)的方法。配置包括容器镜像、端口映射、数据卷挂载以及关键环境变量设置&#xff08;如字符集、大小写敏感等&#xff09;。也说明了启动过程可能遇到的一些问题。通过docker-compose启动达梦数据库可以按照…

服务器中的防火墙设置需要打开吗

服务器中的防火墙属于是一种保护计算机网络不会受到未经授权的网络设备所访问的技术手段&#xff0c;防火墙还有着将内部网络和外部网络进行隔离的功能&#xff0c;在网络之间创建安全屏障&#xff0c;以此来保护网络中数据的安全。防火墙是一种网络安全系统&#xff0c;可以帮…

Java项目:基于SSM框架实现的社区团购管理系统【ssm+B/S架构+源码+数据库+毕业论文+答辩PPT+远程部署】

摘 要 使用旧方法对社区团购信息进行系统化管理已经不再让人们信赖了&#xff0c;把现在的网络信息技术运用在社区团购信息的管理上面可以解决许多信息管理上面的难题&#xff0c;比如处理数据时间很长&#xff0c;数据存在错误不能及时纠正等问题。 这次开发的社区团购系统有…

介绍一下static关键字

在Java中&#xff0c;被static修饰的成员称为静态成员&#xff0c;static关键字可以用来修饰方法或者成员变量&#xff0c;且被static修饰的方法或者成员变量属于类方法或者类属性&#xff0c;也就是说被static修饰的方法或者成员变量不是单独存储在某一个对象的空间&#xff0…

【Java学习|黑马笔记|Day23】网络编程、反射、动态代理

【DAY23】 文章目录【DAY23】一.网络编程1&#xff09;三要素1.1&#xff09;IPInetAddress类的使用1.2&#xff09;端口号1.3&#xff09;协议2.1&#xff09;UDP协议发送数据2.2&#xff09;UDP协议接收数据2.3&#xff09;UDP的三种通信方式3.1&#xff09;TCP协议的发送和接…

【Zephyr】Window下的Zephyr编译和使用

工具下载 参考文档&#xff08;Getting Started Guide — Zephyr Project Documentation&#xff09;中介绍&#xff0c;可以直接通过winget下载&#xff1a; winget download Kitware.CMake Ninja-build.Ninja oss-winget.gperf python Git.Git oss-winget.dtc wget 7zip.7z…

图论(BFS)构造邻接表(运用队列实现搜索)

码蹄集OJ-夏日漫步 #include<bits/stdc.h> using namespace std; int n; int a[200010],dis[200010],qaq[1000010]; vector<int>son[200010]; int que[200010]; int main( ) {memset(qaq,-1,sizeof(qaq));memset(dis,-1,sizeof(dis));cin>>n;for(int i1;i…

vue怎么实现导入excel表功能

<el-uploadref"upload":action"aaa":on-change"importProject"name"excelFile"multiple:auto-upload"false":show-file-list"false"><el-button type"warning">导入</el-button><…

Linux DNS解析3 -- DNS解析代理配置使用

当网关设备配置了 /etc/hosts 文件时&#xff0c;确实可以为终端设备提供自定义DNS解析功能&#xff0c;但具体效果取决于网关的DNS代理服务配置。下面详细解释其工作原理和限制&#xff1a; 一、/etc/hosts 文件的作用 /etc/hosts 是本地静态域名解析文件&#xff0c;格式为&a…

历史版本的vscode下载地址

我有点厌恶vscode越来越臃肿的体积&#xff0c;也不需要层出不穷的新功能&#xff0c;于是网上找寻历史版本。 首先是这个页面&#xff1a;https://code.visualstudio.com/updates &#xff0c;但最多只显示两年&#xff0c;更早的就要手工修改地址栏&#xff0c;我试了最早的…

如何规范化项目执行

要实现项目执行的规范化&#xff0c;应做到以下几点&#xff1a;制定详细的项目执行计划、明确项目团队角色职责、建立高效沟通与协调机制、实施全面的质量与风险管理、采用合适的项目管理工具。其中&#xff0c;尤其重要的是明确项目团队角色职责&#xff0c;通过构建清晰的责…

【Rust异步】async和await异步编程实战:高并发任务处理全解析

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

在Linux上使用DuckCP实现从csv文件汇总数据到SQLite数据库的表

从pypi网站Duckcp页面下载duckcp-0.1.1-py3-none-any.whl 一开始用的Python 3.11.2环境。 继续沿用上文打补丁的方法&#xff0c;得到一个支持python3.11.1的安装包。 因为缺少zip压缩工具&#xff0c;使用python程序来完成对修改后文件的重新压缩。 import os import zipfile…

基于深度学习的图像分类:使用EfficientNet实现高效分类

前言 图像分类是计算机视觉领域中的一个基础任务&#xff0c;其目标是将输入的图像分配到预定义的类别中。近年来&#xff0c;深度学习技术&#xff0c;尤其是卷积神经网络&#xff08;CNN&#xff09;&#xff0c;在图像分类任务中取得了显著的进展。EfficientNet是一种新型的…

Java基础-综合案例

1、设计一个可以执行基本数学运算&#xff08;加减乘除&#xff09;的计算器程序功能描述&#xff1a;用户输入两个数字、一个运算符&#xff08;、-、*、/&#xff09;。根据所选运算符执行相应的数学运算&#xff0c;显示运算结果。import java.util.Scanner;public class Te…

四、计算机组成原理——第3章:存储系统

目录 3.1存储器概述 3.1.1存储器的分类 1.按在计算机中的作用(层次)分类 2.按存储介质分类 3.按存取方式分类 4.按信息的可保存性分类 3.1.2存储器的性能指标 3.2主存储器 3.2.1SRAM芯片和DRAM芯片 1.SRAM的工作原理 2.DRAM的工作原理 3.SRAM和DRAM的比较 4.存储器芯片的内部结…

3D Semantic Occupancy Prediction

3D 语义占用预测&#xff08;3D Semantic Occupancy Prediction&#xff09;旨在将真实世界环境划分为规则的三维体素&#xff08;voxel&#xff09;网格&#xff0c;并对每个体素同时预测&#xff1a; 占用状态&#xff08;Occupancy&#xff09;&#xff1a;该体素是否被物体…

在Word和WPS文字中添加的拼音放到文字右边

在Word和WPS文字中&#xff0c;可以方便地为中文汉字添加拼音。默认的是拼音在汉字的上方&#xff0c;而且不方便直接编辑。可以简单操作后把拼音放在汉字的右边&#xff0c;并且可以方便地编辑。一、Word&#xff1a;先为汉字添加拼音&#xff0c;然后选择性粘贴为纯文本即可1…