矩阵乘法

矩阵乘法并不是对应位置相乘,而是一个“行乘列”的过程。

简单来说,结果矩阵中第 \(i\) 行第 \(j\) 列的元素,是由第一个矩阵的\(i\)与第二个矩阵的\(j\)对应元素相乘再求和得到的。


1. 计算的前提条件

只有当第一个矩阵的列数等于第二个矩阵的行数时,两个矩阵才能相乘。

  • 矩阵 \(A\)\(m \times n\)
  • 矩阵 \(B\)\(n \times p\)
  • 结果矩阵 \(C\)\(m \times p\)

2. 3×2 矩阵乘法示例

我们要计算一个 \(3 \times 2\) 矩阵(3行2列)乘以一个 \(2 \times 2\) 矩阵(2行2列),结果将是一个 \(3 \times 2\) 矩阵。

设定矩阵:

\[A = \begin{bmatrix} 1 & 2 \\ 3 & 4 \\ 5 & 6 \end{bmatrix}, \quad B = \begin{bmatrix} 7 & 8 \\ 9 & 10 \end{bmatrix} \]

计算步骤:

  • 结果矩阵第一行:

    • \(C_{11} = (1 \times 7) + (2 \times 9) = 7 + 18 = \mathbf{25}\)
    • \(C_{12} = (1 \times 8) + (2 \times 10) = 8 + 20 = \mathbf{28}\)
  • 结果矩阵第二行:

    • \(C_{21} = (3 \times 7) + (4 \times 9) = 21 + 36 = \mathbf{57}\)
    • \(C_{22} = (3 \times 8) + (4 \times 10) = 24 + 40 = \mathbf{64}\)
  • 结果矩阵第三行:

    • \(C_{31} = (5 \times 7) + (6 \times 9) = 35 + 54 = \mathbf{89}\)
    • \(C_{32} = (5 \times 8) + (6 \times 10) = 40 + 60 = \mathbf{100}\)

3. 最终结果

\[C = A \times B = \begin{bmatrix} 25 & 28 \\ 57 & 64 \\ 89 & 100 \end{bmatrix} \]

核心口诀:

左行乘右列,对应相乘再加和。


矩阵乘法本质上是一种“变换”“投影”

1. 坐标系的空间变换(最核心的意义)

在计算机图形学和线性代数中,矩阵乘法代表了对空间的拉伸、旋转或平移

  • 你可以把矩阵 \(A\) 看作是一个“转换器”
  • 把向量 \(\vec{v}\) 看作是一个“点”
  • \(A\vec{v}\) 的结果就是这个点在经过某种规则转换后的新位置

直观理解: 想象你有一张橡皮筋做的网,矩阵乘法就是你用力拉扯或旋转这张网的过程。


2. 信息的叠加与加权汇总

从数据处理的角度看,矩阵乘法是在做加权求和

  • 左矩阵的行: 代表不同的“观察维度”或“加权方案”。
  • 右矩阵的列: 代表不同的“对象”或“原始数据”。

例子:
假设矩阵 \(A\) 是 3 种食谱所需的食材比例,矩阵 \(B\) 是 2 家超市的食材单价。
那么 \(A \times B\) 的结果直接就是:用 3 种食谱在 2 家超市分别做饭的总成本。 它一次性处理了所有组合的对应关系。


3. 系统状态的演变(马尔可夫链)

在预测模型(如天气预报、网页排名)中,矩阵乘法代表了状态的转移

  • 如果矩阵 \(P\) 代表了“今天下雨,明天转晴”的概率。
  • 那么 \(P^n\)(矩阵的 \(n\) 次方)就代表了 \(n\) 天后天气的概率分布。
    矩阵乘法在这里捕捉了系统随时间演化的链式反应。

4. 降维与特征提取

在人工智能(AI)和深度神经网络中,矩阵乘法被用来提取特征。

  • 一个高维的图像信号通过一个矩阵(权重),可以被压缩或映射成低维的特征(比如识别出这是一个“猫”)。
  • 大模型(如 GPT)的本质: 就是无数次超大规模的矩阵乘法,将输入的文本向量不断通过权重矩阵进行变换,最终“变换”出下一个字出现的概率。

总结

矩阵乘法不是数学家发明的繁琐游戏,而是一种高效率的并行处理协议。它把复杂的、多维度的对应关系,浓缩进了一个简洁的乘法符号中。


在 Milvus 中的意义: 批量计算向量相似度(如 Inner Product)的本质就是矩阵乘法。

理论与数学含义

矩阵乘法 \(C = A \times B\) 不是简单的元素对应相乘,而是线性变换的复合

  • 物理意义: 矩阵 \(A\) 的每一行可以看作一个待检索向量,矩阵 \(B\) 的每一列是一个查询向量。乘法的结果矩阵中的每个元素 \(C_{ij}\),代表了第 \(i\) 个向量与第 \(j\) 个查询之间的“相关性得分”。

计算原理

\(A\)\(m \times n\) 矩阵,\(B\)\(n \times p\) 矩阵,结果 \(C\) 的元素计算公式为:

\[C_{ij} = \sum_{k=1}^{n} A_{ik}B_{kj} \]

计算示例

\(A\) 为两个 2 维向量,\(B\) 为一个查询向量:

\[A = \begin{bmatrix} 1 & 2 \\ 3 & 4 \end{bmatrix}, B = \begin{bmatrix} 0.5 \\ 0.1 \end{bmatrix} \]

\[C = \begin{bmatrix} (1 \times 0.5 + 2 \times 0.1) \\ (3 \times 0.5 + 4 \times 0.1) \end{bmatrix} = \begin{bmatrix} 0.7 \\ 1.9 \end{bmatrix} \]


2. 矩阵转置 (Matrix Transpose)

矩阵转置(Transpose)的操作非常直观,如果说矩阵乘法是“变换”,那么转置更像是“视角的切换”“结构的重组”


1. 矩阵转置的计算:3×2 示例

计算规则非常简单:行变列,列变行。原本位于第 \(i\) 行第 \(j\) 列的元素,转置后挪到第 \(j\) 行第 \(i\) 列。

示例:

假设我们有一个 \(3 \times 2\) 的矩阵 \(A\)

\[A = \begin{bmatrix} 1 & 2 \\ 3 & 4 \\ 5 & 6 \end{bmatrix} \]

我们将每一行“竖”起来写,或者将每一列“横”过来写,得到转置矩阵 \(A^T\)(这是一个 \(2 \times 3\) 矩阵):

\[A^T = \begin{bmatrix} 1 & 3 & 5 \\ 2 & 4 & 6 \end{bmatrix} \]


2. 矩阵转置的深层意义

为什么要把矩阵“翻转”过来呢?在不同的领域,它有不同的物理意义:

A. 数据的维度重组(表格视角)

在数据分析中,矩阵通常代表一张表:

  • 原矩阵 \(A\):行代表“样本”(比如 3 个学生),列代表“特征”(比如数学、英语成绩)。
  • 转置矩阵 \(A^T\):行变成了“特征”,列变成了“样本”。
    当你需要从“科目”的角度来观察整体分布,而不是从“人”的角度看时,转置就是一种数据透视

B. 算子与向量的角色互换

在线性代数中,矩阵乘法 \(Ax\) 可以看作是矩阵作用于向量。
而转置往往出现在内积(点积)的定义中:

\[\vec{u} \cdot \vec{v} = u^T v \]

这里转置的意义在于将一个“空间中的位置(列向量)”转化为一个“线性函数(行向量)”,使得两个向量可以相乘并产生一个标量结果。

C. 图形学与物理中的“逆”操作

对于某些特殊的矩阵(正交矩阵),转置就等于它的逆矩阵\(A^T = A^{-1}\))。

  • 如果矩阵 \(A\) 代表将物体旋转 30°,那么 \(A^T\) 就代表将物体旋转 -30°
  • 转置在这里代表了某种“撤销”“反向变换”的尝试。

