4. 线性代数与微积分基础:矩阵运算、特征值分解、导数与梯度、优化基础
量化研究员处理的数据本质上是高维空间的数值集合:数百只股票的日收益率、数十个因子暴露、上千个时间窗口的协方差结构。这些数据天然以矩阵形式存在,而因子模型(如Fama-French三因子、Barra风险模型)和机器学习模型(如线性回归、主成分分析、神经网络)的数学内核,正是线性代数与微积分。本章不追求数学系的严格证明,而是从量化实战视角,梳理矩阵运算、特征值分解、导数与梯度、优化算法这四大支柱,帮助你建立从“看懂公式”到“写出代码”再到“理解模型行为”的完整链路。
上图展示了四大模块的联动关系:矩阵运算是数据组织和变换的基础,特征值分解用于提取协方差结构中的主成分,导数与梯度刻画了损失函数的变化方向,优化算法则利用梯度信息迭代求解模型参数。下面逐一深入。
4.1 矩阵运算:因子模型的数据骨架
核心原理
在量化研究中,矩阵是组织截面数据和时间序列数据的自然语言。设我们有 n 个时间窗口、k 个因子,则因子暴露矩阵 B 为 n×k 矩阵,收益率向量 r 为 n×1 向量。因子模型的基本方程:
r = B·f + ε
其中 f 为因子收益率(k×1),ε 为残差。矩阵乘法在这里完成了从因子暴露到收益率的线性映射。协方差矩阵 Σ = Cov(r) 是 n×n 对称半正定矩阵,其计算涉及外积 XᵀX/n,这是矩阵乘法的典型应用。
关键操作流程
- 矩阵乘法:确认维度匹配(m×p 乘以 p×n 得 m×n),使用 NumPy 的
@运算符或np.dot。 - 转置与逆:
X.T转置;np.linalg.inv(X)求逆,但优先使用np.linalg.solve解线性方程组以避免显式求逆的数值不稳定。 - 迹与范数:
np.trace计算迹(对角线元素和),Frobenius 范数np.linalg.norm用于衡量矩阵大小。
案例拆解:最小二乘估计的矩阵实现
假设我们要用两个因子(市值、动量)解释 1000 只股票的横截面收益。设计矩阵 X 为 1000×3(含截距项),收益率向量 y 为 1000×1。OLS 估计量:
w = (XᵀX)⁻¹Xᵀy
在 Python 中实现:
import numpy as np
# X: (1000,3), y: (1000,)
w = np.linalg.solve(X.T @ X, X.T @ y)
# 预测值
y_hat = X @ w
# 残差
resid = y - y_hat
# 残差方差
sigma2 = resid @ resid / (len(y) - X.shape[1])
这里 X.T @ X 是 3×3 矩阵,求逆或求解非常快。注意:当因子间高度相关时,X.T @ X 接近奇异,导致估计不稳定——这正是下一节特征值分解要解决的问题。
np.linalg.inv(X.T @ X) 而非 solve。当矩阵条件数很大时(接近奇异),显式求逆会放大浮点误差,导致权重系数出现极端值。始终优先使用 solve 或 lstsq。
4.2 特征值分解:风险结构的核心工具
核心原理
对于对称矩阵 Σ(如协方差矩阵),特征值分解为 Σ = QΛQᵀ,其中 Q 是正交矩阵(列向量为特征向量),Λ 是对角矩阵(特征值 λ₁ ≥ λ₂ ≥ ... ≥ λₙ ≥ 0)。特征值表示对应特征向量方向上的方差大小。在量化中,这直接对应 PCA(主成分分析):最大的几个特征值对应的特征向量,就是解释方差最多的“风险方向”。
判断方法与操作流程
| 步骤 | 操作 | 量化意义 |
|---|---|---|
| 1. 标准化 | 对因子暴露矩阵做 z-score 标准化 | 消除量纲影响,使各因子可比 |
| 2. 计算协方差 | Σ = XᵀX / (n-1) | 刻画因子间线性关系 |
| 3. 特征分解 | np.linalg.eigh(Σ) | 得到特征值和特征向量 |
| 4. 选择主成分 | 保留累计解释方差 ≥ 85% 的前 m 个 | 降维同时保留主要风险结构 |
| 5. 构建正交因子 | F_new = X @ Q[:, :m] | 得到去相关的因子组合 |
案例拆解:Barra 风险模型中的结构化协方差
Barra 模型使用行业因子和风格因子(如价值、动量、波动率)构建协方差矩阵。原始因子暴露矩阵可能包含 50+ 个因子,直接估计 50×50 协方差矩阵需要大量数据且噪声大。通过特征值分解,我们保留前 10-15 个主成分,即可解释大部分风险。具体操作:
# 假设 X 为标准化后的因子暴露 (n×50)
cov = np.cov(X, rowvar=False) # 50×50
eigvals, eigvecs = np.linalg.eigh(cov)
# 按特征值降序排列
idx = np.argsort(eigvals)[::-1]
eigvals = eigvals[idx]
eigvecs = eigvecs[:, idx]
# 保留前 15 个主成分
k = 15
factor_loadings = eigvecs[:, :k] # 50×15
# 新因子暴露
X_pca = X @ factor_loadings # n×15
这样得到的 15 个正交因子,既降低了维度,又避免了原始因子间的多重共线性问题。在组合优化时,使用这些正交因子构建风险模型,协方差矩阵更稳定。
4.3 导数与梯度:损失函数的导航仪
核心原理
在机器学习中,我们定义损失函数 L(w) 衡量预测值与真实值的差距,其中 w 是模型参数。梯度 ∇L(w) 是一个向量,每个分量是 L 对 w 各分量的偏导数,指向损失函数增长最快的方向。因此,负梯度方向就是损失下降最快的方向。对于线性回归的 MSE 损失:
L(w) = (1/n)||Xw - y||²
∇L(w) = (2/n)Xᵀ(Xw - y)
这个梯度公式可以直接用矩阵运算实现,无需手动推导每个分量。
链式法则与反向传播
对于多层神经网络,损失函数是复合函数。链式法则告诉我们:
∂L/∂w₁ = (∂L/∂a₂) · (∂a₂/∂z₂) · (∂z₂/∂a₁) · (∂a₁/∂z₁) · (∂z₁/∂w₁)
其中 a 是激活值,z 是线性变换输出。反向传播算法正是从输出层向输入层逐层计算这些梯度乘积,避免了重复计算。
案例拆解:梯度检查与数值验证
在实现自定义损失函数时,梯度计算错误是常见问题。使用数值梯度进行验证:
def numerical_gradient(f, w, eps=1e-6):
grad = np.zeros_like(w)
for i in range(len(w)):
w_plus = w.copy(); w_plus[i] += eps
w_minus = w.copy(); w_minus[i] -= eps
grad[i] = (f(w_plus) - f(w_minus)) / (2*eps)
return grad
# 验证解析梯度
w = np.random.randn(10)
analytic = gradient_of_loss(w) # 自定义解析梯度
numeric = numerical_gradient(lambda x: loss(x), w)
print(np.max(np.abs(analytic - numeric))) # 应 < 1e-6
如果差异大于 1e-4,说明解析梯度实现有误,需要检查链式法则的每一步。
4.4 优化基础:从梯度下降到组合求解
核心原理
优化问题在量化中无处不在:最小化损失函数训练模型、最大化效用函数配置资产组合、最小化跟踪误差进行指数增强。梯度下降是最基础的迭代方法:
w_{t+1} = w_t - η · ∇L(w_t)
其中 η 是学习率。学习率过大导致震荡不收敛,过小则收敛缓慢。现代优化器(如 Adam)通过自适应学习率和动量机制,缓解了调参难题。
操作流程与对比
| 优化器 | 更新规则 | 适用场景 | 注意事项 |
|---|---|---|---|
| 批量梯度下降 | 使用全部数据计算梯度 | 小数据集、凸问题 | 计算量大,但收敛稳定 |
| 随机梯度下降 | 每次用一个样本 | 大数据集 | 噪声大,需衰减学习率 |
| Mini-batch | 每次用一小批样本 | 深度学习标准 | batch size 需调参 |
| Adam | 自适应矩估计 | 大多数场景 | 对学习率不敏感,但需关注 β₁, β₂ |
案例拆解:组合优化中的闭式解与迭代解
考虑一个均值-方差组合优化问题:
min wᵀΣw - λ·μᵀw
s.t. Σwᵢ = 1
其中 μ 是预期收益向量,λ 是风险厌恶系数。这是一个带等式约束的二次规划,可以用拉格朗日乘子法得到闭式解:
w* = (1/2λ)Σ⁻¹(μ - γ·1)
其中 γ 由约束条件确定。但在实际中,Σ 可能不可逆(当资产数量大于时间窗口时),此时需要引入正则化:
# 岭回归风格的正则化协方差
Σ_reg = Σ + α·I
w = np.linalg.solve(Σ_reg, μ) # 简化版,未加约束
或者使用梯度下降迭代求解,每次更新后投影到可行域(如权重和为 1):
def project_weights(w):
return w / w.sum() # 简单投影到单纯形
w = np.ones(n) / n
for i in range(1000):
grad = 2 * Σ @ w - λ * μ
w = w - 0.01 * grad
w = project_weights(w)
迭代法的优势在于可以灵活添加约束(如权重非负、行业中性),而闭式解难以处理复杂约束。
常见误区与总结
- 误区一:认为矩阵求逆是万能的。当矩阵接近奇异时,应使用 SVD 或正则化。
- 误区二:忽略特征值分解的数值稳定性。使用
np.linalg.eigh而非eig,前者专门针对对称矩阵,更稳定。 - 误区三:梯度下降中学习率固定不变。应使用学习率衰减或自适应优化器。
- 误区四:在组合优化中直接使用样本协方差矩阵。应进行收缩估计(如 Ledoit-Wolf)或因子结构化处理。
总结而言,线性代数提供了描述高维数据的语言和操作工具,特征值分解帮助我们提取核心风险结构,导数与梯度连接了模型与数据之间的反馈信号,优化算法则将这些信号转化为参数更新。四者环环相扣,构成了量化研究员从数据处理到模型训练再到组合构建的完整数学工具箱。掌握这些基础,后续学习因子模型、机器学习算法时,你将能够理解每个公式背后的几何直觉和计算逻辑,而不仅仅是调用现成的库函数。