机器学习入门 · 有标注的预测

不知道答案?
先问问最近的邻居

新小区里一家店好不好、一套房大概值多少——你往往会先问附近几个人。
机器学习里的 KNN,干的就是同一件事。

向下滑动
第一步 · 生活场景

搬进新小区:两件「问邻居」的小事

1 分类题:这家水果店靠不靠谱?

你刚搬来,想知道楼下水果店好不好。最自然的做法不是做复杂调研,而是问离你最近的几位邻居:3 个人说「好」,2 个人说「一般」,你多半会相信「还不错」。

这里你做的是投票——多数邻居的答案,变成你的答案。后面会把它叫做「分类」。

2 回归题:这套房大概多少钱?

中介报价听着虚,你会去查附近几套面积、楼层、朝向都差不多的成交价,再取个平均:比如 580、600、610 万,你心里大概就有 597 万这个数。

这里你做的是取平均——邻居们的数字,合成你的数字。后面会把它叫做「回归」。

核心洞察

两件事共用同一条直觉:相似的东西,答案往往也接近。机器学习把「相似」变成可计算的距离,把「问几个人」变成一个可调的数字 K——这套方法就叫 K 近邻(K-Nearest Neighbors,KNN)

第二步 · 什么是 KNN

KNN:不「背公式」,只「翻邻居」

1 一句话定义

KNN:要预测一个新样本时,先在已有数据里找出与它最相似(距离最近)的 K 个样本,再根据这 K 个邻居的答案来做决定。

2 三步走,人人都能复述

  1. 算新点到每个已知样本的距离
  2. 按距离排序,取出最近的 K 个;
  3. 综合邻居的答案(下一节细说怎么综合)。
预测(新点) = 综合(它的 K 个最近邻居)
先找邻居,再汇总——骨架就这一句

3 它几乎不「训练」

很多算法会先花很长时间学出一套权重。KNN 更「懒」:训练阶段往往只是把数据存起来;真正算活,发生在你送来一个新样本的那一刻。所以它也常被叫做惰性学习(lazy learning)

小提示:「懒」不是缺点,而是特点——模型简单、好解释,但预测时要翻遍(或高效检索)整份训练集,数据很大时会变慢。
第三步 · 分类与回归

为什么同一套「问邻居」,既能分类又能回归?

1 差别不在找邻居,而在「怎么用邻居」

找谁当邻居,两种任务一样:都按距离挑最近的 K 个。差别只在最后一步——还是用小区里那两件事:

分类 · 问水果店好不好

邻居说「好、好、一般」→ 投票选
答案是类别:好 / 一般 / 差。

回归 · 估附近房价

邻居成交价 580、600、610 → 平均约 597
答案是数字:温度、销量、房价。

2 同一批邻居,两种读法

假设 K=3,三位最近邻居分别是:

邻居距离问水果店(分类)估房价(回归)
张阿姨最近580 万
王叔叔次近600 万
李奶奶第三近一般610 万

分类:好 2 票、一般 1 票 → 判为
回归:(580 + 600 + 610) / 3 = 597 万

核心洞察

KNN 能「身兼两职」,是因为它本质上只承诺一件事:近邻的答案值得参考。标签是类别就统计票数,标签是数字就统计均值——算法骨架不变,只换了汇总方式。

加权版(进阶):有时会让「更近的邻居」说话更响——按距离倒数加权。思想仍是问邻居,只是熟人比远亲更有话语权。
第四步 · 距离度量

「近」到底怎么量?三种常用距离

1 先记住:特征空间里的尺子

生活中「近」可以指走路近、直线近;在数据里,「近」取决于你选哪把尺子。每个样本是一组数字(特征),距离就是两串数字之间的「差多少」。

欧氏距离

√(Δx² + Δy² + …)

直线距离,像乌鸦飞。邻域形状是。最直觉,也是 KNN 默认最常见的选择。

曼哈顿距离

|Δx| + |Δy| + …

只能沿网格走,像城市街区拐弯。邻域形状是菱形。对个别维度的大偏差更「温和」一些。

明可夫斯基距离

( |Δx|ᵖ + |Δy|ᵖ + … )¹ᐟᵖ

一族距离的「总开关」:p=1 就是曼哈顿,p=2 就是欧氏。调 p,邻域形状会在菱形与圆形之间过渡。

p=1 曼哈顿 · p=2 欧氏 · p 可调
记住关系即可;公式选看

2 用「城市地图」感受差别

把蓝点、橙点放在马路十字路口上。欧氏可以斜穿街区;曼哈顿只能贴着灰色马路先横走、再竖走(不能抄斜路)。

蓝虚线 ≈ 欧氏(抄斜路)  橙折线 ≈ 曼哈顿(贴马路)

设相邻路口之间算 1 格。从起点到终点:横走 2 格、竖走 2 格——