D. 机器学习中的权重调整

在深度学习的反向传播算法中,转置矩阵至关重要。

  • 正向传播: 输入数据通过权重矩阵 \(W\) 得到结果。
  • 反向传播: 误差信号需要通过权重矩阵的转置 \(W^T\) 传回给输入层。
    这里转置的意义是:沿着路径反向分摊责任。

3. 核心性质(避坑指南)

在处理复杂公式时,请务必记住这个关于乘法转置的“反直觉”性质:

\[(AB)^T = B^T A^T \]

比喻: 如果你先穿袜子再穿鞋(\(AB\)),那么你要撤销这个过程(转置),必须先脱鞋再脱袜子(\(B^T A^T\))。

你是在处理具体的算法推导(比如最小二乘法或神经网络),还是在整理线性代数的基础笔记?

在 Milvus 中的意义: 用于调整向量布局(从行存到列存),或在计算余弦相似度时将横向向量转为纵向以进行点积。

理论与数学含义

转置 \(A^T\) 是将矩阵的行与列互换。

  • 数学含义: 在内积空间中,转置与伴随算子有关。它常用于改变运算的方向。例如,计算两个向量 \(\mathbf{u}\)\(\mathbf{v}\) 的点积,数学表达为 \(\mathbf{u}^T\mathbf{v}\)

计算示例

\[A = \begin{bmatrix} 1 & 2 & 3 \\ 4 & 5 & 6 \end{bmatrix} \implies A^T = \begin{bmatrix} 1 & 4 \\ 2 & 5 \\ 3 & 6 \end{bmatrix} \]


3. 逆矩阵 (Inverse Matrix)

理解逆矩阵(Inverse Matrix)最直观的方式,就是把它看作是矩阵运算里的“后悔药”“还原键”

在普通的算术中,如果你乘以 \(5\),想要变回原样,你就乘以 \(5\) 的倒数 \(\frac{1}{5}\)。在矩阵世界里,逆矩阵 \(A^{-1}\) 扮演的就是这个“倒数”的角色。


1. 核心定义:什么是“还原”?

如果矩阵 \(A\) 将向量 \(\vec{x}\) 变换到了新位置 \(\vec{y}\)

\[A\vec{x} = \vec{y} \]

那么逆矩阵 \(A^{-1}\) 的作用就是把 \(\vec{y}\) 变回 \(\vec{x}\)

\[A^{-1}\vec{y} = \vec{x} \]

因此,矩阵与其逆矩阵相乘,结果是一个单位矩阵 \(I\)(相当于数字里的 \(1\)),意味着“什么都没改变”:

\[A \cdot A^{-1} = I \]


2. 物理意义:空间的“反向运动”

从空间变换的角度看,逆矩阵就是完全相反的动作

  • 如果矩阵 \(A\) 代表“顺时针旋转 90°”,那么 \(A^{-1}\) 就代表“逆时针旋转 90°”
  • 如果矩阵 \(A\) 代表“在 \(X\) 轴方向拉伸 2 倍”,那么 \(A^{-1}\) 就代表“在 \(X\) 轴方向压缩为 0.5 倍”

3. 为什么有的矩阵没有逆矩阵?(奇异矩阵)

并不是所有矩阵都有逆矩阵。就像在数字里 \(0\) 没有倒数一样,如果一个矩阵破坏了空间的信息,它就不可逆。

  • 降维打击: 想象你把一个 3D 的物体压成了一张 2D 的照片。因为信息丢失了,你无法仅凭照片完全还原出 3D 物体的每一个细节。
  • 行列式为 0: 如果一个矩阵的行列式 \(\det(A) = 0\),意味着它把空间压缩到了更低的维度(比如把平面压成了一条线)。这种情况下,由于“信息重叠”,我们找不到唯一的还原方法,所以逆矩阵不存在。

4. 逆矩阵的实际用途

A. 解线性方程组

这是逆矩阵最经典的应用。如果有方程组 \(A\mathbf{x} = \mathbf{b}\),只要 \(A\) 可逆,我们就能直接求出未知数:

\[\mathbf{x} = A^{-1}\mathbf{b} \]

这就像是把系数移项到等号另一边。

B. 计算机图形学的“回退”

在 3D 游戏或建模软件中,如果你移动了摄像机,系统需要计算从当前视角回到全局坐标系的变换,这时就会用到当前变换矩阵的逆矩阵。

C. 密码学

在某些矩阵加密算法(如 Hill Cipher)中,加密过程是乘以一个矩阵 \(A\),而解密过程就是乘以它的逆矩阵 \(A^{-1}\)


总结

  • 计算上: 它是矩阵的“倒数”。
  • 几何上: 它是变换的“反向操作”。
  • 直观上: 它是寻找“初始状态”的工具。

计算逆矩阵通常比乘法要复杂得多。为了让你看清“还原”的过程,我们用一个最简单的 2×2 矩阵作为示例(3×3 及以上的矩阵通常使用高斯消元法,过程较长)。


1. 2×2 矩阵求逆公式

对于矩阵 \(A = \begin{bmatrix} a & b \\ c & d \end{bmatrix}\),其逆矩阵 \(A^{-1}\) 的公式为:

\[A^{-1} = \frac{1}{ad - bc} \begin{bmatrix} d & -b \\ -c & a \end{bmatrix} \]

  • 分母 \(ad - bc\) 是矩阵的行列式 (\(\det(A)\))。如果它等于 0,则矩阵不可逆。
  • 右边的矩阵:主对角线元素(\(a, d\))互换,副对角线元素(\(b, c\))变号。

2. 具体计算示例

假设我们有一个变换矩阵 \(A\),它代表某种空间拉伸:

\[A = \begin{bmatrix} 4 & 7 \\ 2 & 6 \end{bmatrix} \]

第一步:计算行列式

\[\det(A) = (4 \times 6) - (7 \times 2) = 24 - 14 = 10 \]

因为 \(10 \neq 0\),所以逆矩阵存在。

第二步:应用公式
交换 4 和 6,给 7 和 2 加上负号:

\[A^{-1} = \frac{1}{10} \begin{bmatrix} 6 & -7 \\ -2 & 4 \end{bmatrix} = \begin{bmatrix} 0.6 & -0.7 \\ -0.2 & 0.4 \end{bmatrix} \]


3. 验证:它真的能“还原”吗?

如果我们让 \(A\)\(A^{-1}\) 相乘,结果应该等于单位矩阵 \(I = \begin{bmatrix} 1 & 0 \\ 0 & 1 \end{bmatrix}\)

\[A \cdot A^{-1} = \begin{bmatrix} 4 & 7 \\ 2 & 6 \end{bmatrix} \begin{bmatrix} 0.6 & -0.7 \\ -0.2 & 0.4 \end{bmatrix} \]

  • 左上角: \((4 \times 0.6) + (7 \times -0.2) = 2.4 - 1.4 = \mathbf{1}\)
  • 右上角: \((4 \times -0.7) + (7 \times 0.4) = -2.8 + 2.8 = \mathbf{0}\)
  • 左下角: \((2 \times 0.6) + (6 \times -0.2) = 1.2 - 1.2 = \mathbf{0}\)
  • 右下角: \((2 \times -0.7) + (6 \times 0.4) = -1.4 + 2.4 = \mathbf{1}\)

结果确实是 \(\begin{bmatrix} 1 & 0 \\ 0 & 1 \end{bmatrix}\)!这证明了 \(A^{-1}\) 能够完美撤销 \(A\) 所做的变换。


4. 为什么要学这个?(实际例子)

想象你在解这个方程组:

\[\begin{cases} 4x + 7y = 15 \\ 2x + 6y = 10 \end{cases} \]

