halo 的技术博客

返回

量化里有一个反复出现的痛点:你训好一个模型,市场变了,它就废了。 你在美股大盘上调出的因子模型,搬到 A 股小盘、港股、加密货币上,往往从第一天就水土不服。传统做法要么在每个新市场从头训练(数据太少,学不动),要么把所有市场混在一起训一个「万金油」模型(忽略了市场之间的结构差异,哪个都不精)。

元学习(meta-learning) 提供了第三条路:不学「一个模型」,而学「怎么快速学出一个模型」。它的口号是 learning to learn——让模型学会「学会」。本文聊元学习里最经典的算法 MAML(Model-Agnostic Meta-Learning,Finn et al. 2017):它训练出一个特殊的初始化参数,使得在任何新任务上,只用极少样本、走一两步梯度下降,就能快速适应。

我们把「每个市场/regime」当成一个任务,用合成的因子→收益线性模型跑成看得见的数据:MAML 元初始化在新任务上做 10-shot(仅 10 个样本)一步梯度适应,query MSE 降到 2.07,跑赢 Pooled 全局模型的 2.31 和从零训练的 3.32,逼近 Oracle(用真参数)下界 1.00;10 个种子里 10/10 全胜 Pooled,平均降 MSE 8.2%

一、问题设定:把「市场」变成「任务」#

MAML 的世界观是任务分布(task distribution)。我们假设存在一个任务分布 p(T),每次从中采样一个任务(一个市场/regime)。每个任务是一个因子→收益的线性映射:

y = X · θ_task + 噪声
plaintext

关键假设:不同任务的 θ_task 不是完全无关的,它们从一个共同分布采样

θ_task ~ N(θ0, τ²·I)
plaintext

θ0 是所有任务共享的「中心结构」(比如「价值因子在多数市场都有正暴露」),τ 控制任务之间的差异强度。这个假设是元学习能work的前提:如果各市场毫无共性(τ→∞),那没有任何东西可以迁移;如果各市场完全一样(τ=0),那直接混合训练就够了。真实市场介于两者之间——有共性,也有差异,这正是 MAML 的用武之地。

import numpy as np

P = 5                                          # 因子数
THETA0 = np.array([0.8, -0.5, 0.3, 0.6, -0.4]) # 任务共享中心
TAU = 0.5                                       # 任务间差异强度

def sample_task(rng):
    return THETA0 + rng.normal(0, TAU, P)      # 采样一个市场的真参数

def gen_data(theta, n, rng):
    X = rng.normal(0, 1, (n, P))
    y = X @ theta + rng.normal(0, 1.0, n)
    return X, y
python

二、MAML 的核心:双层优化#

MAML 的精髓是双层优化(bi-level optimization),分内外两个循环:

  • 内层(inner loop)——适应:给定元初始化 θ_meta,在某个任务的少量「支持集(support set)」上做几步梯度下降,得到适应后的参数 φ
φ = θ_meta − α·∇_θ L_support(θ_meta)     (α 是内层学习率)
plaintext
  • 外层(outer loop)——元更新:评估适应后的 φ 在同任务「查询集(query set)」上的损失,把这个损失θ_meta 求梯度,更新 θ_meta
θ_meta ← θ_meta − β·∇_{θ_meta} L_query(φ)     (β 是外层学习率)
plaintext

注意这里的微妙之处:外层的梯度是穿过内层适应步θ_meta 求导的。这意味着 MAML 优化的不是「θ_meta 本身在任务上表现好」,而是「θ_meta 适应之后在任务上表现好」。这就是「learning to learn」——它学的是一个易于适应的起点,而不是一个直接可用的模型。

外层元梯度需要穿过内层梯度步,展开后含一个 Hessian 项:

∇_{θ_meta} L_query(φ) = (I − α·H_support) · ∇_φ L_query(φ)
plaintext

其中 H_support 是支持集损失的 Hessian。对线性回归它是解析的 H = (2/K)·XᵀX

三、元训练收敛:θ_meta 收敛到任务中心#

MAML 训练完,θ_meta 会收敛到什么?直觉上,它应该收敛到任务分布的「共享中心」θ0 附近——因为从这个中心出发,到任何一个具体任务的距离都最短,一步梯度就能到。

