3. 数学基础回顾

说实话,很多同学一听到「数学基础」四个字就想跳过。我当年也是这样。直到我在第一个多模态项目里,死活对齐不了图像和文本的特征空间……后来才发现,问题就出在矩阵分解上。嗯,从那以后我再也不敢轻视这些基础了。

这一章我们不讲纯数学推导,只讲你在多模态感知里真正会用到的部分。说白了,就是三样东西:线性代数(怎么操作高维数据)、概率论(怎么处理不确定性)、信息论(怎么衡量信息量)。

核心观点:数学工具不是用来考试的,是用来解决实际问题的。你理解了这个,后面看会轻松很多。
第3章 数学基础回顾 · 知识体系 线性代数 概率论 信息论 矩阵运算 · 特征分解 · SVD 协方差矩阵 · 投影变换 贝叶斯定理 · 高斯分布 条件概率 · 最大似然估计 互信息 · KL散度 · 熵 交叉熵损失 · 信息增益 多模态感知算法 三者缺一不可:线性代数做变换,概率论做推断,信息论做度量

3.1 线性代数:多模态数据的操作语言

多模态数据长什么样?图像是像素矩阵,文本是词嵌入向量,音频是频谱图矩阵。你想想看,这些本质上都是矩阵和向量。所以线性代数就是操作这些数据的「语法」。

3.1.1 矩阵运算

最基本的操作:矩阵乘法、转置、求逆。但我要强调一个点——矩阵乘法的维度匹配。我在项目中见过太多次因为维度没对齐导致的bug。

# 多模态特征融合的典型矩阵操作
import numpy as np

# 图像特征: 512维向量
img_feat = np.random.randn(1, 512)
# 文本特征: 256维向量  
txt_feat = np.random.randn(1, 256)

# 投影到公共空间 (512 -> 128, 256 -> 128)
W_img = np.random.randn(512, 128)
W_txt = np.random.randn(256, 128)

img_proj = img_feat @ W_img  # shape: (1, 128)
txt_proj = txt_feat @ W_txt  # shape: (1, 128)

# 融合
fusion = np.concatenate([img_proj, txt_proj], axis=1)  # (1, 256)
我的习惯:每次写矩阵运算前,先在注释里写清楚每个变量的shape。这能省掉你至少一半的debug时间。

3.1.2 特征分解与SVD

特征分解是什么?说白了就是找到一个矩阵的「骨架」。对于多模态来说,最常用的其实是SVD(奇异值分解)。

我记得有一次做跨模态检索,特征维度太高,检索速度慢得离谱。用SVD降维后,速度提升了10倍,精度只掉了不到2%。这就是SVD的价值——用最小的信息损失换取最大的效率提升。

方法 适用场景 多模态中的典型应用
特征分解 方阵、对称矩阵 协方差矩阵分析、PCA
SVD 任意矩阵 特征降维、矩阵补全、跨模态对齐
QR分解 数值稳定性要求高 最小二乘求解、特征值计算
我曾经踩过的坑:直接用np.linalg.eig()算特征分解,结果矩阵不是对称的,算出来的特征向量全是复数。后来才意识到,协方差矩阵才是对称的,原始数据矩阵不是。一定要用np.linalg.svd()处理非对称矩阵。

3.2 概率论:处理不确定性的武器

多模态感知里到处都是不确定性。传感器有噪声,数据有缺失,模型有置信度。概率论就是用来量化和管理这些不确定性的。

3.2.1 贝叶斯定理

贝叶斯定理的形式很简单:

P(A|B) = P(B|A) * P(A) / P(B)

但它的思想很深刻——用观测数据更新先验信念。在多模态融合里,这太常用了。

举个例子:视觉和触觉融合判断物体材质。视觉先给一个先验(看起来像木头),触觉传感器给出新的观测数据(硬度反馈),贝叶斯更新后得到后验概率(90%是木头)。