写成矩阵形式就是 \(A\mathbf{x} = \mathbf{b}\)
以前你需要用消元法,现在你只需要把逆矩阵 \(A^{-1}\) 乘到结果上:

\[\begin{bmatrix} x \\ y \end{bmatrix} = \begin{bmatrix} 0.6 & -0.7 \\ -0.2 & 0.4 \end{bmatrix} \begin{bmatrix} 15 \\ 10 \end{bmatrix} = \begin{bmatrix} (9-7) \\ (-3+4) \end{bmatrix} = \begin{bmatrix} 2 \\ 1 \end{bmatrix} \]

直接解出 \(x=2, y=1\)


在 Milvus 中的意义: 主要用于白化(Whitening)处理。通过逆矩阵可以抵消数据的相关性,使特征分布变得“圆润”(各向同性),提升检索精度。

理论与数学含义

\(AB = BA = I\)(单位矩阵),则 \(B\)\(A\) 的逆,记作 \(A^{-1}\)

  • 数学含义: 逆矩阵代表了变换的回退。如果一个矩阵变换将向量拉伸了,逆矩阵就负责把它缩回去。
  • 约束: 只有方阵且行列式 \(\det(A) \neq 0\)(满秩)时,逆矩阵才存在。

计算示例 (2x2)

对于 \(A = \begin{bmatrix} a & b \\ c & d \end{bmatrix}\),其逆为 \(A^{-1} = \frac{1}{ad-bc} \begin{bmatrix} d & -b \\ -c & a \end{bmatrix}\)
\(A = \begin{bmatrix} 4 & 7 \\ 2 & 6 \end{bmatrix}\),行列式为 \(4 \times 6 - 7 \times 2 = 10\)

\[A^{-1} = \frac{1}{10} \begin{bmatrix} 6 & -7 \\ -2 & 4 \end{bmatrix} = \begin{bmatrix} 0.6 & -0.7 \\ -0.2 & 0.4 \end{bmatrix} \]


4. 正交矩阵 (Orthogonal Matrix)

正交矩阵(Orthogonal Matrix)是矩阵世界里的“一等公民”。如果说普通矩阵可能会把空间拉伸、挤压得面目全非,那么正交矩阵就像是一个刚性的框架,它在变换空间时,绝对不会破坏形状和大小。


1. 直观理解:什么是“正交”?

“正交”在数学上就是垂直的意思。一个正交矩阵 \(Q\) 具有两个神奇的几何特性:

  1. 列向量之间互相垂直:任意两列的点积为 0。
  2. 每个列向量的长度都是 1:即单位向量。

2. 数学定义与迷人特性

一个 \(n \times n\) 的实数矩阵 \(Q\) 如果满足以下条件,就是正交矩阵:

\[Q^T Q = I \quad \text{或者} \quad Q^T = Q^{-1} \]

这意味着:正交矩阵的转置就是它的逆矩阵。

  • 在普通矩阵里,求逆矩阵(求“后悔药”)非常麻烦,需要大量计算。
  • 在正交矩阵里,你只需要把矩阵“横竖翻转”一下(转置),就得到了它的逆!

3. 几何意义:保持“原汁原味”

正交矩阵代表的变换(旋转或镜像)具有等距性(Isometry)

  • 保长度:向量经过正交变换后,长度不变。
  • 保角度:两个向量之间的角度在变换后依然保持不变。

形象比喻
想象你手里拿着一个魔方。你无论怎么旋转它(正交变换),魔方的边长不会变,每一面的直角也还是直角。你只是改变了它的朝向,没有把它捏扁或拉长。


4. 2×2 示例:旋转矩阵

最经典的正交矩阵就是旋转矩阵。假设我们要将空间逆时针旋转 \(\theta\) 角度:

\[Q = \begin{bmatrix} \cos\theta & -\sin\theta \\ \sin\theta & \cos\theta \end{bmatrix} \]

验证:
如果 \(\theta = 90^\circ\),则 \(\cos 90^\circ = 0, \sin 90^\circ = 1\)

\[Q = \begin{bmatrix} 0 & -1 \\ 1 & 0 \end{bmatrix} \]

  1. 列向量垂直\([0, 1] \cdot [-1, 0] = (0 \times -1) + (1 \times 0) = 0\)。(满足)
  2. 长度为 1\(\sqrt{0^2 + 1^2} = 1\)。(满足)
  3. 转置等于逆

    \[Q^T = \begin{bmatrix} 0 & 1 \\ -1 & 0 \end{bmatrix} \]

    你可以试着乘一下,\(Q^T Q\) 确实等于单位矩阵 \(I\)

5. 为什么要研究它?

正交矩阵在工程和科学中极度受欢迎,原因有二:

  • 稳定性:在数值计算中,正交矩阵不会放大误差,因为它们不改变向量的模长。
  • 计算简便:转置即求逆,这在处理大规模数据(如图像压缩、PCA 主成分分析)时能节省海量的计算资源。

总结一句话:正交矩阵是只旋转、不形变的“刚性变换”。
为了让你直观感受正交矩阵的特性,我们来看一个具体的 \(3 \times 3\) 旋转矩阵示例。旋转操作是正交矩阵最典型的应用,因为它只改变方向,不改变物体的形状和大小。


1. 构造一个正交矩阵 \(Q\)

假设我们要将三维空间绕 \(Z\) 轴逆时针旋转 \(90^\circ\)。根据旋转矩阵公式,得到的矩阵如下:

\[Q = \begin{bmatrix} 0 & -1 & 0 \\ 1 & 0 & 0 \\ 0 & 0 & 1 \end{bmatrix} \]


2. 验证:为什么它是正交矩阵?

要证明一个矩阵是正交的,最简单的方法是检查它的列向量。

  • 列向量 \(v_1\)\([0, 1, 0]^T\)
  • 列向量 \(v_2\)\([-1, 0, 0]^T\)
  • 列向量 \(v_3\)\([0, 0, 1]^T\)

检查点 A:每个列向量的长度是否为 1?

  • \(|v_1| = \sqrt{0^2 + 1^2 + 0^2} = 1\)
  • \(|v_2| = \sqrt{(-1)^2 + 0^2 + 0^2} = 1\)
  • \(|v_3| = \sqrt{0^2 + 0^2 + 1^2} = 1\)
    (全部满足,说明没有拉伸变换)

检查点 B:列向量之间是否两两垂直(点积为 0)?

  • \(v_1 \cdot v_2 = (0 \times -1) + (1 \times 0) + (0 \times 0) = \mathbf{0}\)
  • \(v_1 \cdot v_3 = (0 \times 0) + (1 \times 0) + (0 \times 1) = \mathbf{0}\)
  • \(v_2 \cdot v_3 = (-1 \times 0) + (0 \times 0) + (0 \times 1) = \mathbf{0}\)
    (全部满足,说明没有剪切/挤压变换)

3. 计算:转置即逆矩阵 (\(Q^T = Q^{-1}\))

这是正交矩阵最强大的计算特性。

第一步:求转置 \(Q^T\)(行变列)

\[Q^T = \begin{bmatrix} 0 & 1 & 0 \\ -1 & 0 & 0 \\ 0 & 0 & 1 \end{bmatrix} \]

第二步:验证 \(Q^T \cdot Q = I\)
我们将两者相乘:

\[\begin{bmatrix} 0 & 1 & 0 \\ -1 & 0 & 0 \\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} 0 & -1 & 0 \\ 1 & 0 & 0 \\ 0 & 0 & 1 \end{bmatrix} = \begin{bmatrix} (0+1+0) & (0+0+0) & (0+0+0) \\ (0+0+0) & (1+0+0) & (0+0+0) \\ (0+0+0) & (0+0+0) & (0+0+1) \end{bmatrix} = \begin{bmatrix} 1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \end{bmatrix} \]

