范数与距离:相似性的几何


文档摘要

范数与距离:相似性的几何 本节摘要:你的距离函数定义了什么叫「相似」——选错了,下游一切都会塌方。两个数据点在一种度量下是最近邻,在另一种度量下却相隔甚远。本节讲透范数(Norm)与距离(Distance)的完整谱系:从 L1(曼哈顿,稀疏与抗噪)、L2(欧几里得,几何直线)、L∞(切比雪夫,最坏情况)到 Lp 的一般族与单位球的形变;从余弦相似度(NLP 与嵌入的王者,只看方向不看长度)、点积相似度(带量级的受欢迎度信号)到马氏距离(用协方差白化后算 L2,识破相关特征里的异常点);再覆盖集合的 Jaccard、字符串的编辑距离(Levenshtein)、分布的 KL 散度(非对称、非真距离)与 Wasserstein(真度量、分布不重叠也给出梯度)。

范数与距离:相似性的几何

本节摘要:你的距离函数定义了什么叫「相似」——选错了,下游一切都会塌方。两个数据点在一种度量下是最近邻,在另一种度量下却相隔甚远。本节讲透范数(Norm)与距离(Distance)的完整谱系:从 L1(曼哈顿,稀疏与抗噪)、L2(欧几里得,几何直线)、L∞(切比雪夫,最坏情况)到 Lp 的一般族与单位球的形变;从余弦相似度(NLP 与嵌入的王者,只看方向不看长度)、点积相似度(带量级的受欢迎度信号)到马氏距离(用协方差白化后算 L2,识破相关特征里的异常点);再覆盖集合的 Jaccard、字符串的编辑距离(Levenshtein)、分布的 KL 散度(非对称、非真距离)与 Wasserstein(真度量、分布不重叠也给出梯度)。本节把每种距离与正则化(L1=Lasso 造稀疏、L2=Ridge 缩权重)、损失函数(MSE/MAE/Huber/交叉熵)、近似最近邻(HNSW/LSH/IVF)一一接通,让你针对任务选对工具。

对应原课程:Phase 01 · Lesson 14 · norms-and-distances(原英文 phases/01-math-foundations/14-norms-and-distances/docs/en.md)。前置:第 1、2 节(线性代数)。

学习目标

阅读完本节,你应当能够:

  1. 从零实现 L1、L2、余弦、马氏、Jaccard、编辑距离函数。
  2. 针对给定 ML 任务选择合适的距离度量,并解释为何其他选择会失败。
  3. 把 L1、L2 范数与 Lasso、Ridge 正则化及其几何约束区域联系起来。
  4. 演示同一数据集在不同度量下给出不同最近邻

一、问题与直觉

你有两个向量——也许是词嵌入、用户画像、像素数组——你想知道:它们有多近?答案完全取决于你选哪个距离函数。你的 KNN 分类器、推荐引擎、向量数据库、聚类算法、损失函数,全都依赖这个选择。选错,模型就在优化错误的东西。

没有普适最优的距离。L2 适合空间数据;余弦相似度统治 NLP;Jaccard 处理集合;编辑距离处理字符串;马氏距离考虑相关性;Wasserstein 移动概率质量。每一种都编码了对「相似」的不同假设。

1.1 范数:度量向量大小

范数度量向量的「大小」。两个向量之间的任何距离都可写成它们差的范数:d(a,b) = ‖a − b‖。所以理解范数就是理解距离。

1.2 L1 范数(曼哈顿距离)

L1 范数是所有分量绝对值之和:‖x‖₁ = |x₁| + |x₂| + … + |xₙ|。叫曼哈顿距离是因为它量的是在只能沿轴走的城市网格上走多远,没有对角线。

点 A = (1, 1),点 B = (4, 5) L1 距离 = |4-1| + |5-1| = 3 + 4 = 7 ← 在网格上向东 3 格、向北 4 格

何时用 L1:高维稀疏数据(文本特征、one-hot);想要对异常值的鲁棒性(单个巨大差异不主导);特征选择(L1 正则化促稀疏)。

