P4-12.2 距离(distance)与尺度(scale)¶
Section ID:
P4-12.2Version:v2026.07.20
P4-12.1 里说过,k-NN 是 通过看附近案例来做判断的模型。但在这里,真正最重要的词其实是 近。
到底什么才算近?
如果跳过这个问题,读者其实只是看到了结果,而没有真的理解模型。因为在 k-NN 里,用什么规则来计算近远 本身就是模型的一部分。
本节范围¶
这一节回答下面这些问题。
- distance 在 k-NN 里扮演什么角色?
- 如果 distance function 改变,neighbor 顺序和 prediction 会不会改变?
- 为什么 scale 会扭曲 distance 计算?
- standardization 会怎样改变 k-NN 的解释?
这一节先收束 为什么在 k-NN 里,distance 和 scale 会改变 neighbor 与 prediction。preprocessing 的目的和类型,仍然以 P4-7.2 Preprocessing 作为基准说明位置;这里专注的是 distance 和 scale 改变判断的场景。
用距离(distance)与尺度(scale)留下的判断标准¶
- 能说明 distance function 不是
模型外部的设置,而是判断规则的一部分 - 能说明 distance function 一旦改变,neighbor 顺序和 prediction 也可能改变
- 能说明 feature 的 scale 不同时,大轴可能会支配 distance
- 能说明 standardization 不是
把数字弄好看,而是重新对齐比较标准
主要学习内容¶
distance 是模型判断规则的一部分¶
k-NN 会先计算新输入与已有数据之间的距离,然后再找出最近的 neighbor。所以 distance function 不是单纯的计算工具,而是决定 谁会被选成 neighbor 的规则。
- Euclidean distance:把距离读成直线长度的方式
- Manhattan distance:把沿轴移动的量加起来的方式
即使是同一个 query,只要 distance rule 改变,neighbor 顺序就可能改变,prediction 也可能跟着改变。
flowchart TD
A["同一个查询"]
B["选择距离规则"]
C["给邻居排序"]
D["预测可能改变"]
A --> B --> C --> D
这里最关键的一句话是:
distance function 是解释输入的一部分视角。
distance function 改变时,neighbor 顺序也会改变¶
假设 query 和两个候选点如下。
| 对象 | 坐标 |
|---|---|
| query | (0, 0) |
| 点 A | (3, 0) |
| 点 B | (2, 2) |
如果按 Euclidean distance 来看:
- query 到 A 的距离 = 3
- query 到 B 的距离 = 约 2.83
所以 B 更近。
但如果按 Manhattan distance 来看:
- query 到 A 的距离 = 3
- query 到 B 的距离 = 4
这次就变成 A 更近。
这个例子展示的是:distance rule 改变 -> neighbor 顺序改变。在真正的 k-NN 里,一旦 neighbor 顺序改变,进入多数表决的 label 也会跟着改变,最终 prediction 当然也可能改变。
为什么 scale 会扭曲 distance 计算¶
和 distance function 一样重要的,是 scale。两个 feature 都是数字,不代表 distance 计算时它们就会被同样看待。
例如,假设有下面两个 feature。
- annual income:数值可能是几百万到几千万
- late payments:可能只是 0、1、2、7 这样的计数
它们都可能很重要。但如果直接保留原始范围,annual income 这一轴在数值上会显得大得多。于是 distance 会更强烈地问 谁的收入数字更像,而不是 谁的逾期模式更像。
这里要分开看的,是下面两件事。
- 单位差异:例如货币、秒数、次数,本来就属于不同的数字体系
- 分散程度差异:即使都是数值型 feature,也可能某个轴的波动远大于另一个轴
这两件事最终都会导向类似的问题:大的轴支配了 distance
flowchart TD
subgraph S1["未缩放"]
direction LR
A1["大尺度特征"] --> B1["距离几乎都沿着这条轴变化"]
end
subgraph S2["缩放之后"]
direction LR
A2["尺度可比较的特征"] --> B2["距离可以同时利用两个特征"]
end
standardization 改变了什么¶
standardization 不是为了让数字变得更漂亮。更准确地说,它是在 重新平衡每个 feature 在 distance 计算里施加的影响。
入门层面,按下面这个顺序来理解就足够了。
- 对每个 feature 先减去 mean
- 再除以 standard deviation
- 让大单位和小单位的轴进入一个更可比的范围
所以,standardization 可以被读成:把原来被淹没的 feature 再拉回比较里
但这并不等于它 一定会提升性能。重新被带回来的 feature 可能包含有用信息,也可能只是在带回噪声。
案例与示例¶
案例 1. 在贷款风险分类里,收入这个大数字掩盖了逾期记录¶
某个贷款筛查辅助模型想把新申请人分成 safe 和 risky。人首先会看 annual income、late-payment count、existing loan size、repayment history 这些信号。
问题在于,这些列的单位差得很大。annual income 可能是很大的数字,而 late-payment count 只是在 0 到几次之间。如果在这种状态下直接计算 k-NN distance,那么 late-payment count 就算在现实里很重要,也可能会被 income 这一轴淹没。
flowchart TD
A["贷款申请人查询"]
B["由混合尺度算出的原始距离"]
C["收入这一轴主导了距离"]
D["缩放后的距离"]
E["逾期还款信号重新显现"]
F["邻居列表发生变化"]
A --> B --> C
A --> D --> E --> F
这个案例显示了下面几个关键点。
- distance 和 scale 不是 preprocessing 之外的小选择,而是判断规则的一部分
- 即使数据本身不变,只要表示方式变了,
谁被算作近邻就可能改变 - 所以在 scale 调整前后,应该首先看
哪些 neighbors 进来了,哪些出去 了,而不是只盯着最后一个 score
练习与示例¶
Python 例子:比较原始距离和 scale 调整后的距离¶
- 问题场景:看看一个新客户更接近
safe还是risky - 输入(input):annual income 与 late-payment count
- label:
safe/risky - 要检查的概念:
- 在原始数字下,收入这一大单位轴可能会支配 distance
- standardization 后,小轴的信息可能会重新进入比较
- 因此,即使 query 相同,最近邻顺序也可能改变
可以按下面这个顺序来读。
- 先看原始距离下,哪一组更近
- 再看 standardization 后,哪些 neighbors 重新变得更近
- 如果出现差异,先把它解释成
nearness 的计算规则改变了,而不是模型本身改变了
示例输出如下。
这个输出里,首先要抓住下面这句话。
k-NN 的结果不仅依赖数据本身,也依赖数据是怎样被表示的。
在原始距离下,先出现的是 risky 组;standardization 之后,先出现的是 safe 组。如果再用 k=3 来看,原始距离里是 risky, risky, safe,所以最后 prediction 是 risky;standardization 之后是 safe, safe, risky,于是 prediction 变成 safe。因此,这个例子首先应该让读者看到的,不只是 score 变了,而是 neighbor 顺序本身变了,而且这种变化真的传到了 k-NN 的判断上。
再改一个值:在相同 scale 下,只增加 late-payment count,会怎样重新打乱 neighbor 顺序¶
现在保持同一个 standardization 方式,只把 query 的 late-payment count 从 0 改成 2。
示例输出如下。
什么保持了不变,什么发生了改变¶
- 保持不变的点:scale 调整之后,distance 仍然不再只看 income,一样会让 late-payment 轴真正参与比较
- 发生变化的点:只把 late-payment count 稍微提高一点,第二个 neighbor 就开始从
safe换成risky - 首先要留下的判断:standardization 不是一次做完就结束的技术检查,它也是重新观察
feature 变化会怎样摇动 neighbor 组成与 prediction的出发点
通过这个比较,k-NN 不再只是 找来近邻案例的模型,而会被重新读成 对表示方式和输入变化都很敏感的比较规则。重要的不是背下 k 的数值,而是能够说明:即使是同一个 query,只要表示方式或 feature 数值稍有变化,哪些 neighbor 会进来,哪些会出去。反复改一处的练习,真正的学习效果也不在于只说 prediction 变了,而在于能指出 改了什么以后,比较标准的哪一部分又被重新打乱了。
| 通用记录语言 | 这次练习里应立刻留下的内容 |
|---|---|
| 看见的结构 | scale 对齐之后,即使很小的 feature 变化,也会重新打乱 neighbor 组成和最终判断 |
| 解释边界 | 只凭某一个 query 的 neighbor 变化,不能直接断定某个 feature 永远更重要 |
| 下一个问题 | 如果改变 k,neighbor 的替换会不会继续传到最终多数表决?其他 query 上也会不会出现同样的敏感度? |
检查清单¶
- 能不能说明为什么 distance function 是判断规则的一部分?
- 是否理解了 distance function 改变时,neighbor 顺序和 prediction 也会改变?
- 是否理解了大轴支配 distance 时,小轴上的重要信息可能会被埋掉?
- 能不能把 standardization 解释成重新平衡比较标准?
- 是否在同一个 query 上,比较了 scale 调整前后哪些 neighbor 进来、哪些出去?
- 即使 standardization 后出现了差异,是否也没有把它单独当成完整的原因解释?
出处与参考资料¶
- scikit-learn, Nearest Neighbors, scikit-learn User Guide, 确认日期: 2026-06-27. https://scikit-learn.org/stable/modules/neighbors.html
- scikit-learn, Importance of Feature Scaling, scikit-learn Examples, 确认日期: 2026-06-27. https://scikit-learn.org/stable/auto_examples/preprocessing/plot_scaling_importance.html