结果完美回到了单位矩阵 \(I\)


4. 总结:这个计算说明了什么?

  1. 极简求逆:如果你在编程或做物理模拟,需要把一个旋转过的物体“转回来”,你不需要调用复杂的矩阵求逆算法,直接把矩阵转置一下就能用,速度极快且没有舍入误差。
  2. 能量守恒:在物理学中,正交变换意味着坐标系的变换不改变动能或位势的标量值(因为长度保持不变)。

在实际应用(比如 3D 渲染或数据降维)中,我们经常会遇到一组乱七八糟的向量,需要把它们规范化成一组“互相垂直且长度为 1”的标准基。这个标准过程叫做 施密特正交化 (Gram-Schmidt Process)


施密特正交化:从“乱”到“正”

假设我们有两个基向量 \(v_1, v_2\),它们并不垂直。我们要把它们变成正交基 \(u_1, u_2\)

1. 找第一个方向(标准化)

直接让第一个新向量 \(u_1\) 等于 \(v_1\)(通常还会除以长度使其变为单位向量)。

\[u_1 = v_1 \]

2. 找第二个垂直方向(投影与剔除)

这是最关键的一步。我们从 \(v_2\) 中减去它在 \(u_1\) 方向上的投影。剩下的部分就一定和 \(u_1\) 垂直了。

\[u_2 = v_2 - \text{proj}_{u_1}(v_2) \]


计算示例:2×2 矩阵正交化

假设我们有一个普通矩阵,它的列向量互不垂直:

\[A = \begin{bmatrix} 1 & 1 \\ 1 & 0 \end{bmatrix} \quad \implies v_1 = \begin{bmatrix} 1 \\ 1 \end{bmatrix}, v_2 = \begin{bmatrix} 1 \\ 0 \end{bmatrix} \]

第一步:处理 \(v_1\)

我们直接取 \(v_1\)。为了最后得到正交矩阵,我们需要把它单位化(长度变为 1)。
\(v_1\) 的长度是 \(\sqrt{1^2 + 1^2} = \sqrt{2}\)

\[q_1 = \frac{v_1}{|v_1|} = \begin{bmatrix} 1/\sqrt{2} \\ 1/\sqrt{2} \end{bmatrix} \]

第二步:处理 \(v_2\)

先找到 \(v_2\)\(q_1\) 方向上的分量,然后减掉它:

  1. 点积\(v_2 \cdot q_1 = (1 \times \frac{1}{\sqrt{2}}) + (0 \times \frac{1}{\sqrt{2}}) = \frac{1}{\sqrt{2}}\)
  2. 减去投影

    \[u_2 = v_2 - (v_2 \cdot q_1)q_1 = \begin{bmatrix} 1 \\ 0 \end{bmatrix} - \frac{1}{\sqrt{2}} \begin{bmatrix} 1/\sqrt{2} \\ 1/\sqrt{2} \end{bmatrix} = \begin{bmatrix} 1 \\ 0 \end{bmatrix} - \begin{bmatrix} 0.5 \\ 0.5 \end{bmatrix} = \begin{bmatrix} 0.5 \\ -0.5 \end{bmatrix} \]

  3. 单位化 \(u_2\)\(u_2\) 的长度是 \(\sqrt{0.5^2 + (-0.5)^2} = \sqrt{0.5} = \frac{1}{\sqrt{2}}\)

    \[q_2 = \frac{u_2}{|u_2|} = \begin{bmatrix} 0.5 \times \sqrt{2} \\ -0.5 \times \sqrt{2} \end{bmatrix} = \begin{bmatrix} 1/\sqrt{2} \\ -1/\sqrt{2} \end{bmatrix} \]

最终得到的正交矩阵 \(Q\)

\[Q = \begin{bmatrix} 1/\sqrt{2} & 1/\sqrt{2} \\ 1/\sqrt{2} & -1/\sqrt{2} \end{bmatrix} \]


验证一下?

  • 垂直吗? \((1/\sqrt{2} \times 1/\sqrt{2}) + (1/\sqrt{2} \times -1/\sqrt{2}) = 0.5 - 0.5 = 0\)垂直!
  • 长度是 1 吗? \(\sqrt{0.5 + 0.5} = 1\)满足!

总结

正交化就像是给空间里的向量“做手术”:

  1. 对齐:选定一个参考轴。
  2. 切除:把其他向量中不垂直的部分全部切掉。
  3. 拉伸:把所有向量都修剪成长度为 1。

这种方法在计算机视觉中非常重要,比如当我们根据相机拍摄的画面重建 3D 坐标系时,第一步往往就是对估算出的轴进行正交化处理。


旋转矩阵(Rotation Matrix) 是线性代数中最具“动态感”的工具之一。它是一类特殊的正交矩阵,专门用于在欧几里得空间中描述物体的旋转。


1. 旋转矩阵是什么?

在数学定义上,旋转矩阵 \(R\) 必须同时满足以下两个条件:

  1. 它是正交矩阵\(R^T R = I\)(保持长度和角度不变)。
  2. 它的行列式等于 1\(\det(R) = 1\)
    • 注:如果行列式等于 -1,那它就包含了“镜像反射”,而不是纯粹的旋转。

2. 如何计算(公式)

二维空间(2D)

在平面上,将一个点逆时针旋转 \(\theta\) 角度的矩阵为:

\[R(\theta) = \begin{bmatrix} \cos\theta & -\sin\theta \\ \sin\theta & \cos\theta \end{bmatrix} \]

三维空间(3D)

在 3D 空间中,旋转是绕着某个“轴”进行的。最基本的是绕坐标轴旋转:

  • 绕 Z 轴旋转:

    \[R_z(\theta) = \begin{bmatrix} \cos\theta & -\sin\theta & 0 \\ \sin\theta & \cos\theta & 0 \\ 0 & 0 & 1 \end{bmatrix} \]

  • 绕 Y 轴旋转:

    \[R_y(\theta) = \begin{bmatrix} \cos\theta & 0 & \sin\theta \\ 0 & 1 & 0 \\ -\sin\theta & 0 & \cos\theta \end{bmatrix} \]

  • 绕 X 轴旋转:

    \[R_x(\theta) = \begin{bmatrix} 1 & 0 & 0 \\ 0 & \cos\theta & -\sin\theta \\ 0 & \sin\theta & \cos\theta \end{bmatrix} \]


3. 计算示例

场景:将向量 \(\vec{v} = \begin{bmatrix} 1 \\ 0 \end{bmatrix}\)(指向正右方)逆时针旋转 \(90^\circ\)

  1. 代入角度\(\cos 90^\circ = 0\), \(\sin 90^\circ = 1\)
  2. 构建矩阵

    \[R = \begin{bmatrix} 0 & -1 \\ 1 & 0 \end{bmatrix} \]

  3. 矩阵乘法

    \[R\vec{v} = \begin{bmatrix} 0 & -1 \\ 1 & 0 \end{bmatrix} \begin{bmatrix} 1 \\ 0 \end{bmatrix} = \begin{bmatrix} (0 \times 1 + -1 \times 0) \\ (1 \times 1 + 0 \times 0) \end{bmatrix} = \begin{bmatrix} 0 \\ 1 \end{bmatrix} \]

结果:向量变为了 \(\begin{bmatrix} 0 \\ 1 \end{bmatrix}\)(指向正上方),旋转成功。


4. 旋转矩阵的物理意义

A. 坐标系的重新定义

你可以把旋转矩阵的列向量看作是“旋转后”的新坐标轴在旧坐标系中的位置。
例如在上面的 \(90^\circ\) 旋转中:

  • 第一列 \(\begin{bmatrix} 0 \\ 1 \end{bmatrix}\) 是原来的 \(x\) 轴转到了 \(y\) 轴的位置。
  • 第二列 \(\begin{bmatrix} -1 \\ 0 \end{bmatrix}\) 是原来的 \(y\) 轴转到了负 \(x\) 轴的位置。

