胡慧华
菜单
首页人工智能机器学习深度学习智能体项目实践关于我
← 返回机器学习课程

MACHINE LEARNING · 02

KNN算法:从一朵花开始,理解“近邻”分类思想

从一朵不知道品种的鸢尾花出发,理解机器学习如何通过寻找相似样本完成分类。

零基础预计25分钟分类算法

K-NEAREST NEIGHBORS

学完本节课,你将能够:

  1. 区分“特征”和“标签”
  2. 理解寻找邻居并投票的过程
  3. 用距离表示样本的相似程度
  4. 理解K值为什么会影响结果
01

问题引入:这朵新花是什么品种?

植物学家提供历史数据,由你完成一次新品种判断。

BOTANICAL RESEARCH BRIEF

一份来自植物学家的研究任务

从已知样本出发,判断一朵新花。

01 · 研究发现

外观相近,却有三个品种

研究对象可以分为山鸢尾、变色鸢尾和维吉尼亚鸢尾。品种差异与花萼、花瓣的长宽密切相关。

山鸢尾变色鸢尾维吉尼亚鸢尾
02 · 建立样本

测量数据 + 正确品种

植物学家测量每朵花的四项数据,再由专家确认真实品种,建立了一份可供分析的历史样本。

花萼长度花萼宽度花瓣长度花瓣宽度
03 · 轮到你了

判断一朵未知的新花

新花的四项测量已经完成,但品种仍是未知。请结合历史样本,判断它最可能属于哪一个品种。

已知特征 → 预测标签
研究附件 · 鸢尾花仿真历史样本CSV · 150条样本 · 每个品种50条 · 用于课程算法实验查看并下载 ↓

NEW SAMPLE首先看看这朵等待判断的新花,植物学家已经为我们提供了哪些测量数据。

特征测量结果
花萼长度6.0 cm
花萼宽度2.9 cm
花瓣长度5.0 cm
花瓣宽度1.7 cm
品种
你的任务

只有测量数据,怎样判断这朵新花的品种?

查看直觉思路
  1. 在历史数据中找一些和它长得相似的花;
  2. 查看这些相似花朵已经确认的品种;
  3. 哪个品种出现得最多,就把新花暂时判断为哪个品种。

这个从历史样本中寻找“邻居”的直觉方法,就是KNN算法的基本思想。

02

问题分析:特征、标签和分类

什么是特征?

花萼长度、花萼宽度、花瓣长度和花瓣宽度,都是描述一朵花的可测量信息。在机器学习中,这些用来描述对象的信息叫作特征

特征,就是我们用来认识和区分一个对象的信息。
判断对象可以采集的特征
鸢尾花花瓣长度、花瓣宽度
一套房子面积、楼层、位置、房龄
一位用户年龄、消费次数、浏览偏好
一封邮件发件人、关键词、链接数量

并不是特征越多越好。真正有帮助的,是能够体现不同类别差异的特征。

什么是标签?

历史数据中的每朵花都已经由专家鉴定了品种。“山鸢尾”“变色鸢尾”“维吉尼亚鸢尾”就是这些数据的标签

标签,就是历史数据中已经确认的正确答案。
花瓣长度花瓣宽度品种标签
1.40.2山鸢尾
4.51.5变色鸢尾
5.72.1维吉尼亚鸢尾

新花只有特征、没有标签。我们的任务,是根据历史数据预测它的标签,这类问题叫作分类问题

历史花朵花萼与花瓣特征已知品种标签判断新花
03

解题思路:物以类聚,人以群分

同一个品种的花,在花瓣长度和宽度上往往比较接近:山鸢尾普遍短而窄,变色鸢尾大小居中,维吉尼亚鸢尾通常更长、更宽。

  1. 把新花放进历史数据中
  2. 找到与它最相似的几朵花
  3. 查看这些花的品种
  4. 让邻居进行投票
  5. 用票数最多的品种作为预测
K参考几个邻居Nearest距离最近、特征最相似Neighbors历史数据中的邻居样本
KNN就是找到离新样本最近的K个历史样本,让它们投票决定新样本的类别。
04

如何找到最相似的花?

把“看起来很像”的直觉,变成计算机能够比较的数字。

直观地说,我们会把新花与历史花朵逐项比较:花瓣长度是否接近、花瓣宽度是否接近,花萼长度和宽度又相差多少。四项数据越接近,两朵花就越相似。

但计算机不能只凭“看起来像”作判断。我们需要把相似程度变成一个可以计算、排序的数字,这个数字就是距离:距离越小,样本越相似。

01 · 一维

比较一个数字的差值

只看花瓣长度时,5.0 cm 与 5.1 cm 相差 0.1 cm。差值越小,就越相似。

| 5.0 − 5.1 | = 0.1
02 · 二维