尺子怎么走怎么算距离邻域形状
欧氏 斜穿街区 √(2² + 2²) ≈ 2.83
曼哈顿 先横 2 格,再竖 2 格 |2| + |2| 4 菱形
明可夫斯基 由 p 决定合并不同轴的差 (|2|ᵖ + |2|ᵖ)1/p p=1→4;p=2→2.83 随 p 变化

同一对点,曼哈顿「路程」更长——因为它不许抄斜路,必须沿网格累加。

3 为什么常要先「缩放」特征?

假设用两个特征找「相似邻居」:身高(厘米)和年收入(元)。

身高差收入差欧氏距离(示意)
不缩放5 cm50,000 元≈ 50000(收入几乎独占)
缩放到相近量级后0.30.4≈ 0.5(两轴都能说话)

不缩放时,收入把距离「带跑」,身高几乎没用。所以用 KNN 前,通常要做标准化 / 归一化,让每根轴分量差不多。

4 可以自定义距离吗?

可以。KNN 的骨架只要求:你能算出「两个样本有多不像」。换掉默认的欧氏距离,换成你自己的尺子,算法其余步骤(取最近 K 个 → 投票或平均)不变。

5 自定义时一般怎么做?

  1. 写一个函数 d(样本A, 样本B),返回一个非负数:越小越像。
  2. 在「算距离 → 排序 → 取 K」那一步,用你的 d 替换欧氏距离。
  3. 用验证集 / 网格搜索,比较自定义尺子和欧氏、曼哈顿谁更管用。
常见自定义想法适合什么数据直觉
余弦距离(1 − 余弦相似度)文本、高维向量看方向像不像,不太看长短
加权欧氏有些特征更重要重要维度差一点点也算「远」
汉明距离0/1、类别编码数有多少位不一样

工具里常见两种接法:直接传入自定义函数;或先算好「两两距离矩阵」,再告诉模型「距离我已经算好了」(如 scikit-learn 的 metric='precomputed')。

注意两点:① 好最好满足「自己到自己为 0、A 到 B 与 B 到 A 一样」——否则「最近」会变得别扭;② 有些加速结构(如 KD 树)只认特定距离,自定义后可能只能用「暴力算全部距离」,数据很大时会更慢。
第五步 · 动手试

互动:看邻域形状,感受距离与投票

你可以试试:先点「放到交界处」,再切换距离——半透明区域会在圆 / 菱形之间变化(明可夫斯基 p=3 介于两者之间);拖动 K,看邻居圈变大变小。

点「放到交界处」,或直接在画布上点击放置查询点。
类别 A / 偏低 类别 B / 偏高 查询点(填充色=预测) 回归:蓝→橙表示数值由低到高 邻域形状随距离变化
第六步 · 选 K 值

K 该取几?它要事先设定,不是学出来的

1 你刚在 Demo 里拖过的那个 K

K 太小:只信最近一两个人,灵敏但容易被噪声带偏。
K 太大:几乎全民公投,边界变糊。
上面 Demo 里把 K 从 1 拖到 15,就能亲眼看到邻居圈变大、票数被「冲淡」。

K = 1 只信最近一个人:灵敏,但容易被噪声带偏
适中的 K 听几个人的意见:既稳一点,又不过分模糊
K 很大 几乎全民公投:边界变糊,容易欠拟合

二分类时,K 常取奇数,减少投票平票。但这只是经验,不是铁律。

2 K 属于「超参数」,适合用网格搜索来试

和模型自己学出来的权重不同,K 必须在训练开始前由人指定——这类事先设定的旋钮叫超参数。常见做法是列出候选,比如:

K ∈ {1, 3, 5, 7, 9, 11}
再配合交叉验证,看哪一个 K 在验证集上表现最好

把候选铺成一张「网格」、逐个试完再挑最优——正是网格搜索的思路。距离种类、是否加权,也可以一起放进网格。

想系统搞清「参数 vs 超参数」以及网格搜索怎么和交叉验证配合,请读:

什么是网格搜索:参数、超参数与穷举调参 →

核心洞察

没有放之四海皆准的「最佳 K」。合适的 K 取决于数据噪声、样本密度和任务目标——所以实践里我们用验证集 / 交叉验证来选,而不是凭感觉拍一个。

第七步 · 优缺点

什么时候用 KNN?什么时候慎用?

适合

· 概念简单,结果好解释
· 数据量中等、特征维数不太高
· 决策边界不规则、不想先假设线性
· 需要快速搭一个「能跑的基线」

慎用 / 注意

· 样本很多时,每次预测都要算距离,可能变慢
· 特征很多时,「远近」会变得模糊(维度灾难)
· 特征尺度不一,必须先缩放
· 类别极不平衡时,多数类容易「霸占」投票

和评估的衔接:分类效果好不好,别只盯准确率——类别不平衡时请看精确率、召回率与混淆矩阵。可参考 预测评估与混淆矩阵
总结

带走这几句

返回首页