B. 保持“刚性”

旋转矩阵之所以重要,是因为它是一种刚体变换(Rigid Transformation)

  • 它不会拉伸物体(保长度)。
  • 它不会扭曲物体(保角度)。
  • 这使得它在机器人学(机械臂转动)、游戏开发(人物转身)和航空航天(飞机姿态控制)中不可或缺。

C. 链式反应(复合旋转)

旋转矩阵可以通过相乘来组合。如果你先绕 X 轴转,再绕 Y 轴转,总的变换就是 \(R_{total} = R_y R_x\)

  • 注意:矩阵乘法不满足交换律,所以先绕 X 再绕 Y,跟先绕 Y 再绕 X 的结果通常是不同的!

5. 局限性与进阶

虽然旋转矩阵很直观,但在处理复杂的 3D 旋转时,它会有“万向节死锁(Gimbal Lock)”的问题,且计算量较大。因此,在高端图形学和无人机控制中,人们往往会使用四元数(Quaternions)来代替旋转矩阵。

在 Milvus 中的意义: 极其重要。乘积量化 (PQ) 之前的 OPQ (Optimized Product Quantization) 核心就是寻找一个最优的正交矩阵。

理论与数学含义

如果 \(Q^T Q = I\)(即 \(Q^T = Q^{-1}\)),则 \(Q\) 是正交矩阵。

  • 数学含义: 正交矩阵代表的是旋转或镜像变换
  • 关键特性: 正交变换不改变向量的长度,也不改变向量之间的夹角(即保持欧氏距离不变)。这在向量降维和量化中非常关键,因为它保证了数据变换后相似性不丢失。

计算示例

\[Q = \begin{bmatrix} \cos\theta & -\sin\theta \\ \sin\theta & \cos\theta \end{bmatrix} \]

\(\theta = 90^\circ\)

\[Q = \begin{bmatrix} 0 & -1 \\ 1 & 0 \end{bmatrix} \]

验证 \(Q^T Q\)

\[\begin{bmatrix} 0 & 1 \\ -1 & 0 \end{bmatrix} \begin{bmatrix} 0 & -1 \\ 1 & 0 \end{bmatrix} = \begin{bmatrix} 1 & 0 \\ 0 & 1 \end{bmatrix} = I \]


深度解析:这些理论如何串联?

在 Milvus 处理数据的全生命周期中:

  1. 特征处理: 使用逆矩阵进行白化,消除原始特征中维度间的冗余相关性。

  2. 空间旋转: 使用正交矩阵对向量空间进行旋转(OPQ),使得向量分段后每一段的能量更加均匀,从而减少量化误差。

  3. 计算加速: 利用矩阵乘法的并行特性,配合 SIMD 指令集(如 AVX512),在 CPU/GPU 上实现每秒数百万次的相似度计算。

掌握了这些,你就能理解为什么 Milvus 在某些配置下召回率更高,或者为什么特定的索引类型(如 IVF_PQ)需要进行一次长期的“训练(Training)”过程——那个训练过程本质上就是在通过迭代寻找最优的聚类中心矩阵旋转矩阵


协方差

理解协方差(Covariance),最简单的方法是把它看作是“两个变量是否步调一致”的度量。

如果说方差(Variance)是在描述一个变量自己“抖动”得有多厉害,那么协方差就是在描述两个变量“一起抖动”的默契程度。


1. 直观理解:三种关系

我们可以通过两个变量 \(X\)\(Y\) 的变化趋势来判断协方差的正负:

  • 正协方差(Positive)\(X\) 变大时,\(Y\) 也倾向于变大。它们像是一对好伙伴,同向变化(如:身高与体重)。
  • 负协方差(Negative)\(X\) 变大时,\(Y\) 反而变小。它们像是跷跷板,反向变化(如:运动时间与体脂率)。
  • 零协方差(Zero)\(X\) 的变化跟 \(Y\) 完全没关系。它们是相互独立的(如:你的身高与今天的股价)。

[Image of scatter plots showing positive, negative, and zero covariance]


2. 计算公式

对于两个随机变量 \(X\)\(Y\),它们的协方差公式为:

\[\text{Cov}(X, Y) = \frac{\sum_{i=1}^{n} (X_i - \bar{X})(Y_i - \bar{Y})}{n - 1} \]

其中:

  • \(X_i, Y_i\) 是具体的样本观测值。
  • \(\bar{X}, \bar{Y}\) 是它们的平均值。
  • \(n - 1\) 是样本容量(统计学中常用 \(n-1\) 来获得无偏估计)。

3. 计算示例

假设我们有两组数据,代表两个特征:

  • 特征 X: \([1, 3, 5]\)
  • 特征 Y: \([2, 4, 9]\)

第一步:计算平均值

  • \(\bar{X} = (1+3+5)/3 = 3\)
  • \(\bar{Y} = (2+4+9)/3 = 5\)

第二步:计算每个样本的离差乘积

  1. 第一个点:\((1-3) \times (2-5) = (-2) \times (-3) = \mathbf{6}\)
  2. 第二个点:\((3-3) \times (4-5) = 0 \times (-1) = \mathbf{0}\)
  3. 第三个点:\((5-3) \times (9-5) = 2 \times 4 = \mathbf{8}\)

第三步:求和并平均

\[\text{Cov}(X, Y) = \frac{6 + 0 + 8}{3 - 1} = \frac{14}{2} = \mathbf{7} \]

结论:协方差为 7(正值),说明这两个特征具有明显的正相关性。


4. 协方差矩阵(Covariance Matrix)

当你处理白化或检索任务时,通常面对的是多个特征,这时就需要协方差矩阵
如果数据有 \(d\) 个特征,协方差矩阵是一个 \(d \times d\) 的对称矩阵:

  • 对角线:是每个特征自己的方差
  • 非对角线:是特征之间的协方差

5. 协方差的局限与白化的联系

协方差的一个“坑”在于它受量纲(单位)影响很大。如果 \(X\) 是以“米”为单位,协方差可能是 \(7\);如果改成“厘米”,协方差会瞬间变成 \(700\)

这就解释了你之前提到的白化处理

  1. 协方差告诉我们数据是“斜着的椭圆”(特征间有相关性)。
  2. 我们通过计算协方差矩阵的逆矩阵(或其变体),可以找到一个变换,把这些相互纠缠的特征“拆解”开。
  3. 最终让协方差矩阵变成单位矩阵 \(I\)(对角线全是 1,非对角线全是 0),这就是最完美的白化状态。

在计算机视觉(如图像检索)和深度学习中,白化(Whitening) 的本质就是通过线性变换,将原本“椭圆状”分布的数据分布变成“正圆状”分布。

1. 深度理解:什么是白化?

想象你有一堆数据点,它们在坐标系中呈斜着的长椭圆分布。这意味着特征之间存在相关性(比如:身高越高的人往往体重也越重,这两个维度信息冗余了)。

白化的两个核心目标:

  1. 去相关(Decorrelation):让不同特征之间的协方差变为 0(把椭圆扶正)。
  2. 归一化(Standardization):让每个特征的方差都变为 1(把长短轴拉成一样长)。

为什么要变“圆润”?
在向量检索中,我们常用欧氏距离。如果数据是长椭圆的,某个维度波动一点点就会对距离产生巨大影响。白化后,每个维度对距离的贡献是平等的,特征的表达就更加客观。


2. 白化的数学原理:逆矩阵的介入

白化最常用的手段是 ZCA 白化PCA 白化。其核心逻辑如下:

假设原始数据的协方差矩阵为 \(\Sigma\)
我们想要找到一个变换矩阵 \(W\),使得变换后的数据协方差矩阵变为单位矩阵 \(I\)
数学证明得出,这个变换矩阵 \(W\) 往往包含协方差矩阵特征分解后的逆平方根

