跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像AI 生图工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
PythonAI算法

K-近邻算法(KNN)原理、流程与 Python 实战案例

K-近邻算法(KNN)是一种非参数化、懒惰学习的监督学习算法,适用于分类和回归任务。核心思想是通过计算样本间距离找到最近的 K 个邻居进行预测。 KNN 的距离度量方法(欧氏、曼哈顿等)、数学表达、算法流程及 Python 代码实现。内容涵盖 K 值选择策略(交叉验证、肘部法则)、距离度量影响、加权 KNN 以及回归任务的具体应用。最后总结了 KNN 的优缺点及工程实践建议,如特征归一化和 KD 树优化。

全栈工匠发布于 2026/4/5更新于 2026/7/2348 浏览
K-近邻算法(KNN)原理、流程与 Python 实战案例

K-近邻算法(KNN)详细全流程详解与案例

一、KNN 算法简介

K-近邻算法(K-Nearest Neighbors, KNN)是一种非参数化、懒惰学习的监督学习算法,可用于分类和回归任务。KNN 的核心思想是:对一个新样本,找到训练集中距离最近的 K 个邻居,根据这些邻居的类别或数值来预测新样本的类别或数值。

文章配图

  • 分类任务(Classification):采用多数投票原则,K 个邻居中出现最多的类别为预测类别。
  • 回归任务(Regression):取 K 个邻居的均值作为预测值。

二、KNN 算法原理与数学表达

1. 距离度量

KNN 的关键在于如何度量样本间的距离。常用距离有:

  • 其他:汉明距离(Hamming)、余弦距离(Cosine)等

闵可夫斯基距离(Minkowski Distance):

d(x, y) = \left( \sum_{i=1}^n |x_i - y_i|^p \right)^{1/p}

曼哈顿距离(Manhattan Distance):

d(x, y) = \sum_{i=1}^n |x_i - y_i|

欧氏距离(Euclidean Distance):

d(x, y) = \sqrt{\sum_{i=1}^n (x_i - y_i)^2}

2. KNN 分类数学表达

对一个新样本 $x$,KNN 的预测类别 $\hat{y}$ 为:

\hat{y} = \operatorname{mode}{y_{(1)}, y_{(2)}, ..., y_{(K)}}

其中 $y_{(i)}$ 为距离 $x$ 最近的第 $i$ 个训练样本的类别。

3. KNN 回归数学表达

对一个新样本 $x$,KNN 的预测值 $\hat{y}$ 为:

\hat{y} = \frac{1}{K} \sum_{i=1}^K y_{(i)}

其中 $y_{(i)}$ 为最近 K 个邻居的真实数值。

三、KNN 算法详细流程

Step 1:准备数据

  • 收集并整理训练数据集,包含特征和标签。
  • 对特征进行归一化或标准化(KNN 对尺度敏感)。

Step 2:选择距离度量方式

  • 通常选用欧氏距离,也可根据实际需求选择其他距离。

Step 3:确定 K 值

  • K 是超参数,需通过交叉验证或'肘部法则'选择。
  • K 太小易受噪声影响,K 太大则可能欠拟合。

Step 4:预测新样本

  • 对于每个新样本,计算其与所有训练样本的距离。
  • 选出距离最近的 K 个邻居。
  • 分类任务:统计 K 个邻居中出现最多的类别作为预测结果。
  • 回归任务:取 K 个邻居的均值作为预测结果。

Step 5:评估与调优

  • 用测试集评估模型准确率或均方误差。
  • 调整 K 值、距离度量方式等参数优化模型。

四、KNN 案例流程与完整代码演示

案例:二维数据点分类

我们用一组二维点(2D Points)作为训练集,类别用颜色区分。新样本点用 KNN 算法预测其类别,并可视化决策边界。

1. 数据准备与可视化

import matplotlib.pyplot as plt 
import numpy as np 
# 训练数据 
X_train = np.array([[1,2],[2,3],[3,1],[6,5],[7,7],[8,6]]) 
y_train = np.array([0,0,0,1,1,1]) # 0: 蓝色,1: 红色 
plt.scatter(X_train[y_train==0,0], X_train[y_train==0,1], color='blue', label='Class 0') 
plt.scatter(X_train[y_train==1,0], X_train[y_train==1,1], color='red', label='Class 1') 
plt.xlabel('X1') 
plt.ylabel('X2') 
plt.title('KNN Training Data') 
plt.legend() 
plt.show()

