现在位置: 首页 > AI 数学基础 > 正文

向量的模长与余弦相似度

上一章的点积同时包含了长度和方向的信息。

本章把它们拆开:模长单独衡量大小,余弦相似度单独衡量方向一致性

模长:向量有多长?

模长就是向量从原点到终点的「直线距离」——勾股定理在高维空间的推广。

L1 范数

\( \|\mathbf{v}\|_1 = \sum |v_i| \)

曼哈顿距离:沿街道走

(3,4) 的 L1 = 7

L2 范数(默认)

\( \|\mathbf{v}\|_2 = \sqrt{\sum v_i^2} \)

直线距离:空中飞

(3,4) 的 L2 = 5

未特别说明时,「模长」或 \( \|\mathbf{v}\| \) 默认指 L2 范数。

单位向量:扔掉长度,只留方向

任何非零向量除以自己的模长,得到长度为 1 的 单位向量

\[ \hat{\mathbf{v}} = \frac{\mathbf{v}}{\|\mathbf{v}\|} \]

归一化后向量方向不变,但模长变为 1。

余弦相似度:只看方向,不看大小

余弦相似度 = 把两个向量都归一化为单位向量后,再做点积:

\[ \text{cosine\_sim}(\mathbf{a}, \mathbf{b}) = \frac{\mathbf{a}\cdot\mathbf{b}}{\|\mathbf{a}\|\|\mathbf{b}\|} = \cos\theta \]

方向一致

cos=1

方向垂直

cos=0

方向相反

cos=-1

余弦相似度只关心方向,不关心长度。

v = (3,4) 和 w = (6,8)(w = 2v),长度差一倍,但余弦相似度 = 1——因为它们方向完全相同。


生活例子

模长:距离的度量

你家到学校直线距离 5 公里(L2 = 5),但沿街道走要绕 7 公里(L1 = 7)。

两种度量方式各有用途,AI 中主要用 L2。

余弦相似度:音乐品味匹配

张三听了 100 首歌,李四听了 10 首歌。用点积的话,张三的分数天然更高。

但用余弦相似度,只看品味方向是否一致——张三(活跃用户)和李四(新用户)也能公平比较。


数学定义

拆解核心公式

\[ \mathbf{a} \cdot \mathbf{b} = \|\mathbf{a}\| \|\mathbf{b}\| \cos\theta \]

点积 = 长度乘积 × 方向一致性。反过来可以求出:

\[ \cos\theta = \frac{\mathbf{a} \cdot \mathbf{b}}{\|\mathbf{a}\| \|\mathbf{b}\|} \]

Python 动手实践

实例

import numpy as np

v_runoob = np.array([3, 4, 0])
w_runoob = np.array([6, 8, 0])  # v 的 2 倍

# 模长
norm_v = np.linalg.norm(v_runoob)   # L2 默认
norm_w = np.linalg.norm(w_runoob)
print(f"||v|| = {norm_v:.1f}, ||w|| = {norm_w:.1f}")  # 5, 10

# 归一化
unit_v = v_runoob / norm_v
unit_w = w_runoob / norm_w
print("v 归一化:", unit_v)    # [0.6, 0.8, 0.]
print("w 归一化:", unit_w)    # [0.6, 0.8, 0.] 完全相同!

# 余弦相似度
cos_sim = np.dot(v_runoob, w_runoob) / (norm_v * norm_w)
print(f"余弦相似度 = {cos_sim:.4f}")  # 1.0

# 批量计算余弦相似度矩阵
embeddings = np.array([
    [0.2, 0.5, 0.1, 0.8, 0.3],
    [0.3, 0.6, 0.2, 0.7, 0.4],
    [0.9, 0.1, 0.8, 0.1, 0.9],
])
norms = np.linalg.norm(embeddings, axis=1, keepdims=True)
normalized = embeddings / norms
sim_matrix = normalized @ normalized.T
print("\n余弦相似度矩阵:")
print(np.round(sim_matrix, 3))
||v|| = 5.0, ||w|| = 10.0
v 归一化: [0.6 0.8 0. ]
w 归一化: [0.6 0.8 0. ]
余弦相似度 = 1.0000

余弦相似度矩阵:
[[1.    0.996 0.146]
 [0.996 1.    0.182]
 [0.146 0.182 1.   ]]

AI 中的应用场景

语义搜索与推荐系统

将查询词和文档分别编码为向量后,用余弦相似度排序——找最相关的文档。Google 的语义搜索、RAG(检索增强生成)中的向量检索都依赖余弦相似度。

相比点积,余弦相似度不受向量模长影响——一篇长文章的向量模长可能很大,但用余弦相似度能公平地与短查询比较方向一致性。

人脸识别:余弦相似度 > 欧氏距离

FaceNet 等面部识别模型将人脸映射为 128 维嵌入向量。两个人脸是否匹配,用余弦相似度判断——它对照明条件、照片亮度(影响向量模长)不敏感。

两张同一个人不同光照下的照片,嵌入向量方向几乎一致(cos ≈ 0.95+),但模长可能差很多。

L2 正则化防止过拟合

损失函数中加入 \( \lambda\|\mathbf{w}\|^2 \)(权重衰减),惩罚权重模长过大。权重模长大意味着模型对某些特征过度信任,泛化能力差。L2 正则化将其拉向原点附近。

Batch Normalization 中的归一化

BN 对每层激活值做归一化:减均值后除以标准差,将数据变为模长稳定的分布。这用到了 L2 范数的概念来控制各层输出的尺度。