\[W = \Sigma^{-1/2} \]

这里“逆”矩阵的意义就在于:利用数据自身的统计相关性结构(\(\Sigma\)),生成一个反向的算子,把相关性完全抵消掉。


3. 计算示例(简易版)

假设我们有 2 个特征,其协方差矩阵 \(\Sigma\) 如下(表示特征 1 和特征 2 强正相关):

\[\Sigma = \begin{bmatrix} 4 & 2 \\ 2 & 4 \end{bmatrix} \]

第一步:特征分解(寻找主成分方向)

通过计算,我们得到特征值 \(\lambda\) 和特征向量矩阵 \(U\)

  • \(\lambda_1 = 6, \lambda_2 = 2\)
  • \(U\) 是将空间旋转到椭圆长短轴方向的正交矩阵。

第二步:构造白化矩阵

我们需要在长轴方向缩减 \(\sqrt{6}\) 倍,在短轴方向缩减 \(\sqrt{2}\) 倍。
白化矩阵 \(W = U \Lambda^{-1/2} U^T\)
其中 \(\Lambda^{-1/2} = \begin{bmatrix} 1/\sqrt{6} & 0 \\ 0 & 1/\sqrt{2} \end{bmatrix}\)

第三步:应用变换

对于任何一个原始数据向量 \(\mathbf{x}\),变换后的向量 \(\mathbf{x}_{white} = W\mathbf{x}\)

结果:
变换后的数据,其协方差矩阵会变成:

\[\Sigma_{new} = W \Sigma W^T = I = \begin{bmatrix} 1 & 0 \\ 0 & 1 \end{bmatrix} \]

原本斜着的、长短不一的分布,现在变成了以原点为中心、半径为 1 的正圆


4. 在检索精度提升中的意义

  • 消除冗余:如果特征 A 和 B 高度相关,不白化时检索系统会“双倍计分”,导致权重偏移。白化后它们独立贡献。
  • 抑制噪声:白化过程中通常会压缩特征值极小的维度(那些通常是噪声),增强信号的信噪比。
  • 各向同性(Isotropic):使余弦相似度或欧氏距离在所有方向上都具有相同的物理意义。

白化就像是给数据做了一次“各行各业的标准化”: 不管你原始数据的量级和相关性如何,统统拉到同一个标准圆里谈相似性。


量化

乘积量化 (Product Quantization, PQ) 是 Milvus 等向量数据库能够处理十亿级数据的“黑科技”。它的核心思想是:与其完整存储一个高维大向量,不如将其切碎,并用“代号”来表示每一块。

这就好比将一张高清大图(高维向量)压缩成极小的缩略图,但在检索时,依然能大概分辨出图里画的是什么。


1. 核心理论:分而治之

PQ 的过程可以分为四个步骤:切分、聚类、编码、查询

A. 向量切分 (Sub-vector Splitting)

假设原始向量维度是 \(D=128\)。我们将其水平切分为 \(m=8\) 个子向量,每个子向量的维度为 \(D/m = 16\)

B. 子空间聚类 (Sub-space Clustering)

对每一个子空间,利用 K-Means 算法训练出一套“码本”(Codebook)。

  • 每个子空间通常聚类出 \(k=256\) 个中心点(Centroids)。
  • 为什么是 256?因为这样每个中心点的索引只需要 1 Byte (8 bits) 就能表示。

C. 编码压缩 (Encoding)

对于任何一个原始向量,我们看它的每一个子向量距离该子空间里的哪个中心点最近,就用该中心点的“编号”来代替。

  • 压缩比惊人: 一个 128 维的浮点数向量(\(128 \times 4\) 字节 = 512 字节),压缩后变成了 8 个编号(\(8 \times 1\) 字节 = 8 字节)。压缩率达 64 倍。

2. 计算示例:从 128 维到 8 字节

为了直观,我们简化模型:

  • 原始向量: \(V = [0.1, 0.2, 0.9, 0.8]\) (4维)
  • 切分参数: \(m=2\)(切分为两个 2 维子向量)
    • 子向量 1: \([0.1, 0.2]\)
    • 子向量 2: \([0.9, 0.8]\)

步骤:

  1. 查询码本: 假设我们预先训练好了码本:
    • 子空间 1 的中心点: ID 0: [0.11, 0.21], ID 1: [0.5, 0.5]
    • 子空间 2 的中心点: ID 0: [0.1, 0.1], ID 1: [0.89, 0.81]
  2. 查找最近邻:
    • 子向量 1 \([0.1, 0.2]\)ID 0 最近。
    • 子向量 2 \([0.9, 0.8]\)ID 1 最近。
  3. 最终存储: 原始向量 \(V\) 被存储为 [0, 1]

3. 实际应用场景:非对称距离计算 (ADC)

在 Milvus 中,当你发起查询(Query)时,PQ 是如何工作的?它并不需要把库里的数据“解压”还原。

场景:十亿级图像特征搜索

假设你有一张图片,提取出特征向量 \(Q\)

  1. 计算距离表 (Lookup Table): 计算 \(Q\) 的各个子段与各个码本中心点的距离,生成一张 \(m \times k\) 的小表格。
  2. 查表求和: 当扫描库中的压缩向量(如 [0, 1])时,只需去表里查:第 1 段 ID 为 0 的距离 + 第 2 段 ID 为 1 的距离。

这种“查表+加法”的操作比直接计算 128 维欧氏距离快了几个数量级!


4. 深刻解析:数学与工程的权衡

  • 精度损失: PQ 是一种有损压缩。由于用中心点代替了实际点,计算出的距离是近似值。这就是为什么它被称为 ANN (Approximate Nearest Neighbor)
  • 内存优化: 向量数据库最大的瓶颈通常是内存。PQ 让单机能够承载的数据量提升了数十倍。
  • 计算优势: 利用 ADC (Asymmetric Distance Computation),计算过程中不需要反量化,极大压低了 CPU 负担。

深度思考:

PQ 的弱点在于它假设子空间之间是独立的。如果你的向量各维度之间相关性极强(例如前 10 维和后 10 维高度相关),简单的 PQ 效果会很差。这时候,就需要用到我们在前一章提到的正交矩阵进行 OPQ(优化乘积量化) 旋转,先让维度解耦,再切分。


OPQ (Optimized Product Quantization) 是对 PQ 的进阶优化。如果说 PQ 是简单的“切分与压缩”,那么 OPQ 就是在压缩之前先进行一次“空间整形”,以确保压缩后的精度损失降到最低。


1. 为什么需要 OPQ?(痛点分析)

PQ 有一个致命的假设:向量的不同维度之间是相互独立的,且能量分布是均匀的。

但在现实应用(如图像特征、语义向量)中,这几乎不可能:

  • 相关性: 维度 1 和维度 10 可能高度相关。
  • 能量不均: 某些维度的信息量(方差)很大,某些维度很小。

PQ 的尴尬: 如果直接切分,可能会把高度相关的两个维度切分到不同的子空间,导致量化器无法捕捉这种相关性;或者某个子空间信息量爆炸,而另一个子空间全是一堆无意义的零,导致严重的量化误差。


2. OPQ 的核心理论:旋转与对齐

OPQ 在 PQ 之前增加了一个正交矩阵 \(R\)。它的目标是寻找一个最佳的旋转方式:

  1. 解耦相关性: 通过旋转,让维度之间的相关性降低(类似于 PCA 的效果)。
  2. 能量均衡: 让每个子空间的方差(信息量)尽可能相等。

其数学目标函数为:

\[\min_{R, \mathcal{C}} \sum_{x} \| Rx - q(Rx) \|^2 \]

其中 \(R\) 必须是正交矩阵(保持原始距离不变),\(q\) 是量化函数。