实用公式:多模态贝叶斯融合
P(类别 | 图像, 文本) ∝ P(图像 | 类别) × P(文本 | 类别) × P(类别)
假设各模态条件独立,就可以把联合概率拆成乘积。

3.2.2 高斯分布

高斯分布为什么重要?因为中心极限定理告诉我们,很多自然现象都近似服从高斯分布。传感器噪声、特征分布、模型预测误差……你想想看,是不是都像高斯?

我个人习惯用多元高斯分布来建模多模态特征的联合分布。均值和协方差矩阵分别刻画了「最可能的值」和「各维度之间的相关性」。

# 多元高斯分布示例
import numpy as np
from scipy.stats import multivariate_normal

# 假设图像和文本特征的联合分布
mean = np.array([0.5, 0.3])  # 均值
cov = np.array([[1.0, 0.6],   # 协方差矩阵
                [0.6, 1.0]])

# 生成样本
samples = np.random.multivariate_normal(mean, cov, size=1000)

# 计算概率密度
pdf_val = multivariate_normal.pdf([0.6, 0.4], mean=mean, cov=cov)
注意:协方差矩阵的非对角线元素表示模态间的相关性。值越大,说明两个模态越「同步」。这在多模态融合里是个重要指标。

3.3 信息论:量化信息的标尺

信息论解决什么问题?两个问题:一个变量包含多少信息?两个变量共享多少信息?

3.3.1 熵与互信息

熵衡量不确定性。熵越大,不确定性越大。互信息衡量两个变量之间的依赖程度。

在多模态里,互信息特别有用。你可以用它来判断:图像和文本到底有多「相关」?如果互信息高,说明两个模态对齐得好;如果低,说明它们各说各话。

概念 公式 多模态含义
熵 H(X) -∑p(x)log p(x) 单个模态的不确定性
联合熵 H(X,Y) -∑∑p(x,y)log p(x,y) 两个模态的联合不确定性
互信息 I(X;Y) H(X) + H(Y) - H(X,Y) 模态间的共享信息量

3.3.2 KL散度

KL散度衡量两个概率分布之间的「距离」。注意,它不是真正的距离度量,因为它不对称——KL(P||Q) ≠ KL(Q||P)。

我在做多模态知识蒸馏时,就用KL散度来让学生模型模仿教师模型的输出分布。说白了,就是让两个分布尽量接近。

# KL散度计算示例
import numpy as np

def kl_divergence(p, q):
    """计算KL(P||Q)"""
    p = np.asarray(p, dtype=np.float64)
    q = np.asarray(q, dtype=np.float64)
    # 避免log(0)
    p = np.clip(p, 1e-10, 1)
    q = np.clip(q, 1e-10, 1)
    return np.sum(p * np.log(p / q))

# 两个模态的输出分布
p_vision = [0.7, 0.2, 0.1]   # 视觉模型预测
p_text = [0.5, 0.3, 0.2]     # 文本模型预测

kl = kl_divergence(p_vision, p_text)
print(f"KL散度: {kl:.4f}")
我曾经踩过的坑:KL散度对分布中的零值非常敏感。如果p(x)=0但q(x)>0,计算会出问题。我的解决方案是加一个很小的平滑项(比如1e-10),或者用JS散度代替KL散度。

3.4 三者如何协同工作?

你可能会问:这三者到底怎么配合?我画个流程你就明白了。

  1. 数据表示:用线性代数把多模态数据变成向量/矩阵
  2. 不确定性建模:用概率论(高斯分布)描述每个模态的分布
  3. 信息度量:用信息论(互信息/KL散度)衡量模态间的相关性
  4. 融合决策:用贝叶斯定理或最大似然估计做最终判断
一句话总结:线性代数负责「怎么算」,概率论负责「怎么猜」,信息论负责「怎么比」。三者缺一不可。

好了,数学基础就讲到这里。这些工具在后面每一章都会反复出现。你不需要一次全记住,但要知道它们能解决什么问题。遇到具体场景时,再回来翻翻这一章就行。