与 L1 正则化(Lasso)的联系:在损失里加 ‖w‖₁ 惩罚权重绝对值之和,把小权重推到恰好为零,自动做特征选择。L1 惩罚在权重空间造出菱形约束区域,菱形的角恰在坐标轴上——损失等高线最易在角处相切,使某些权重为零。

与损失函数的联系:平均绝对误差 MAE 就是预测与目标的平均 L1 距离,线性惩罚所有误差,比 MSE 更抗异常值。

1.3 L2 范数(欧几里得距离)

L2 范数是直线距离:‖x‖₂ = √(x₁² + x₂² + … + xₙ²),就是几何课学的距离,n 维的勾股定理。

点 A = (1, 1),点 B = (4, 5) L2 距离 = √((4-1)² + (5-1)²) = √(9+16) = √25 = 5.0 ← 穿过网格的对角直线

何时用 L2:低到中维连续数据;特征尺度可比;物理距离(空间数据、传感器);像素级图像相似度。

与 L2 正则化(Ridge)的联系:加 ‖w‖₂² 惩罚大权重,与 L1 不同它不把权重推到零,而是按比例把所有权重向零收缩。L2 惩罚造出圆形约束区域,没有落在轴上的角——权重变小但极少恰好为零。

与损失函数的联系:均方误差 MSE 是 L2 距离平方的平均,平方让大误差受罚更重。MAE = |y-ŷ|(线性、抗异常值);MSE = (y-ŷ)²(二次、对异常值敏感)。

1.4 Lp 范数:一般族

L1、L2 是 Lp 范数的特例:‖x‖_p = (|x₁|^p + … + |xₙ|^p)^(1/p)。不同的 p 造出不同形状的「单位球」(距原点距离为 1 的所有点的集合):

p=1: 菱形 (角在轴上) p=2: 圆/球 (通常的圆球) p=3: 超椭圆 (圆角方形) p=∞: 方形/超立方体 (沿轴的平直边)

1.5 L∞ 范数(切比雪夫距离)

当 p → ∞,Lp 范数收敛到最大绝对分量:‖x‖∞ = max(|x₁|, …, |xₙ|)。两点距离由它们差异最大的那一维决定,其余维被忽略。

点 A = (1, 1),点 B = (4, 5) L∞ 距离 = max(|4-1|, |5-1|) = max(3, 4) = 4

何时用 L∞:任一维的最坏偏差要紧时(国际象棋王的移动是 L∞——任一方向走一步算 1);制造公差(每维都必须在规格内)。

1.6 余弦相似度与余弦距离

余弦相似度量两向量的夹角,忽略大小:cos_sim(a,b) = (a·b)/(‖a‖₂·‖b‖₂),范围 [-1, +1]:-1 反向、+1 同向、0 垂直。余弦距离 = 1 − 余弦相似度,范围 [0, 2]。

a = (1, 0),b = (1, 1) cos_sim = (1*1 + 0*1)/(1*√2) = 1/√2 = 0.707 cos_dist = 1 - 0.707 = 0.293

为何余弦统治 NLP 与嵌入:在文本里,文档长度不应影响相似度——一篇讲猫的文档即使比另一篇讲猫的长一倍,仍应「相似」。余弦忽略大小(长度)只看方向,两篇词分布相同但长度不同的文档方向相同,余弦相似度为 1.0。何时用:文本相似度(TF-IDF、词/句嵌入);量级是噪声、方向是信号的任何领域;推荐系统(用户偏好向量);嵌入搜索(向量数据库几乎总用余弦或点积)。

1.7 点积相似度 vs 余弦相似度

点积 a·b = ‖a‖·‖b‖·cos(夹角)。余弦相似度是点积除以两个范数。当两向量都已单位归一化(范数=1),点积与余弦相同:a·b = cos(夹角)

区别在于:点积包含量级信息,范数更大的向量得分更高。这在一些检索系统里要紧——你想让「热门」项排名更高,量级充当隐式的质量或重要性信号。实战:要纯方向相似度用余弦;量级承载有意义信息时用点积;若嵌入已 L2 归一化,两者无差别。

1.8 马氏距离(Mahalanobis)