3. 计算示例:空间旋转的效果

为了简化理解,我们看一个 2 维向量的例子。

场景:

假设原始数据分布在一条直线 \(y=x\) 上(维度强相关):

  • 向量 \(V_1 = [1, 1]\), \(V_2 = [2, 2]\)
  • 如果我们把 \(V\) 切分成两个 1 维子空间:
    • PQ 会把维度 1 聚类,维度 2 聚类。由于两维都在变,量化器需要同时在两个子空间耗费资源。

OPQ 的处理:

  1. 寻找旋转矩阵 \(R\) 发现数据都在 \(45^\circ\) 方向。
  2. 执行旋转: 构造旋转矩阵(正交矩阵):

    \[R = \begin{bmatrix} \cos(-45^\circ) & -\sin(-45^\circ) \\ \sin(-45^\circ) & \cos(-45^\circ) \end{bmatrix} = \begin{bmatrix} 0.707 & 0.707 \\ -0.707 & 0.707 \end{bmatrix} \]

  3. 变换结果:
    • \(RV_1 = \begin{bmatrix} 0.707 & 0.707 \\ -0.707 & 0.707 \end{bmatrix} \begin{bmatrix} 1 \\ 1 \end{bmatrix} = \begin{bmatrix} 1.414 \\ 0 \end{bmatrix}\)
    • \(RV_2 = \begin{bmatrix} 0.707 & 0.707 \\ -0.707 & 0.707 \end{bmatrix} \begin{bmatrix} 2 \\ 2 \end{bmatrix} = \begin{bmatrix} 2.828 \\ 0 \end{bmatrix}\)

效果分析:

旋转后,第二维全部变成了 0
在量化时,我们只需要给第一维分配全部的比特(Bit),而第二维不需要分配。这就极大地降低了量化误差。


4. 实际应用场景:大规模语义搜索

在 Milvus 中,OPQ 常用于 IVF_PQ 索引的增强版:

  • 场景描述: 处理由 BERT 或 CLIP 模型生成的 512 维或 768 维稠密向量。
  • 痛点: 这些模型的输出向量通常在某些维度上具有极高的冗余。
  • OPQ 的作用:
    1. 训练阶段: 在建立索引时,Milvus 会采样一部分数据,通过迭代算法(如非参数化 OPQ)训练出矩阵 \(R\) 和码本。
    2. 存储阶段: 所有向量先乘以 \(R\),再进行 PQ 编码存储。
    3. 查询阶段: 查询向量也先乘以 \(R\),然后利用 ADC (非对称距离计算) 在量化空间检索。

5. 深刻总结

特性 PQ (乘积量化) OPQ (优化乘积量化)
空间处理 直接切分 先旋转,再切分
计算复杂度 较低 略高(多了一次矩阵乘法)
检索精度 一般 显著高于 PQ,尤其在维度相关时
核心数学 K-Means 正交矩阵 + 迭代优化

一句话理解: PQ 是在现有的格子里填色,OPQ 是先旋转格子,让格子对齐颜料的形状,再填色。


HNSW

要透彻理解 HNSW (Hierarchical Navigable Small World),可以将其想象成一个“高维空间的交通网络”。它巧妙地结合了概率图论与经典数据结构,解决了在高维空间中寻找最近邻的“维度灾难”问题。


1. HNSW 的设计原理:双重理论支柱

HNSW 的成功建立在两个核心概念之上:跳表(Skip List)可导航小世界图(Navigable Small World, NSW)

A. 结构设计:分层跳表思想

在普通的有序链表中查找元素是 \(O(N)\)。跳表通过增加“索引层”,让搜索可以跳跃式前进,复杂度降为 \(O(\log N)\)
HNSW 将这一思想引入图结构:

  • 第 0 层(Bottom Layer): 存放所有数据点,连接最致密。
  • 上层(Higher Layers): 按概率抽样保留少量节点。层数越高,节点越稀疏。
  • 数学约束: 每一个节点被抽样到第 \(l\) 层的概率遵循指数分布,确保了层级结构的稳定性。

B. 连接设计:小世界网络

在每一层内部,节点之间通过 NSW 算法 连接。

  • 贪心搜索: 从一个起始点开始,检查其邻居,移动到离目标最近的邻居,重复此过程,直到找不到更近的点。
  • 局部邻居 M: 每个节点最多连接 \(M\) 个邻居。为了保证“小世界”特性,算法在插入时会选择那些能“覆盖”更多方向的邻居,而不仅仅是最近的邻居。

2. 计算示例:搜索一个向量

假设我们有一个 2 层结构的 HNSW 索引,我们要查询向量 \(Q\)

第一步:顶层切入 (Layer 1)

  1. 从预定义的全局入口点 (Enter Point, EP) 开始。
  2. 计算 \(Q\)\(EP\) 及其在 Layer 1 的所有邻居的距离。
  3. 贪心跳转: 发现邻居 \(A\)\(Q\) 更近,跳转到 \(A\)
  4. \(A\) 的邻居中找不到比 \(A\) 更近的点。
  5. 下沉:\(A\) 为入口,进入 Layer 0。

第二步:底层精搜 (Layer 0)

  1. 此时我们手里的“当前最近点”是 \(A\)
  2. 计算 \(A\) 在 Layer 0 的所有邻居(连接更密集)与 \(Q\) 的距离。
  3. 多点探索: 此时算法会维护一个大小为 \(efSearch\) 的动态列表(候选池)。
    • 即使点 \(B\) 暂时不是最近,但它可能通向更近的点,也会被放入池中。
  4. 最终从池中选出距离 \(Q\) 最近的 \(K\) 个点作为结果。

3. 数学含义:为什么它比暴力计算快?

  • 暴力计算 (Flat Index): 需要计算 \(Q\) 与库中 \(N\) 个向量的距离,复杂度 \(O(N \cdot D)\)
  • HNSW 搜索:
    • 在每一层,由于“小世界”特性,我们只需要计算极少数邻居的距离。
    • 总计算量大约为 \(\text{常数} \times \log(N) \times D\)
    • 示例: 在 100 万个 128 维向量中检索,暴力计算需要 100 万次距离运算;HNSW 可能只需要不到 1000 次。

4. 关键参数的工程数学含义

在 Milvus 中配置 HNSW 时,理解这几个参数是“精通”的标志:

参数 数学定义 实际影响
M 每个节点的出度(邻居数) 内存杀手\(M\) 越大,索引越大,但路径越多,召回率越高。通常取 16~64。
efConstruction 构图时的探索宽度 决定了建索引的质量。越大,图的连接越科学,但建索引越慢。
efSearch 搜索时的探索宽度 性能开关。搜索时,增大它能提升召回率,但会增加查询耗时。

5. 深刻解析:HNSW 的“启发式”邻居选择

HNSW 不仅仅是选最近的 \(M\) 个点作为邻居。它采用了一种启发式算法 (Heuristic Strategy)
如果一个候选点 \(P\) 虽然离目标点比较近,但它已经在现有邻居 \(N\) 的“阴影”下了(即 \(dist(P, N) < dist(P, Target)\)),那么 HNSW 可能会放弃连接 \(P\)

数学含义: 这样做是为了让邻居尽可能向空间的不同方向辐射,而不是扎堆在一起。这保证了搜索时能快速穿越空间,而不至于陷入局部的“泥潭”。


总结

HNSW 是“以空间换时间”的极致体现。它通过复杂的构图算法,在内存中维护了一个高度组织化的拓扑结构。


DiskANN

DiskANN 是由微软研究院提出的一种针对大规模向量搜索(OOD, Out-of-Memory)设计的算法。它的核心目标是在保证搜索精度和延迟的前提下,让索引能够存储在 SSD 上,从而支持在单台机器上检索数十亿规模的数据集。