文章配图

2. 用 KNN 预测新样本

import matplotlib.pyplot as plt 
import numpy as np 
from sklearn.neighbors import KNeighborsClassifier 
# 训练数据 
X_train = np.array([[1,2],[2,3],[3,1],[6,5],[7,7],[8,6]]) 
y_train = np.array([0,0,0,1,1,1]) # 0: 蓝色,1: 红色 
knn = KNeighborsClassifier(n_neighbors=3) 
knn.fit(X_train, y_train) 
# 新样本 
X_test = np.array([[3,4],[7,5]]) 
y_pred = knn.predict(X_test) 
print("Predicted classes:", y_pred)

文章配图

3. 可视化决策边界

import matplotlib.pyplot as plt 
import numpy as np 
from sklearn.neighbors import KNeighborsClassifier 
# 训练数据 
X_train = np.array([[1,2],[2,3],[3,1],[6,5],[7,7],[8,6]]) 
y_train = np.array([0,0,0,1,1,1]) # 0: 蓝色,1: 红色 
knn = KNeighborsClassifier(n_neighbors=3) 
knn.fit(X_train, y_train) 
# 新样本 
X_test = np.array([[3,4],[7,5]]) 
y_pred = knn.predict(X_test) 
print("Predicted classes:", y_pred) 
# 绘制决策边界 
h = .02 # 网格步长 
x_min, x_max = X_train[:, 0].min() - 1, X_train[:, 0].max() + 1 
y_min, y_max = X_train[:, 1].min() - 1, X_train[:, 1].max() + 1 
xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h)) 
Z = knn.predict(np.c_[xx.ravel(), yy.ravel()]) 
Z = Z.reshape(xx.shape) 
plt.contourf(xx, yy, Z, alpha=0.3, cmap=plt.cm.RdBu) 
plt.scatter(X_train[y_train==0,0], X_train[y_train==0,1], color='blue', label='Class 0') 
plt.scatter(X_train[y_train==1,0], X_train[y_train==1,1], color='red', label='Class 1') 
plt.scatter(X_test[:,0], X_test[:,1], color='green', marker='*', s=200, label='Test Points') 
plt.xlabel('X1') 
plt.ylabel('X2') 
plt.title('KNN Decision Boundary (K=3)') 
plt.legend() 
plt.show()

文章配图

五、KNN 进阶内容与工程实践

1. K 值选择与模型表现

KNN 的K 值直接影响模型的泛化能力:

  • K 太小(如 K=1):模型对噪声敏感,容易过拟合(Overfitting),决策边界复杂。
  • K 太大:模型过于平滑,容易欠拟合(Underfitting),决策边界简单。

文章配图

常用 K 值选择方法:

  • 交叉验证(Cross Validation):在训练集上用不同 K 值测试,选择准确率最高的 K。
  • '肘部法则':画出 K 与错误率的关系曲线,选择拐点处的 K。

KNN 在'月牙形'数据集上的 K 值交叉验证的示例代码(K 值交叉验证):

import numpy as np 
import matplotlib.pyplot as plt 
from sklearn.datasets import make_moons 
from sklearn.neighbors import KNeighborsClassifier 
from sklearn.model_selection import cross_val_score 
# 增加噪声、减少样本数 
X, y = make_moons(n_samples=60, noise=0.5, random_state=42) 
plt.scatter(X[y==0,0], X[y==0,1], color='blue', label='Class 0', alpha=0.6) 
plt.scatter(X[y==1,0], X[y==1,1], color='red', label='Class 1', alpha=0.6) 
plt.title('Noisy Moons Dataset (n=60, noise=0.5)') 
plt.legend() 
plt.show() 
cv = 5 
max_k = 20 
k_range = range(1, max_k+1) 
scores = [] 
for k in k_range: 
    knn = KNeighborsClassifier(n_neighbors=k) 
    score = cross_val_score(knn, X, y, cv=cv, scoring='accuracy').mean() 
    scores.append(score) 
plt.plot(k_range, scores, marker='o') 
plt.xlabel('K') 
plt.ylabel('Cross-validated Accuracy') 
plt.title('K Selection for KNN on Noisy Moons (n=60, noise=0.5)') 
plt.grid(True) 
plt.show() 
best_k = k_range[np.argmax(scores)] 
print(f"Best K: {best_k}, Best CV Accuracy: {max(scores):.3f}") 
print("All scores:", scores)