欧几里得距离对所有维一视同仁,但若特征相关或尺度不同,L2 会误导。马氏距离考虑数据的协方差结构:

d_M(x,y) = √((x-y)ᵀ · S⁻¹ · (x-y)) ← S 是数据协方差矩阵

直觉:马氏距离先白化(去相关 + 归一化)数据,再在那个变换空间里算 L2。若 S 是单位矩阵(不相关、单位方差),马氏退化为欧几里得。

身高与体重相关: 6尺2寸、180磅 —— 不算异常 5尺0寸、180磅 —— 异常 欧几里得可能说两者离均值同样远;马氏因考虑身高-体重相关性,正确识别第二个为异常点。

何时用:异常检测(离均值马氏距离大的点是异常);特征尺度不同且相关时的分类;有足够数据估可靠协方差时;制造的多元过程监控。

1.9 Jaccard 相似度(集合)

Jaccard 量两集合的重叠:J(A,B) = |A∩B| / |A∪B|,范围 [0,1]:0 无重叠、1 完全相同。Jaccard 距离 = 1 − Jaccard 相似度。

A = {猫, 狗, 鱼},B = {猫, 鸟, 鱼, 蛇} 交集 = {猫, 鱼}(2),并集 = {猫,狗,鱼,鸟,蛇}(5) Jaccard 相似度 = 2/5 = 0.4,Jaccard 距离 = 0.6

何时用:比较标签/类别/特征集合;基于词有无(非频率)的文档相似度;近似重复检测(MinHash 近似 Jaccard);二元特征向量(有/无数据);分割模型评估(IoU = Jaccard)。

1.10 编辑距离(Levenshtein)

编辑距离是把一个串变成另一个所需的最少单字符操作(插入、删除、替换)数。用动态规划算,填一个矩阵,其中 (i,j) 项是串 A 前 i 字符与串 B 前 j 字符的编辑距离。

kitten -> sitting(3 步): kitten -> sitten(替换 k→s) sitten -> sittin(替换 e→i) sittin -> sitting(插入 g)

何时用:拼写检查与纠正;DNA 序列比对(带加权操作);模糊字符串匹配;脏文本去重。

1.11 KL 散度(不是距离,却常被当距离用)

KL 散度量一个概率分布与另一个的差异(第 9 节已讲,这里因常被当「距离」而纳入):D_KL(P‖Q) = Σ p(x)·log(p(x)/q(x))关键性质:KL 散度不对称 D_KL(P‖Q) ≠ D_KL(Q‖P),它不满足距离的基本要求,也不满足三角不等式——它是散度(Divergence),不是距离。前向 KL(P‖Q)「均值-seeking」,Q 试图覆盖 P 所有模态;反向 KL(Q‖P)「模态-seeking」,Q 聚焦 P 的单一模态。出现于:VAE(ELBO 的 KL 项把潜分布推向先验)、知识蒸馏(学生匹配教师分布)、RLHF(KL 惩罚让微调模型贴近基座)、策略梯度方法。

1.12 Wasserstein 距离(推土机距离)

Wasserstein 距离度量把一个概率分布变换成另一个所需的最小「功」——若一个分布是一堆土、另一个是一个坑,你要搬多少土、搬多远。

W(P,Q) = inf(所有运输方案 γ 的 E[d(x,y)]) 对 1D 分布,简化为 CDF 绝对差的积分:W₁(P,Q) = ∫|CDF_P(x) − CDF_Q(x)| dx

为何重要:① 它是真度量(对称、满足三角不等式);② 即使分布不重叠也给出梯度(KL 散度在不重叠时为无穷);③ 这一性质使它成为 Wasserstein GAN 的核心,解决了原始 GAN 的训练不稳定。

不重叠分布:P=[1,0,0,0,0],Q=[0,0,0,0,1] KL 散度:无穷(log 0) Wasserstein:4(把全部质量搬 4 格) ← Wasserstein 给出有意义的梯度,KL 不给

何时用:GAN 训练(WGAN、WGAN-GP);比较可能不重叠的分布;最优运输问题;图像检索(比较颜色直方图)。

1.13 不同任务为何需要不同距离