MAML 元训练收敛:元初始化收敛到任务分布的『共享中心』

实测 ‖θ_meta − θ0‖ = 0.119,确实收敛到 θ0 附近(注意它不完全等于 θ0,因为 MAML 优化的是「适应后」的损失,会略微偏离以补偿内层步的方向)。作为对比,Pooled 全局模型的 θ_pool 也在 θ0 附近(‖θ_pool−θ0‖=0.033)——但两者的用法完全不同:Pooled 直接拿 θ_pool 去预测(不适应),而 MAML 拿 θ_meta起点再用新任务数据适应。下一节看这个差异带来多大区别。

四、Few-shot 适应结果:碾压从零训练,跑赢全局模型#

在 400 个全新任务上评估,每个任务只给 K=10 个样本做适应,比较四种方法:

  • MAML:从 θ_meta 出发,用 10 个样本走一步梯度;
  • Pooled:直接用混合训练的全局模型 θ_pool(不适应);
  • Scratch:从随机初始化出发,用 10 个样本适应;
  • Oracle:直接用真 θ_task(理论下界)。
def adapt(theta_init, Xs, ys, lr=0.05, steps=1):
    phi = theta_init.copy()
    for _ in range(steps):
        phi = phi - lr * grad(phi, Xs, ys)
    return phi

# 新任务上:MAML 元初始化 + 10 样本一步适应
phi_maml = adapt(theta_meta, Xs, ys, steps=1)
python
方法新任务 query MSE相对 Oracle 差距
MAML(10-shot, 1 步)2.07+107%
Pooled(全局,不适应)2.31+131%
Scratch(随机初始化)3.32+232%
Oracle(真 θ)1.000%

10-shot 适应:MAML 快速逼近 Oracle,碾压 Scratch 与 Pooled

三个结论:

  1. MAML 完胜 Scratch(降 MSE 37.8%):这是元学习最直观的价值——同样只有 10 个样本,从「好起点」出发比从随机起点出发好太多。Scratch 的高方差(箱线图里最宽)也说明从零训练在小样本下极不稳定。
  2. MAML 跑赢 Pooled(降 MSE 10.6%):Pooled 的问题在于它用同一组参数面对所有任务,无法针对新市场的具体差异微调;MAML 保留了「适应」这一步,能吃到任务的个性化信息。
  3. 离 Oracle 还有距离:MSE 2.07 vs Oracle 1.00。这个 gap 来自「只有 10 个样本」的信息约束——even 最优的适应也无法从 10 个含噪样本里完全恢复真参数。样本越多,gap 越小(下一节)。

五、样本效率:K 越小,MAML 优势越大#

MAML 的核心卖点是样本效率(sample efficiency)——在数据稀缺时优势最大。扫描适应样本数 K:

样本效率:MAML 在极少样本(K小)时优势最大

  • K 很小(2~5):MAML 和 Pooled 都远好于 Scratch(从零训练在 K=2 时几乎学不动),MAML 与 Pooled 的差距也最明显;
  • K 增大(20~40):三条线开始收敛——当每个任务的数据足够多时,从零训练也能学好,元学习的边际价值下降。

这条曲线揭示了元学习的适用边界:它是为数据稀缺场景设计的。在量化里,这对应「新上市的品种」「刚出现的新 regime」「小众市场」——历史数据少到无法独立建模,但又和已知市场有共性。如果你的新市场有十年高频数据,直接单独训练可能就够了,不必上 MAML。

六、单任务适应轨迹:一步到位 vs 慢慢爬#

最能体现「learning to learn」的,是单个新任务上的适应轨迹:

单任务适应轨迹:MAML 一步就贴近最优,从零要走很多步

从 MAML 元初始化出发,第一步梯度就把 MSE 拉到接近 Oracle;而从零初始化出发,走完 8 步还在半路。这正是 MAML 训练的目标函数所优化的东西——它专门把 θ_meta 放在一个「一步就能到」的位置。这也是 MAML 在实盘里最诱人的特性:市场 regime 切换后,你不需要重新训练几天,只要拿新数据走一两步梯度,模型就跟上了。