1. DiskANN 的核心设计原理

传统的 HNSW 算法虽然快,但由于其高度随机的内存访问特性,索引必须全量存放在内存中,成本极高。DiskANN 通过以下三个支柱解决了这个问题:

A. Vamana 图索引

Vamana 是 DiskANN 核心的图结构。相比于 HNSW 的多层结构,Vamana 是单层图

  • 长程边(Long-range edges): 在构图过程中,Vamana 会刻意引入长程边。这使得搜索时可以像“小世界网络”一样,快速从起始点跳跃到目标区域附近。
  • 高度连通性: 即使是 SSD 上的节点,也能通过少量的随机读取(Random I/O)快速收敛。

B. 内存与磁盘的协同(PQ 压缩)

  • 内存: 存储原始向量的压缩版(通常使用 PQ,Product Quantization)。用于在搜索时快速计算估算的距离,过滤候选集。
  • 磁盘: 存储完整的原始向量Vamana 图结构。用于在搜索的最后阶段重新计算精确距离(Re-ranking)。

为了减少磁盘 I/O 次数,DiskANN 不采用逐个节点的深度优先搜索,而是采用 Beam Search

  1. 维护一个大小为 \(L\) 的候选队列。
  2. 每一轮从队列中选出未访问过的、离查询点最近的 \(W\) 个点(Beam Width)。
  3. 合并 I/O: 一次性从磁盘读取这 \(W\) 个点的所有邻居。这样可以将多次小规模读取合并,充分利用 SSD 的带宽。

2. 计算示例

假设我们要在二维空间中寻找与查询点 \(Q\) 最近的向量。

场景设定

  • 查询点 \(Q\): \([0.5, 0.5]\)
  • 内存中的 PQ 数据: 存储了所有点的压缩表示,计算距离极快。
  • 磁盘中的数据: 存储了点的精确坐标和它们在 Vamana 图中的邻居。
  • Beam Width (\(W\)): 2(每次从磁盘读 2 个点的邻居)。

搜索步骤

  1. 初始化:

    • 从导航点(通常是数据集中心)开始。
    • 在内存中使用 PQ 计算 \(Q\) 到导航点的近似距离。放入候选集 \(L\)
  2. 第一轮迭代:

    • \(L\) 中选出距离 \(Q\) 最近的 2 个点(假设为 \(A\)\(B\))。
    • 磁盘操作: 从磁盘一次性读取 \(A\)\(B\) 的完整向量及其邻居列表。
    • 精确校准:\(A, B\) 的精确坐标重新计算与 \(Q\) 的距离。
  3. 扩展与更新:

    • 发现 \(A\) 的邻居是 \(\{C, D\}\)\(B\) 的邻居是 \(\{E\}\)
    • 在内存中用 PQ 快速计算 \(Q\)\(\{C, D, E\}\) 的距离。
    • 将这些点加入 \(L\),并根据距离排序,保留前 \(k\) 个。
  4. 收敛:

    • 重复上述过程,直到 \(L\) 中的前位节点不再发生变化。

3. 性能对比:为什么它比传统方法强?

特性 HNSW (传统) DiskANN
存储位置 必须全部在内存 索引和原向量在 SSD,少量 PQ 在内存
内存需求 极高 (100% 索引) 极低 (约 1/10 或更少)
图结构 分层 (Hierarchical) 单层 (Vamana)
I/O 模式 零星小读取 (不适合磁盘) 批量合并读取 (优化 SSD)

总结

DiskANN 的精髓在于“空间换成本”。它承认磁盘慢,但通过 Vamana 的强连通性 减少跳转次数,再通过 Beam Search 把剩下的跳转打包处理。


当数据规模从千万级跨越到亿级时,内存瓶颈(Memory Wall)会迫使我们从“纯内存计算”转向“冷热数据分离”或“磁盘常驻”的方案。


一、 邻居是如何计算的?(度量衡问题)

“邻居”是一个相对概念,它取决于你定义的距离度量(Distance Metric)

1. 核心度量方式

虽然点积(Inner Product, IP)是常用的一种,但并不是唯一:

  • L2(欧氏距离): 计算两点间的直线距离。$$d = \sqrt{\sum (a_i - b_i)^2}$$。常用于图片检索、人脸识别。
  • IP(内积): 计算两向量的乘积和。$$d = \sum a_i b_i$$。常用于推荐系统(矩阵分解后的向量)或搜索召回。
  • Cosine(余弦相似度): 关注向量的方向而非大小。$$d = \frac{A \cdot B}{|A||B|}$$。在自然语言处理(NLP)中是标配。

2. 计算原理:SIMD 加速

在亿级数据下,无论用哪种公式,CPU 都忙不过来。Milvus 底层利用了 SIMD(单指令多数据流) 技术,如 AVX2 或 AVX512 指令集。

  • 原理: 传统 CPU 一次处理一个加法,SIMD 可以一次性把 8 个或 16 个浮点数塞进一个寄存器,一秒钟内完成上亿次距离计算。

二、 亿级数据的破局:DiskANN 与 IVF-HNSW

HNSW 最大的问题是索引比数据还大。亿级 128 维向量,HNSW 索引可能需要 200GB+ 内存。如果不想买昂贵的超大内存服务器,有两条路:

1. DiskANN:基于磁盘的“Vanta”架构

DiskANN 是目前处理亿级以上数据的工业界标准方案(Milvus 已经集成)。

  • 设计精髓: Vanta 图 + PQ 压缩。
    • 内存里放什么? 放一个压缩后的向量副本(PQ 压缩后极小)和少量的索引导航信息。
    • 磁盘里放什么? 放原始的高维向量和完整的图结构。
  • 工作流程:
    1. 在内存中通过压缩向量进行快速预筛选(可能会有误差)。
    2. 确定潜在候选者后,直接从 SSD 磁盘中读取原始向量进行精确重新排序(Re-ranking)。
  • 优势: 内存占用降低 10 倍以上,且通过 SSD 的随机读能力保持了极高的召回率。

2. IVF-HNSW:分治法

这是一种将“聚类”和“图”结合的混合方案。

  • 计算逻辑:
    1. IVF 层(粗聚类): 将整个空间划分为 \(N\) 个聚类中心(Bucket)。
    2. HNSW 层(局部精索): 并不对全库建一张大图,而是对每个 Bucket 内部的数据建 HNSW 索引。
  • 查询过程:
    1. 先计算查询向量离哪个中心点(Bucket)近。
    2. 只进入那几个特定的 Bucket,运行 HNSW 搜索。
  • 平衡点:
    • 成本: 内存压力减小,因为你不需要建立全局巨大的 \(M\) 邻居边。
    • 性能: 搜索速度比纯 IVF 快,比纯 HNSW 慢,但通过调整 nprobe(扫描的桶数),你可以精准控制性能和精度的天平。

三、 性能与成本的平衡决策表

如果你正面临亿级规模的架构选型,可以参考下表:

方案 内存消耗 查询延迟 召回率 适用场景
纯 HNSW 极高 (All-in-RAM) 极低 (< 5ms) 极高 (> 98%) 预算充足,追求极致实时性
IVF-PQ 极低 中等 一般 (有损) 成本极其敏感,数据量百亿级
DiskANN 中等 低 (取决于 SSD) 极高 主流大规模工业级推荐方案
IVF-HNSW 中等 数据分布极其不均匀的场景

深度解析:为什么 DiskANN 必须配合 SSD?

传统的 HDD(机械硬盘)随机读 IOPS 太低,会导致查询延迟从毫秒级直接跳到秒级。DiskANN 的数学精妙之处在于它优化了图的连通性,使得每次查询只需要极少数几次(通常少于 5 次)磁盘 I/O。

一个核心的配置建议:
如果你在 Milvus 中启用 DiskANN,请务必确保你的磁盘是 NVMe SSD