任务 最佳距离 原因
文本相似度 余弦 量级是噪声、方向是含义
图像像素比较 L2 空间关系要紧、特征尺度可比
稀疏高维特征 L1 鲁棒、不放大罕见的大差异
集合重叠(标签) Jaccard 数据天然是集合而非向量
字符串匹配 编辑距离 操作映射人类编辑直觉
异常检测 马氏 考虑特征相关性与尺度
比较分布 KL 散度 量度用 Q 代 P 损失的信息
GAN 训练 Wasserstein 分布不重叠也给出梯度
嵌入(向量库) 余弦或点积 嵌入训练把含义编码进方向
推荐 点积 量级可编码受欢迎度/置信度
DNA 序列 加权编辑距离 替换代价随核苷酸对而变
制造 QC L∞ 任一维的最坏偏差要紧

1.14 与损失函数的联系

损失函数就是作用于「预测 vs 目标」的距离函数:

损失函数 所用距离 行为 MSE L2 平方 重罚大误差 MAE L1 均等罚所有误差 Huber 大误差用 L1, 兼顾二者:抗异常值, 小误差用 L2 零附近梯度平滑 交叉熵 KL 散度 量度分布失配 Hinge max(0, margin-d) 只罚 margin 以下 Triplet L2(典型) 拉近正例、推开负例

1.15 与正则化的联系

正则化在损失里加权重范数惩罚:

  • L1 正则(Lasso):loss + λ·‖w‖₁ → 稀疏权重(部分恰为零),自动特征选择,解有角(零处不可导)。
  • L2 正则(Ridge):loss + λ·‖w‖₂² → 小权重(全部向零收缩),无特征选择(无恰为零),处处光滑。
  • Elastic Net:loss + λ₁·‖w‖₁ + λ₂·‖w‖₂² → 结合 L1 稀疏与 L2 稳定,相关特征组一起保留或丢弃。

为何 L1 造稀疏而 L2 不:在 2D 权重空间画约束区域——L1 是菱形、L2 是圆。损失的等高线(椭圆)最可能在菱形的(某权重为零)处相切,而在圆的光滑点(两权重都非零)处相切。

1.16 最近邻搜索

每个距离函数都隐含一个最近邻搜索问题:给查询点,找数据集中最近的点。精确最近邻搜索每查一次是 O(n·d),大数据集太慢。近似最近邻(ANN) 用一点精度换巨大加速:

算法 方法 使用者 KD-tree 轴对齐空间划分 sklearn(低维) Ball tree 嵌套超球 sklearn(中维) LSH 随机哈希投影 近重复检测 HNSW 分层可导航小世界图 FAISS、Qdrant、Weaviate IVF 倒排文件+聚类搜索 FAISS(十亿级) 乘积量化 压缩向量、压缩空间内搜索 FAISS(内存受限)

HNSW(分层可导航小世界)是现代向量数据库的主流算法,它建一个多层图,每个节点连到其近似最近邻。搜索从顶层(稀疏、长跳)开始,逐层下降到底层(密集、短跳)。

二、从零实现

完整源码见 phases/01-math-foundations/14-norms-and-distances/code/distances.py,所有函数只用基本 Python math 从零实现,涵盖全部范数与距离函数,以及「同一数据、不同距离、不同最近邻」与「嵌入相似度搜索」的演示。

核心骨架示例:

def l1(a, b): return sum(abs(x - y) for x, y in zip(a, b)) def l2(a, b): return math.sqrt(sum((x - y)**2 for x, y in zip(a, b))) def linf(a, b): return max(abs(x - y) for x, y in zip(a, b)) def cosine_similarity(a, b): dot = sum(x*y for x, y in zip(a, b)) na = math.sqrt(sum(x*x for x in a)); nb = math.sqrt(sum(y*y for y in b)) return dot / (na * nb) def jaccard(A, B): return len(A & B) / len(A | B) def edit_distance(s, t): m, n = len(s), len(t) dp = [[0]*(n+1) for _ in range(m+1)] for i in range(m+1): dp[i][0] = i for j in range(n+1): dp[0][j] = j for i in range(1, m+1): for j in range(1, n+1): cost = 0 if s[i-1] == t[j-1] else 1 dp[i][j] = min(dp[i-1][j]+1, dp[i][j-1]+1, dp[i-1][j-1]+cost) return dp[m][n]