文章配图

文章配图

代码解释

  • make_moons生成了一个有噪声、非线性可分的二分类数据集,非常适合演示 KNN 的 K 值选择。
  • cross_val_score对每个 K 进行 5 折交叉验证,记录平均准确率。
  • scores 曲线显示不同 K 值下模型的泛化能力。

结果解读

  • K=1 时,模型容易过拟合噪声点,准确率较低。
  • K 变大后,模型对噪声不敏感,准确率提升,达到一个峰值(通常在 K=5~10)。
  • K 再变大,模型变得过于平滑,欠拟合,准确率下降。
  • 最佳 K 值就是准确率最高处,对应的 K 值就是你应该选择的 K。

你会看到一条**'先上升后下降'**的曲线,这就是 K 值选择的意义所在。

注:有时候,K 值到很大的情况 Acc 依然很高,那是因为噪声(Noise)太少了。而现实情况中,噪声是一定会出现的。因此 K 值不是越高越好,而是能适配最大部分情况为佳!

总结

  • KNN 的 K 值选择在数据量小、噪声大、类别分布不均时作用最明显。
  • 真实业务中,务必用交叉验证和多 K 对比来选择最优 K,避免模型过拟合或欠拟合。

2. 距离度量的选择与影响

不同的距离度量适用于不同的数据特征:

  • 欧氏距离:适合连续型、尺度一致的特征。
  • 曼哈顿距离:对异常值更鲁棒,适合稀疏特征。
  • 闵可夫斯基距离:p 参数可调节距离的'敏感度'。
  • 余弦距离:适合文本、方向型特征。
  • 汉明距离:适合离散/二值特征。

在 sklearn 中可通过 metric 参数设置:

knn = KNeighborsClassifier(n_neighbors=3, metric='manhattan')

示例代码:

from sklearn.neighbors import KNeighborsClassifier 
import numpy as np 
# 训练数据 
X_train = np.array([[1,2],[2,3],[3,1],[6,5],[7,7],[8,6]]) 
y_train = np.array([0,0,0,1,1,1]) # 0: 蓝色,1: 红色 
# 曼哈顿距离(L1 范数) 
knn = KNeighborsClassifier(n_neighbors=3, metric='manhattan') 
knn.fit(X_train, y_train) 
# 测试数据 
X_test = np.array([[3,4],[7,5]]) 
y_pred = knn.predict(X_test) 
print("Manhattan KNN Predicted classes:", y_pred)

3. 加权 KNN

加权 KNN会根据距离远近给邻居不同权重,距离越近权重越高,常用权重函数为倒数权重:

w_i = \frac{1}{d(x, x_i) + \epsilon}

在 sklearn 中可直接设置:

knn = KNeighborsClassifier(n_neighbors=3, weights='distance')

这样,预测时距离近的邻居影响更大,模型对边界点更敏感。

示例代码:

from sklearn.neighbors import KNeighborsClassifier 
import numpy as np 
import matplotlib.pyplot as plt 
# 训练数据 
X_train = np.array([[1,2],[2,3],[3,1],[6,5],[7,7],[8,6]]) 
y_train = np.array([0,0,0,1,1,1]) # 0: 蓝色,1: 红色 
# 加权 KNN(距离倒数加权) 
knn = KNeighborsClassifier(n_neighbors=3, weights='distance') 
knn.fit(X_train, y_train) 
# 测试数据 
X_test = np.array([[3,4],[7,5]]) 
y_pred = knn.predict(X_test) 
print("Weighted KNN Predicted classes:", y_pred) 
# 决策边界可视化 
h = .02 
x_min, x_max = X_train[:, 0].min() - 1, X_train[:, 0].max() + 1 
y_min, y_max = X_train[:, 1].min() - 1, X_train[:, 1].max() + 1 
xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h)) 
Z = knn.predict(np.c_[xx.ravel(), yy.ravel()]) 
Z = Z.reshape(xx.shape) 
plt.contourf(xx, yy, Z, alpha=0.3, cmap=plt.cm.RdBu) 
plt.scatter(X_train[y_train==0,0], X_train[y_train==0,1], color='blue', label='Class 0') 
plt.scatter(X_train[y_train==1,0], X_train[y_train==1,1], color='red', label='Class 1') 
plt.scatter(X_test[:,0], X_test[:,1], color='green', marker='*', s=200, label='Test Points') 
plt.xlabel('X1') 
plt.ylabel('X2') 
plt.title('Weighted KNN Decision Boundary (K=3)') 
plt.legend() 
plt.show()

