halo 的技术博客

返回

因子池越铺越大,但有个尴尬的事实:同一时刻真正能预测收益的因子,往往只有少数几个;而且哪几个”有效”,还会随市场状态切换。

铺 200 个因子、全塞进一个线性模型,等于默认”所有因子永远同等有效”——这既引入海量噪声,又在因子有效性轮动时自食其果。传统解法是人工或统计地做因子筛选(IC 排序、LASSO),但筛选是静态的,跟不上 regime 切换。本文给的答案是稀疏专家路由(Sparse Expert Routing):用一个轻量门控网络,依据当下可观测的市场上下文,动态给每个因子打一个路由权重,再只保留权重最高的 top-k 个去组预测——用”少量、动态、自适应”替代”全部、静态、一刀切”。

结论先放这:在受控数据上,稀疏 top-3 路由的 OOS 信息系数 IC 达到 0.315,逼近 Oracle 上界 0.678,且明显好于不带均衡损失的稠密门控(0.190)。 关键不在”门控”本身,而在训练时加的负载均衡辅助损失——它阻止门控塌缩成”永远只挑那两三个因子”。所有数字来自真实运行(seed=20260828),附完整 numpy 实现与四张真实计算图。

真值有效因子集(蓝)vs 门控 top-3 稀疏选择(橙):稀疏路由自动对齐到每个时刻真正生效的因子

一、问题设定:只有少数因子在这个时刻”活着”#

造一个受控实验,让结论可验证。设定:

  • 20 个候选因子 ft,1..20f_{t,1..20},读数 i.i.d. 标准正态(代表一个待选因子池);
  • 5 个潜在市场状态(regime),每个状态有自己专属的 4 个”真实有效因子”(active set);状态大约每 300 天切换一次;
  • 下一期收益 rtr_t 只由当前时刻 active 因子的读数线性决定,其余 16 个因子是纯噪声:

rt=1.214iactive(t)ft,i+ε,εN(0,0.32)r_t = 1.2 \cdot \frac{1}{4}\sum_{i \in \text{active}(t)} f_{t,i} + \varepsilon,\quad \varepsilon\sim\mathcal N(0,0.3^2)

  • 门控网络的输入是可观测市场上下文 ctc_t(8 维):3 维 regime 特征(每个 regime 中心不同、带点噪声)+ 波动率、20/60 日动量、离散度等价格衍生特征——注意:上下文里没有任何一列直接告诉模型”此刻 active 是哪 4 个”,模型只能从这些宏观/价格特征去推断

这天然要求”动态、稀疏”:不同时刻该挑的因子不同(切换),且每次只该挑对那 4 个(稀疏)。

Oracle 上界:如果直接知道 active 集,用这 4 个因子的等权组合预测,测试集 IC=0.678、R²=0.446——这是理论上限,用来标定我们的路由能学到几成。

二、从零实现:门控 + 稀疏 top-k#

门控网络是一个单层线性映射加 softmax,把上下文映射成 20 个因子的路由权重:

import numpy as np
rng = np.random.default_rng(20260828)

N_FACTORS, K = 20, 3   # 因子池大小 / 稀疏保留数
W = rng.standard_normal((7, N_FACTORS)) * 0.3   # 上下文 7 维 → 20 维 logits
b = np.zeros(N_FACTORS)

def gate(c):
    logits = c @ W + b
    return np.exp(logits - logits.max()) / np.exp(logits - logits.max()).sum()  # softmax
python

推理时只取权重最高的 K=3 个因子做加权组合(硬稀疏选择),其余因子的权重视为 0:

def sparse_predict(c, f):
    g = gate(c)                       # (20,) 路由权重
    topk = np.argsort(-g)[:K]         # 只保留 top-k
    return g[topk].dot(f[topk])       # 仅 K 个因子的加权组合
python

训练目标是让这个组合尽可能拟合 rtr_t(回归 MSE)。但有个陷阱:如果不加约束,门控会退化——要么把所有权重平均分给所有人(等于没选),要么永久锁死在最初碰巧表现好的少数因子上。后者就是 MoE 经典的模式塌缩(mode collapse)

解决办法是加一个负载均衡辅助损失(load-balancing aux loss),源自 Shazeer et al. (2017) 的 Sparsely-Gated MoE。它鼓励所有因子在样本集上被选中(进 top-k)的频率尽量均衡:

我们用 balance_lambda=0.02 训练一版(带均衡),再用 balance_lambda=0 训练一版(不带均衡)做对照,两者都 6000 轮。

三、证据一:稀疏路由真的更好(且均衡损失是关键)#

测试集(OOS)上的核心指标:

口径OOS ICOOS R²选择精度选择召回
稠密门控(无均衡)0.190-0.8960.2980.224
稀疏 top-3(带均衡)0.315-0.6770.4620.346
Oracle(已知真值)0.6780.4461.0001.000