三、框架对比

最常见的实战用途:在向量数据库里找相似项。

def cosine_similarity_matrix(X): norms = np.linalg.norm(X, axis=1, keepdims=True) norms = np.where(norms == 0, 1, norms) X_normalized = X / norms return X_normalized @ X_normalized.T # 归一化后点积 = 余弦 embeddings = np.random.randn(1000, 768) sim_matrix = cosine_similarity_matrix(embeddings) similarities = sim_matrix[0] top_k = np.argsort(similarities)[::-1][1:6] # 最相似的 5 个(排除自身)

当你调用 model.encode(text) 再搜索向量库时,底层就是:嵌入模型把文本映成向量,向量库用 ANN 算法(避免全量比对)计算查询向量与每个存储向量的余弦相似度(或点积)。FAISS(Meta)、Pinecone、Weaviate、Qdrant 都内置了这些。

四、可复用产物

  • code/distances.py:全部距离函数的从零实现 + 「同数据不同距离不同最近邻」与「嵌入相似度搜索」演示。
  • 一份说明:如何在给定任务里选对距离度量的决策框架。

源码见 phases/01-math-foundations/14-norms-and-distances/code/

五、练习

  1. (Easy) 算 (1,2,3) 与 (4,0,6) 的 L1、L2、L∞ 距离,验证恒有 L∞ ≤ L2 ≤ L1,并证明该序为何成立。
  2. (Medium) 造两个余弦相似度高(>0.9)但 L2 距离大(>10)的向量,几何上解释发生了什么;再造两个余弦低(<0.3)但 L2 小(<0.5)的向量。
  3. (Medium) 实现函数:给数据集与查询点,返回在 L1、L2、余弦、马氏下的最近邻;找一个四者全分歧的数据集。
  4. (Hard) 用 CDF 法手算 [0.5,0.5,0,0] 与 [0,0,0.5,0.5] 的 Wasserstein 距离;再算 [0.25,0.25,0.25,0.25] 与 [0,0,0.5,0.5] 的,哪个更大、为什么?
  5. (Hard) 实现 MinHash 近似 Jaccard:生成 100 个随机集合,算所有对的精确 Jaccard,与用 50、100、200 个哈希函数的 MinHash 近似比较,画近似误差图。

本节要点回顾

  1. 距离函数定义「相似」:两个点在一种度量下最近、在另一种下可能很远,选错下游全塌。
  2. L1 = 曼哈顿:绝对值之和,抗异常值、促稀疏,MAE 损失、Lasso 正则。
  3. L2 = 欧几里得:平方和开根,n 维勾股,MSE 损失、Ridge 正则,适合连续空间数据。
  4. Lp 单位球形变:p=1 菱形、p=2 圆、p=∞ 方形;L∞ 只看差异最大的那一维。
  5. 余弦相似度统治 NLP:只看方向不看长度,文档长度不影响相似度;归一化后等于点积。
  6. 点积带量级信号:要纯方向用余弦,要「受欢迎度」隐式信号用点积。
  7. 马氏距离白化后算 L2:用协方差 S⁻¹ 去相关归一化,识破相关特征里的异常点。
  8. Jaccard 算集合、编辑距离算字符串:IoU = Jaccard;Levenshtein 用动态规划。
  9. KL 散度不对称非真距离:前向均值-seeking、反向模态-seeking;Wasserstein 是真度量、分布不重叠也给梯度(WGAN 核心)。
  10. L1 造稀疏、L2 只收缩:L1 菱形有角在轴上(易相切得零权重),L2 圆光滑(权重变小但非零);ANN 用 HNSW/LSH/IVF 加速最近邻。

下一节,我们用统计回答「模型是真有效还是只是运气好」——面向机器学习的统计:描述性统计、相关、假设检验、p 值、置信区间、bootstrap,以及如何区分统计显著与实际显著。


发布者: 作者: Rohit Gupta 转发
评论区 (0)
U