合并两个方向的差异

同时比较长度和宽度时,把两个差值分别平方、相加,再开平方,得到平面上的直线距离。

√(长度差² + 宽度差²)
03 · 多维

扩展为空间向量距离

使用四项特征时方法不变:将每一维的差异合并,得到两个特征向量之间的距离。

√(差₁² + … + 差₄²)
从一维到多维,核心始终相同:把各项特征的差异合并成一个距离,距离越小,就代表越相似。

先把每朵花放到二维坐标图上

为了便于理解,暂时只选择两个特征:横轴是花瓣长度,纵轴是花瓣宽度。每朵花都可以表示为一个点,例如历史花是 (4.5, 1.5),新花是 (5.0, 1.7)

图上的两个点越近,说明两朵花在这两个特征上越相似。
花瓣长度(cm)花瓣宽度(cm)4.555.561.21.51.82.12.4
山鸢尾变色鸢尾维吉尼亚鸢尾待分类新花

什么是向量?

看到“向量”不必紧张。这里可以把它理解为“按照固定顺序排列的一组数字”。

6.0花萼长度2.9花萼宽度5.0花瓣长度1.7花瓣宽度
特征向量,就是用一组有固定顺序的数字来描述一个对象。

如何计算距离?

A点为 (1, 1),B点为 (4, 5)。横向相差3,纵向相差4,根据勾股定理,两点直线距离为5。

新花 (5.0, 1.7) 与历史花 (5.1, 1.6)√[(5.0 − 5.1)² + (1.7 − 1.6)²]√(0.01 + 0.01) ≈ 0.14

距离只有0.14,说明两朵花非常相似。使用四个特征时方法不变:分别计算四项差值、平方、相加,最后开平方。

距离 = √(花萼长度差² + 花萼宽度差² + 花瓣长度差² + 花瓣宽度差²)
05

计算结果:让最近的5朵花投票

计算机会求出新花与每一朵历史花的距离,然后从近到远排序。

排名花瓣长度花瓣宽度距离历史标签
15.11.60.14变色鸢尾
24.81.80.22变色鸢尾
34.91.50.22变色鸢尾
44.51.50.54变色鸢尾
55.51.90.54维吉尼亚鸢尾
65.72.10.81维吉尼亚鸢尾
当前 K 值5
邻居投票

变色鸢尾 4票维吉尼亚鸢尾 1票山鸢尾 0票

最终预测变色鸢尾

答案不是凭空产生的:先计算距离,再选出最近的5朵花,最后统计它们的已知标签。

06

K值为什么会影响结果?

K代表参加投票的邻居数量。我们可以寻找最近的3朵、5朵或7朵花。参加投票的邻居发生变化,最终结果也可能改变。

K值邻居投票结果预测结果
K=33朵变色,0朵维吉尼亚变色鸢尾
K=54朵变色,1朵维吉尼亚变色鸢尾
K=74朵变色,3朵维吉尼亚变色鸢尾
  • K太小,容易受到个别异常数据影响;
  • K太大,可能把较远、不相似的数据也算进来;
  • 实际工程会尝试多个K值并比较效果;
  • 二分类经常选择奇数,减少平票可能。
K不是凭感觉永久确定的,而是需要通过数据实验不断验证。
INTERACTIVE LAB

改变 K,观察投票结果

花瓣长度(cm)花瓣宽度(cm)4.555.561.21.51.82.12.4
山鸢尾变色鸢尾维吉尼亚鸢尾待分类新花

当前选择最近的 5 朵花

变色鸢尾4
维吉尼亚鸢尾1
山鸢尾0 票
预测结果变色鸢尾

K值改变 → 邻居改变 → 票数改变 → 结果可能改变

07

KNN的完整工作过程

  1. 01输入新花的特征
  2. 02计算与每朵历史花的距离
  3. 03按照距离从近到远排序
  4. 04选择最近的K朵花
  5. 05统计邻居的品种
  6. 06用票数最多的品种作为预测
KNN认为,彼此相似的数据,通常更可能属于同一类别。

把完整过程写成 Python 代码

理解算法步骤后,我们可以直接使用 sklearn 中的KNN模型完成相同过程。下面的示例使用完整鸢尾花数据训练模型,再预测课程中的新花 [6.0, 2.9, 5.0, 1.7]

PYTHON · SCIKIT-LEARN

用代码完成一次KNN分类