4. KNN 回归

KNN 不仅能做分类,也能做回归。KNN 回归的预测值为 K 个邻居的均值或加权均值。

下面是一个更复杂的 KNN 回归案例,包括带噪声的非线性数据、不同权重的 KNN 回归曲线、可视化和详细流程解释,非常适合理解 KNN 回归的行为和调参意义。

示例代码:KNN 回归(可视化 + 流程讲解)

import numpy as np 
import matplotlib.pyplot as plt 
from sklearn.neighbors import KNeighborsRegressor 
# 1. 生成带噪声的非线性训练数据 
np.random.seed(42) 
X_train = np.sort(5 * np.random.rand(40, 1), axis=0) 
y_train = np.sin(X_train).ravel() + 0.3 * np.random.randn(40) # 正弦 + 高斯噪声 
# 2. 创建测试数据用于预测(密集采样,便于画曲线) 
X_test = np.linspace(0, 5, 500)[:, np.newaxis] 
# 3. 创建两个 KNN 回归模型,分别用 uniform 和 distance 权重 
knn_uniform = KNeighborsRegressor(n_neighbors=5, weights='uniform') 
knn_distance = KNeighborsRegressor(n_neighbors=5, weights='distance') 
# 4. 训练模型 
knn_uniform.fit(X_train, y_train) 
knn_distance.fit(X_train, y_train) 
# 5. 预测 
y_pred_uniform = knn_uniform.predict(X_test) 
y_pred_distance = knn_distance.predict(X_test) 
# 6. 可视化 
plt.figure(figsize=(10, 6)) 
plt.scatter(X_train, y_train, color='darkorange', label='Training data') 
plt.plot(X_test, y_pred_uniform, color='navy', label='Uniform weights') 
plt.plot(X_test, y_pred_distance, color='c', label='Distance weights') 
plt.title('KNN Regression with Uniform and Distance Weights') 
plt.xlabel('X') 
plt.ylabel('y') 
plt.legend() 
plt.show()

文章配图

代码流程与结果解释

1. 数据生成
  • 用正弦函数加高斯噪声生成 40 个训练点,模拟现实中非线性、带噪声的回归问题。
2. 测试点
  • 用 np.linspace 生成 0~5 区间的 500 个点,便于画出平滑的 KNN 回归曲线。
3. KNN 回归模型
  • weights='uniform':每个邻居权重相同,预测值为 K 个邻居的简单平均。(普通的 KNN 算法)
  • weights='distance':距离越近的邻居权重越高,预测值为加权平均,更贴近局部数据。(权重和距离成反比)
4. 训练与预测
  • 分别用两种权重训练模型,并对所有测试点做预测。
5. 可视化解析
  • 橙色散点为训练样本。
  • 蓝色曲线(uniform)和青色曲线(distance)分别为两种 KNN 回归预测结果。
  • 可以看到 distance 权重的预测曲线在训练点附近更贴近真实数据,尤其在边界和噪声点多的地方。
6. 小结
KNN 回归示例:带噪声的正弦数据上,使用 uniform 和 distance 权重的预测曲线对比
  • KNN 回归可以拟合非线性关系,但 K 值和权重对结果影响很大。
  • 距离加权的 KNN 回归在边界或噪声多时表现更好。
  • 你可以调整 n_neighbors、weights、噪声大小等参数,观察模型拟合能力和泛化能力的变化。

5. KNN 的优缺点与工程建议

优点

  • 实现简单,无需训练过程,易于理解和可解释。
  • 适用于多分类、多回归问题。
  • 对异常值不敏感(K 较大时)。

缺点

  • 预测时计算量大,需遍历全部训练集(可用 KD 树等优化)。
  • 对特征尺度敏感,需标准化或归一化。
  • 对高维数据效果差(维度灾难)。
  • K 值和距离度量需调优。

工程建议

  • 特征需归一化/标准化,避免尺度影响距离计算。
  • 可用交叉验证选 K 和距离度量。
  • 大数据集可用 KD 树、球树等加速查找。
  • 适合特征维度较低、样本量中等的场景。