七、鲁棒性:10 个种子#

单次结果可能侥幸。跑 10 个不同种子(不同的任务分布采样、不同的元训练)确认:

  • MAML 相对 Pooled 平均降 MSE 8.2% ± 1.6%
  • MAML < Pooled(即 MAML 更优):10/10 个种子全胜。

10/10 的稳定性说明:在「任务间有共性也有差异」的结构下,MAML 相对 Pooled 的优势是系统性的,不是运气。当然,这个优势的大小(8.2%)取决于任务差异强度 τ——τ 越大(市场越不同),适应这一步越值钱,MAML 相对 Pooled 的优势越大。

八、六大真实陷阱#

  1. 任务无共性则元学习无效:这是头号前提。MAML 假设任务从共同分布采样(有 θ0)。如果你的「不同市场」其实是毫无关联的随机系统(τ→∞),元学习学不到任何可迁移的东西,会退化成 Scratch。上线前必须验证任务间确实存在共享结构(比如做跨市场因子相关性分析)。
  2. 元过拟合(meta-overfitting):MAML 可能对元训练用过的那批任务过拟合,在真正的新任务上失效。必须把任务本身也分成「元训练任务」和「元测试任务」,绝不能用测试任务的市场参与元训练。
  3. 二阶梯度的计算与稳定性:完整 MAML 需要 Hessian(二阶梯度)。深度模型里这非常昂贵且不稳定。实践中常用一阶近似(FOMAML)或 Reptile——我们代码里的线性模型 Hessian 是解析的,但深度网络需要谨慎处理。
  4. 内层学习率与步数的敏感性α(内层 lr)和内层步数是关键超参。太大适应会震荡,太小一步到不了位。这两个超参本身也需要在元验证集上调,且很容易过拟合。
  5. 分布漂移打破任务假设:金融市场的任务分布 p(T) 本身在时变(2008 的 regime 和 2020 的不同)。MAML 假设新任务来自训练时的同一分布 p(T),一旦真实市场演化出训练时从未见过的 regime,元初始化也会失效。需要持续用新任务滚动更新 θ_meta
  6. 标签与前视偏差照样致命:元学习不能豁免量化的基本纪律。如果 support/query 的划分泄漏了未来信息,或因子构造有前视偏差,MAML 只会把这些偏差「更高效地」学进元初始化。所有 support/query 划分必须严格按时间切分。

九、结语#

MAML 的价值不在于「更强的模型」,而在于一种应对变化的元能力。它把量化建模的问题从「训一个好模型」重构成「训一个好起点,让适应变得廉价」。这对金融这种非平稳、regime 频繁切换、新品种不断涌现的领域尤其贴切——你无法为每个新市场都攒够十年数据,但你可以让模型学会「借用旧市场的经验,用几个样本快速上手新市场」。

对量化研究者而言,元学习最该记住的三件事:

  • 它是为数据稀缺设计的——K 越小优势越大,数据充足时单独训练可能就够,别为了用而用;
  • 它的前提是任务间有共性——上线前务必验证跨市场的共享结构,无共性则元学习退化成从零训练;
  • 它换来的是「适应速度」而非「绝对精度」——MAML 的杀手锏是 regime 切换后一两步梯度就跟上,而不是在单一稳定市场上碾压专用模型。

它和之前聊过的迁移学习、集成模型、概念漂移检测是同一条主线上的不同工具:在一个永远在变的市场里,与其追求一个永远正确的模型,不如学会如何快速变得正确。

注:本文的任务/市场为「共享中心 θ0 + 任务差异 τ」的自洽合成线性模型,用于演示 MAML 的双层优化机制与样本效率;真实跨市场迁移涉及非线性因子、时变任务分布、非平稳噪声,落地需接入真实多市场数据、严格按时间切分 support/query、用元测试任务验证泛化,并做样本外与 walk-forward 验证。

元学习(MAML)跨市场快速适应:让策略学会『学会』
https://blog.halo26812.eu.org/blog/meta-learning-maml
Author halo
Published at 2026年7月14日
版权声明 CC BY-NC-SA 4.0
Comment seems to stuck. Try to refresh?✨