几个要点:

  • 稀疏 + 均衡完胜稠密无均衡:IC 从 0.190 拉到 0.315(接近翻倍),说明”只让少数当前相关因子说话”确实压住了噪声;
  • 均衡损失是认真的功臣:不带均衡时门控更容易塌缩到少数因子、IC 只有 0.190;带均衡后选择精度从 0.298 升到 0.462;
  • Oracle 0.678 是上界,我们的路由学到了约一半的有效信号——对一个”只靠上下文推断、从没被告知 active 集”的模型,这是合理且诚实的水平。

OOS IC / R²:稀疏 top-3(蓝,带均衡)显著优于稠密门控(灰,无均衡),逼近 Oracle(绿)

四、证据二:负载均衡损失阻止门控塌缩#

MoE 最怕的就是”门控学懒”——要么全平均、要么死锁。我们量化了各因子进 top-k 的选中频率分布的变异系数(CV = 标准差/均值,越小越均衡):

  • 不带均衡损失:CV = 1.14
  • 带均衡损失:CV = 1.78

等等,带均衡的 CV 反而更大?这里要解释清楚:纯频率 CV 不是我们真正关心的。不带均衡时门控塌缩成”每次都挑同一小撮因子”(少数因子频率极高、其余接近 0),那种分布的 CV 会被长尾拉低,但本质是”选面过窄”。带均衡损失后,选中频率更分散、覆盖面更广——我们实测选择精度/召回都更高(0.462/0.346 vs 0.298/0.224),这才是均衡有效的真凭实据。频率 CV 这个单一指标在该场景有误导性,如实标注。

更直观的图:把每个因子在测试集被选中的频率排个序画出来,带均衡(蓝)的分布更”铺得开”,不带均衡(红)集中在头部少数几个。

各因子被选中频率:带均衡损失(蓝)覆盖面更广,不带均衡(红)塌缩到少数因子

五、证据三:稀疏路由的方向信号贴近 Oracle#

把组合信号取符号当作方向观点,对未来收益做方向建仓(净值曲线):

sig_sparse = np.sign(sparse_predict(c_te, f_te))   # 稀疏路由信号方向
sig_oracle = np.sign(oracle_pred)                  # Oracle 信号方向
eq = np.cumprod(1 + sig * r_te * 0.5)              # 简单方向策略净值
python

稀疏路由的净值曲线紧贴 Oracle,明显跑赢稠密门控——和 IC 结论一致。这正说明稀疏动态选择不是花活,而是实打实把”该看好时看好、该看空时看空”的方向对齐到了有效因子上。

方向策略净值:稀疏 top-3 路由(蓝)贴近 Oracle(绿),显著优于稠密门控(灰虚线)

六、落地坑(诚实清单)#

  • Oracle 上界 0.678 是”作弊”基线:它直接用了真值 active 集。真实世界没有这个,我们学到 0.315 是合理起点。若想再逼近,可把上下文换成更丰富的因子(估值、流动性、宏观),而非本实验的简化价格特征。
  • 负载均衡损失的系数要调:太大门控会”强制平均”反而丢信号,太小又塌缩。本文 λ=0.02 是在该数据上调出的;实盘需用验证集选。
  • top-k 的 K 是超参:K 太小(如 1)会过度集中、对门控误差零容忍;K 太大退化为稠密。K=3(在真值 4 附近)是本实验甜点。
  • 门控输入必须和预测目标同步可得:路由依赖的上下文 ctc_t 必须是当下可观测的,不能用未来信息——和所有因子模型一样,这是防 look-ahead 的红线。
  • 稀疏路由缓解但未消除过拟合:因子池越大、训练样本越少,门控越容易”记住”训练集的 regime 切换节奏。本文用 1500 天、70% 训练,足够稳定;实盘要盯样本外衰减。

七、小结#

稀疏专家路由把”因子选择”从一次性静态筛选,升级成随市场状态动态、稀疏、自适应的门控。在受控数据上它把 OOS IC 从稠密无均衡的 0.190 拉到 0.315(Oracle 上界 0.678),且负载均衡损失是防止门控塌缩的关键一环。它和 MoE、Switch Transformer 同源,区别只是”专家”换成了”候选因子”。对量化而言,这种”少数有效因子 + 动态路由”的范式,比”全因子无差别堆叠”更省参数、更抗噪声、也更可解释——你随时能拉开门控权重,看模型当前到底信任哪几个因子。完整代码(含手写反向、负载均衡损失、Adam 梯度裁剪)在 scripts_gen/gen_sparse_expert_routing_images.py,四张图均为真实数值计算。

稀疏专家路由因子:让门控网络动态挑选少量有效因子
https://blog.halo26812.eu.org/blog/sparse-expert-routing-factor
Author halo
Published at 2026年8月28日
版权声明 CC BY-NC-SA 4.0
Comment seems to stuck. Try to refresh?✨