六、KNN 算法总结

K-近邻算法(KNN)是最经典的**'懒惰学习'**方法之一,凭借简单直观、无模型假设、易于实现等优点,广泛应用于分类、回归、推荐、异常检测等领域。KNN 的核心思想是'以邻为师',通过距离度量和多数投票实现预测。实际应用中,建议合理选择 K 值、距离度量和特征预处理方法,并结合数据规模和业务需求优化模型。

目录

  1. K-近邻算法(KNN)详细全流程详解与案例
  2. 一、KNN 算法简介
  3. 二、KNN 算法原理与数学表达
  4. 1. 距离度量
  5. 2. KNN 分类数学表达
  6. 3. KNN 回归数学表达
  7. 三、KNN 算法详细流程
  8. Step 1:准备数据
  9. Step 2:选择距离度量方式
  10. Step 3:确定 K 值
  11. Step 4:预测新样本
  12. Step 5:评估与调优
  13. 四、KNN 案例流程与完整代码演示
  14. 1. 数据准备与可视化
  15. 训练数据
  16. 2. 用 KNN 预测新样本
  17. 训练数据
  18. 新样本
  19. 3. 可视化决策边界
  20. 训练数据
  21. 新样本
  22. 绘制决策边界
  23. 五、KNN 进阶内容与工程实践
  24. 1. K 值选择与模型表现
  25. 增加噪声、减少样本数
  26. 2. 距离度量的选择与影响
  27. 训练数据
  28. 曼哈顿距离(L1 范数)
  29. 测试数据
  30. 3. 加权 KNN
  31. 训练数据
  32. 加权 KNN(距离倒数加权)
  33. 测试数据
  34. 决策边界可视化
  35. 4. KNN 回归
  36. 1. 生成带噪声的非线性训练数据
  37. 2. 创建测试数据用于预测(密集采样,便于画曲线)
  38. 3. 创建两个 KNN 回归模型,分别用 uniform 和 distance 权重
  39. 4. 训练模型
  40. 5. 预测
  41. 6. 可视化
  42. 1. 数据生成
  43. 2. 测试点
  44. 3. KNN 回归模型
  45. 4. 训练与预测
  46. 5. 可视化解析
  47. 6. 小结
  48. KNN 回归示例:带噪声的正弦数据上,使用 uniform 和 distance 权重的预测曲线对比
  49. 5. KNN 的优缺点与工程建议
  50. 六、KNN 算法总结
  • 免费图片AI生成工具免费生成了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
  • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
  • 100+免费在线小游戏爽一把
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • Miloco 本地大模型智能家居部署与使用记录
  • 国产 AI 大模型 Kimi 技术解析与应用前景
  • Git Push 失败常见原因排查:权限、分支保护与冲突解决
  • OpenClaw 在 Mac 上本地化部署及接入飞书教程
  • 抗辐照 MCU 在高空长航时无人机热管理系统中的可靠性研究
  • 3步彻底解决SubtitleEdit Purfview Faster Whisper XXL引擎安装失败
  • Java volatile 关键字深度解析:机制、场景与避坑指南
  • Arduino BLDC 基于串口指令的远程控制工业巡检机器人
  • ollama 模型管理、删除模型 、open-webui 开启大模型交互
  • Windows 程序启动失败:Visual C++ 运行库缺失修复方案
  • Java 动态代理核心原理与实战对比
  • RTX 4090 本地部署腾讯混元与阿里通义万相视频模型
  • Rust 十年路:所有权、零成本抽象与跨领域渗透
  • 低代码平台的两种价值观:短期成果与长期成本
  • MAVROS 安装配置与 ROS C++ 仿真实战指南
  • 数据结构初阶:二叉树的链式存储结构
  • Apache IoTDB 全场景部署:跨「端 - 边 - 云」的时序数据库实践
  • C++ 继承机制详解:从基础到多态
  • Neo4j 图数据库安装与操作指南
  • OpenClaw 接入自定义模型并通过 WebUI 实现智能操作

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • RSA密钥对生成器

    生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online

  • Mermaid 预览与可视化编辑

    基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online

  • 随机西班牙地址生成器

    随机生成西班牙地址(支持马德里、加泰罗尼亚、安达卢西亚、瓦伦西亚筛选),支持数量快捷选择、显示全部与下载。 在线工具,随机西班牙地址生成器在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • curl 转代码

    解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online