01from sklearn.datasets import load_iris
02from sklearn.model_selection import train_test_split
03from sklearn.preprocessing import StandardScaler
04from sklearn.neighbors import KNeighborsClassifier
05iris = load_iris()
06X, y = iris.data, iris.target
07X_train, X_test, y_train, y_test = train_test_split(
08 X, y, test_size=0.2, random_state=42, stratify=y
09)
10scaler = StandardScaler()
11X_train = scaler.fit_transform(X_train)
12X_test = scaler.transform(X_test)
13model = KNeighborsClassifier(n_neighbors=5)
14model.fit(X_train, y_train)
15accuracy = model.score(X_test, y_test)
16new_flower = [[6.0, 2.9, 5.0, 1.7]]
17new_flower = scaler.transform(new_flower)
18prediction = model.predict(new_flower)
19print(iris.target_names[prediction[0]])

逐行理解代码

  1. 01

    从 sklearn 内置数据集中导入鸢尾花数据加载器。

  2. 02

    导入数据拆分工具,用来划分训练集和测试集。

  3. 03

    导入标准化工具,避免不同特征的数值范围干扰距离。

  4. 04

    导入 sklearn 提供的 KNN 分类模型。

  5. 05

    加载完整鸢尾花数据,包括四项特征、品种标签和字段说明。

  6. 06

    X 保存花萼与花瓣的四项特征,y 保存每朵花的品种标签。

  7. 07

    开始拆分数据:模型用训练集寻找邻居,用测试集检查预测效果。

  8. 08

    取20%作为测试集;固定随机种子,并保持三个品种的比例。

  9. 09

    完成训练集和测试集的拆分。

  10. 10

    创建标准化器,让四项特征处于可比较的数值尺度。

  11. 11

    从训练数据学习标准化规则,并转换训练集。

  12. 12

    使用同一套规则转换测试集,不能重新学习一次。

  13. 13

    创建KNN模型,并规定每次参考最近的5个邻居。

  14. 14

    把训练特征和正确标签交给模型;KNN会保留这些历史样本。

  15. 15

    让模型预测测试集,并计算分类准确率。

  16. 16

    输入课程中的新花,四个数字的顺序必须与训练数据一致。

  17. 17

    用训练阶段得到的标准化规则处理新花。

  18. 18

    寻找新花最近的5个训练样本,通过投票得到品种编号。

  19. 19

    把品种编号转换为名称并输出预测结果。

08

KNN到底“学习”了什么?

KNN与一些会提前总结规律的算法不同。它保留历史数据,遇到新问题时,再寻找最近的邻居。

新同学选择社团

一位新同学喜欢篮球、跑步和户外活动。找到兴趣最相似的5名老同学,如果其中4人加入体育社,就可以合理猜测他也可能选择体育社。

新同学的兴趣特征
老同学参加的社团标签
兴趣相似程度距离
最相似的几位老同学K个邻居
邻居选择最多的社团预测结果
KNN不是凭空猜测,而是根据历史上与新对象最相似的数据作出判断。
09

KNN可以用在哪里?

01

水果分类

根据重量、大小、颜色和甜度判断水果种类。

02

手写数字识别

将图片转换成像素数据,寻找最相似的历史数字。

03

用户分级

根据浏览、购买和消费金额判断用户等级。

04

内容推荐

寻找兴趣相似的用户或内容,辅助完成推荐。

05

疾病辅助判断

根据年龄、体温、心率和检查指标寻找相似案例。算法结果只能作为辅助,不能代替医生诊断。

10

KNN的优点和局限

优势

简单、直观、低门槛

  • 思想直观,容易理解
  • 不需要复杂训练过程
  • 可用于分类和数值预测
  • 适合小规模、结构清晰的数据
局限

距离并不总是可靠

  • 数据多时,每次预测计算量大
  • 无关特征可能干扰判断
  • 不同单位和范围会影响距离
  • K值需要通过实验选择
  • 类别不均衡时多数类易占优势
为什么单位会影响结果?

年龄通常是几十,年收入可能是几十万。直接计算距离时,收入会产生过大的影响。实际工程通常会先对不同特征做标准化处理;具体方法将在后续课程中展开。

LESSON SUMMARY

你已经理解了KNN

  1. 特征是描述对象的信息,标签是历史数据中的正确答案。
  2. KNN通过寻找最近的历史样本预测新样本。
  3. “最近”通常通过特征向量之间的距离判断。
  4. 最近的K个邻居通过投票决定分类结果。
  5. K值、特征选择和数据处理都会影响预测效果。
KNN是一种根据样本之间的距离,找到最近的K个历史样本,再通过邻居投票完成分类的机器学习算法。
12

课后思考

假设我们希望判断一位新用户是否会购买某项产品:

  1. 你准备采集哪些特征?
  2. 历史数据的标签是什么?
  3. 什么样的用户可以算作“相似用户”?
  4. K取3、5或7时,结果是否可能不同?
查看思路

可以从用户的浏览、收藏、购买频率和消费金额出发;标签可以是“购买”或“未购买”。相似用户需要在选定特征上距离较近,而不同K值确实可能带来不同投票结果。

完成课程返回机器学习课程列表 →