首页 / 资讯中心 / 文章详情

变分自编码器复现指南:截面股票收益率预测与隐变量压缩

变分自编码器复现指南:截面股票收益率预测与隐变量压缩 ★ FEATURED ARTICLE
简介基于变分自编码器的截面股票收益率预测复现资源对应学术论文《FactorVAE》适合熟悉机器学习与Python、希望将VAE引入金融量化的读者。资源将完整复现过程整理为一个Word文档压缩包内仅此一个文件大小约27KB内容却覆盖环境配置、数据标准化、模型设计、训练评估与业务应用全流程。文档从数据读取与标准化切入详细展示了基于PyTorch的FactorVAE实现包括GRU特征提取器、因子编码器、因子解码器和因子预测器的设计并给出损失函数定义及逐步训练指令便于读者复现。评估部分细致解释了Rank IC与Rank ICIR两类指标的计算方式并补充了模型可视化、可解释性分析和鲁棒性测试思路最后通过构建投资组合绘制预测收益与组合累计收益曲线直观验证模型有效性。已有194人学习代码依托PyTorch、Pandas等常用库虽以Word形式呈现但核心代码段可直接迁移。读者可据此搭建自己的概率动态因子模型深入理解变分自编码器在股票收益预测中的应用价值也可作为金融科技研究与实践的参考。1. 变分自编码器与截面股票收益率预测为什么值得复现一个反直觉的结论是把变分自编码器VAE用到截面股票收益率预测上核心价值往往不在“预测得更准”而在于把高维、高噪声的因子特征压缩成一个低维隐变量再在隐变量上做收益预测。截面数据的形态是多个交易日、多只股票、多个特征组成的三维数组论文典型的做法是取某一天的“股票×特征”切片输入 VAE经过编码器得到均值和方差用重参数化采样得到隐变量 z最后用一个预测头输出下一期收益。相比直接做全连接回归这种做法多了一层概率建模隐空间相当于一个带正则化的因子压缩器能在样本有限时抑制对噪声的过拟合。这篇笔记适合想动手复现论文的学生、正在把生成模型引入因子挖掘的研究者以及不满足于线性多因子、想尝试更灵活 alpha 结构的量化从业者。2. 从论文到模型VAE 如何变成截面收益预测器2.1 为什么用 VAE 而非直接回归隐变量相当于因子压缩器截面股票收益预测的常见设定是给定第 t 日的股票特征矩阵 X_t预测第 t1 期的收益率向量 y_t。传统多因子模型假设 y_i 与一组特征线性相关但论文通常会假设存在一个非线性函数 g使得 y_i g(f(x_i)) ε。这里的难点在于特征之间高度相关噪声远大于信号且截面上可用的股票数量有限。如果直接把 X_t 灌进一个多层感知机预测 y_t模型很容易记住截面上的噪声换一个时间段就失效。VAE 的建模思路不同它假设存在一个低维隐变量 z能够生成观测到的特征 x_i同时 z 与未来收益 y_i 相关。编码器负责从 x_i 推断 z 的后验分布解码器负责从 z 重建 x_i预测头再从 z 得到收益预测。这样z 就成了连接“特征”和“收益”的中间表示。我一般把这个结构理解为“因子压缩器”把动量、反转、换手率、波动率、估值等几十个原始特征压成 8 到 32 维的隐变量。与 PCA 这种线性降维不同VAE 允许非线性映射同时通过 KLD 正则项让隐空间分布平滑避免 AutoEncoder 那样把特征空间扭曲成碎片。这也是它在论文里被用来做收益预测的根本原因不再追求对特征的重建误差最小而是追求隐变量对下游收益预测的稳定性。另外要注意这个设定与普通 AutoEncoder 有本质差别。AutoEncoder 只要求编码、解码后信息损失最小训练完通常只拿编码器当特征提取器但隐空间没有结构约束任意两个样本在隐空间里的距离没有太大意义。VAE 对隐变量施加了标准正态先验让编码器输出的后验分布尽量接近 N(0,1)训练出来的隐空间更连续、扰动更小这对收益预测这种信噪比极低的任务很关键。2.2 结构拆解编码器、重参数化、解码器与预测头复现论文时模型结构可以拆成四块编码器输入原始特征 x输出隐变量的均值 μ 和对数方差 logvar。典型结构是两层到三层的全连接网络中间用 LeakyReLU 激活避免 ReLU 在训练前期把大量神经元杀死。最后一层分裂成两个 head分别输出 μ 和 logvar。注意网络输出的是 logvar 而不是方差本身这样既保证方差通过指数运算后永远为正又让梯度传播更稳定。重参数化是整个 VAE 的核心技巧。直接对随机变量 z 采样梯度无法传回编码器所以论文里用 z μ ε·σ其中 ε 是标准正态随机数。这个操作把随机性移到 ε 上μ 和 σ 的梯度路径得以保留既让模型能够反向传播又保留了采样带来的随机性。解码器从 z 重建原始特征 x结构上是编码器的镜像。论文里对解码器做不做预测没有统一要求但复现时保留解码器是有好处的重建损失能给隐变量一个“信息量下限”避免编码器把所有 z 都压到先验附近。预测头负责从 z 输出未来收益预测 y。这里的关键是预测头不能太深。我在复现时一般只用一层 64 维的隐藏层加一个线性输出因为如果预测头能力太强模型会直接把 VAE 扔到一边变成“先降维再回归”的普通 MLP失去概率建模带来的正则效果。2.3 损失组合重建损失、KLD 与预测损失的权重怎么配训练时的总损失由三部分组成L L_recon β * L_KLD λ * L_predL_recon 是重建损失衡量解码器能否从 z 恢复原始特征。特征如果做了标准化直接用 MSE 即可。L_KLD 是散度项衡量编码器输出的后验分布与标准正态先验的差距公式是 -0.5 * Σ(1 logvar - μ² - exp(logvar))。这一项让隐空间保持连续和平滑。L_pred 是预测损失通常也是 MSE衡量模型对下一期收益的拟合能力。权重 β 和 λ 是复现中最容易踩坑的地方。常见错误是把 λ 设成 5 甚至 10此时预测损失压过其他两项模型本质变成了 MLP只是套了一层 VAE 的外壳。反过来β 太大也不好KLD 会占据主导编码器把所有样本都映射到先验附近导致模型的预测与输入几乎无关。我一般以 β0.1、λ1 作为起点观察重建损失和 KLD 是否都在合理范围然后再微调。3. 截面数据准备对齐、去极值与没有未来函数的划分3.1 特征矩阵怎么搭三维张量、行业中性化和市值中性化数据准备决定复现结果的真实性。截面收益预测的数据通常组织成一个三维数组shape 为 [交易日数 T, 股票数 N, 特征数 F]。每个日期切面是一个 N×F 的矩阵这一天的每一行代表一只股票的特征。第一步是清洗原始行情。停牌期间的收益率要填成 NaN特征值也要对应处理不能简单用 0 填充否则模型会把“停牌”学成一种有收益的状态。通常的做法是如果股票在某日停牌当天的所有特征置为 NaN在构造训练样本时直接丢弃该行。回测时则要注意停牌股在预测日是不可交易的不能列入组合。第二步是行业中性化和市值中性化。这一步的目的不是丢弃信息而是去掉行业内共同的系统性波动。常见做法是对每个特征在每月或每日截面上做一次回归特征值 行业哑变量 对数市值 残差最终使用残差作为模型输入。原因是股票收益的很大一部分由行业风格和市值风格驱动如果不过滤掉这些主导成分VAE 学到的主要是风格而不是个股层面的 alpha。下面是一个最小化的中性化实现import numpy as np import pandas as pd def neutralize_factor(raw_factor, industry_df, log_mv): # raw_factor: 某一天截面上所有股票的因子值 Series # industry_df: 同一截面的行业哑变量 DataFrame # log_mv: 同一截面的对数市值 Series X pd.concat([industry_df, log_mv], axis1) X[const] 1.0 beta, _, _, _ np.linalg.lstsq(X.values, raw_factor.values, rcondNone) resid raw_factor.values - X.values beta return pd.Series(resid, indexraw_factor.index)代码里的关键是最小二乘残差np.linalg.lstsq把因子值投影到行业和市值张成的空间残差就是剔除这两个风格之后的成分。如果某只股票所在行业样本量太少导致哑变量出现共线性可以先在行业列上去掉样本数少于 10 的小行业或把这些行业合并到“其他”类。中性化必须在每个截面上独立做不能用全样本回归否则仍然是信息泄漏。3.2 时间切片划分训练/验证/测试按时间滚动截面收益预测里数据不能随机 shuffle。原因很简单股票收益存在时间序列相关性如果训练集里混入未来的样本模型等于提前看到了答案回测指标会虚高到完全没有参考价值。我一般按时间顺序切分dates sorted(close_df.index) train_dates dates[:300] valid_dates dates[300:360] test_dates dates[360:420]训练集 300 个交易日、验证集 60 个、测试集 60 个这是比较常见的最小配置。验证集用来选超参数测试集只用于最终评估。需要滚动窗口时可以每 20 个交易日把训练集的起点往后挪一段模拟真实的滚动复现。这里有一个容易被忽略的点验证集和测试集不能参与任何标准化参数的拟合只能应用训练集计算好的参数。3.3 去极值与截面标准化均值方差只能用训练集算金融特征数据里经常出现极端值。比如某只小盘股单日换手率突然到 30%或市盈率因为盈利接近零变成几百这些离群点会主导 MSE 损失。常见做法是 MAD 去极值对每个截面上的特征计算中位数和绝对偏差把落在中位数 ± 3 倍调整 MAD 之外的观测值截断。调整系数 1.483 是为了让 MAD 在正态假设下等价于标准差。标准化这一步是复现论文里最容易翻车的地方。正确的做法是只在训练集上拟合均值和方法def fit_zscore(factor_df, fit_dates): sub factor_df.loc[fit_dates] mean sub.mean(axis0) std sub.std(axis0) std[std 1e-8] 1.0 # 防止常数特征除零 return mean, std def apply_zscore(factor_df, mean, std): return (factor_df - mean) / std这段代码里fit_dates严格限定为训练集日期mean和std保存下来后再应用到验证集和测试集。如果直接把整个 DataFrame 的.mean()和.std()算出来用测试集信息就已经参与了训练这就是“隐性未来函数”。另外标准化的口径要和模型输入对齐。通常对每个因子在时间维度上做标准化即以每只股票的历史分布为基准也有论文按每天横截面上做标准化以全市场股票的当期分布为基准。两种口径都有道理前者更适合处理因子值本身的量纲差异后者更适合横截面排序任务。关键是一旦选定了一种口径训练、验证、测试都必须保持一致不能用混的。4. 核心代码复盘用 PyTorch 复现 VAE 收益预测的完整流程4.1 模型定义编码器、解码器与预测头放一起下面的代码是一个可以直接跑通的 StockVAE 模型括号里是复现论文时常用的默认参数。编码器两层、解码器两层、预测头一层属于轻量配置适合特征维度在 30 到 100 之间的常见因子库。import torch import torch.nn as nn class StockVAE(nn.Module): def __init__(self, feat_dim, latent_dim32, beta0.1, dropout0.2): super().__init__() # 编码器把高维特征压到隐变量的均值和方差 self.encoder nn.Sequential( nn.Linear(feat_dim, 256), nn.LeakyReLU(0.2), nn.Dropout(dropout), nn.Linear(256, 128), nn.LeakyReLU(0.2), nn.Dropout(dropout), ) self.mu_layer nn.Linear(128, latent_dim) self.logvar_layer nn.Linear(128, latent_dim) # 解码器从隐变量重建原始特征 self.decoder nn.Sequential( nn.Linear(latent_dim, 128), nn.LeakyReLU(0.2), nn.Linear(128, 256), nn.LeakyReLU(0.2), nn.Linear(256, feat_dim), ) # 预测头只用隐变量预测未来收益 self.predictor nn.Sequential( nn.Linear(latent_dim, 64), nn.ReLU(), nn.Linear(64, 1), ) def reparameterize(self, mu, logvar): std torch.exp(0.5 * logvar) eps torch.randn_like(std) return mu eps * std def forward(self, x, return_allFalse): h self.encoder(x) mu, logvar self.mu_layer(h), self.logvar_layer(h) z self.reparameterize(mu, logvar) recon self.decoder(z) pred self.predictor(z) if return_all: return recon, pred, mu, logvar, z return pred这段代码里值得留意的是 Dropout 的位置。股票特征的噪声远大于图像或文本Dropout 放在编码器的每一层之后能显著抑制对截面噪声的过拟合。LeakyReLU 而不是 ReLU是为了避免训练初期梯度稀疏导致某些神经元永久失活。预测头只做一层 64 维的原因前面说过容量太大会让模型绕过隐变量的概率约束。reparameterize函数里std torch.exp(0.5 * logvar)等价于std sqrt(exp(logvar))这样做的好处是网络输出无界的 logvar经指数变换后永远为正数值上比直接输出 std 更稳。eps是标准正态随机数每次前向传播都不同这是 VAE 训练随机性的来源。4.2 重参数化与采样训练用随机性推理用均值训练阶段要用采样后的 z 去参与解码和预测这是 VAE 能学到平滑隐空间的前提。如果训练阶段直接使用 μ 而不是采样后的 z模型会退化成普通的 AutoEncoder隐空间没有概率约束。推理阶段则反过来应该用 μ 代替 z 来做预测以消除采样噪声。我在项目里通常这样处理训练时调用model(x, return_allTrue)推理时先取编码器输出再单独调用predictor。这样做的好处是模型在测试集上的输出完全确定不会因随机种子或采样产生波动有利于后续 IC 计算的稳定性。4.3 训练循环三个 loss 一起反传的写法下面是一个典型的最小训练循环包含重建损失、KLD 和预测损失的组合。def train_one_epoch(model, loader, optimizer, beta0.1, lambda_pred1.0): model.train() total_loss 0.0 total_samples 0 for x_batch, y_batch in loader: # x_batch: [batch_size, feat_dim]; y_batch: [batch_size, 1] recon, pred, mu, logvar, z model(x_batch, return_allTrue) recon_loss nn.MSELoss()(recon, x_batch) kl_loss -0.5 * torch.mean( 1 logvar - mu.pow(2) - logvar.exp() ) pred_loss nn.MSELoss()(pred, y_batch) loss recon_loss beta * kl_loss lambda_pred * pred_loss optimizer.zero_grad() loss.backward() nn.utils.clip_grad_norm_(model.parameters(), 5.0) optimizer.step() total_loss loss.item() * x_batch.size(0) total_samples x_batch.size(0) return total_loss / total_samples重建损失与预测损失都是 MSE数量级上通常相差不大但 KLD 项在模型刚初始化时可能很小也可能很大。如果发现 loss 曲线震荡剧烈可以先把 beta 设为 0.01等训练稳定后再逐步提高到目标值这个做法叫 KL annealing在复现 VAE 类论文时很实用。clip_grad_norm_的作用是防止个别极端收益样本导致梯度爆炸。金融数据里偶尔会出现极端的收益比如重组复牌涨 50%如果不做梯度裁剪一个 batch 就能把隐空间推到不合理的位置。裁剪阈值一般取 5.0经验上没有给模型带来明显副作用。Oct 优化器建议用 Adam学习率初始 1e-3观察 10 个 epoch 后 loss 不再下降就把学习率降到 3e-4。batch_size 我一般取 512 到 2048因为样本来自多个交易日、多只股票相关性比时序模型低大 batch 能稳定梯度的估计。显存不够时优先减小 batch_size 而不是减小隐维度因为 latent_dim 对模型性能的影响更敏感。4.4 从预测值到 Rank IC验证代码与参数表训练结束后的第一步不是看回测曲线而是看截面上的排序能力。Rank IC 是预测值与实际收益之间的 Spearman 相关系数它只关心排序是否一致不关心预测值的绝对大小。对每天的截面分别计算再取时间平均就能得到一个比较稳定的模型评价指标。import pandas as pd from scipy.stats import spearmanr def eval_rank_ic(model, feature_dict, ret_dict, device): model.eval() ic_list [] with torch.no_grad(): for date, x_df in feature_dict.items(): x torch.tensor(x_df.values, dtypetorch.float32, devicedevice) h model.encoder(x) mu model.mu_layer(h) pred model.predictor(mu).squeeze(-1) y ret_dict[date].values mask pd.notna(y) ic spearmanr(pred.cpu().numpy()[mask], y[mask]).correlation if pd.notna(ic): ic_list.append(ic) return pd.Series(ic_list).mean()这里的feature_dict是按日期组织的验证集特征ret_dict是对应日期的下期收益。推理时我直接取 μ 作为隐变量不重新采样否则同一个日期重复预测会得到不同结果不利于调参比较。Rank IC 的绝对值在 0.02 以下基本没有应用价值0.03 到 0.05 在日频横截面预测里已经算可用的水平具体阈值取决于特征质量和市场状态。关键超参的初始设定可以参考下面这张表参数建议初值调整方向latent_dim32特征多且欠拟合时试 64噪声大过拟合时减到 16beta0.1KLD 塌缩就调小重建崩溃就调大dropout0.2回测不稳定时升到 0.3~0.5lr1e-3训练震荡时降到 3e-4 或 1e-4batch_size512显存足够时用 1024 或 2048lambda_pred1.0预测过拟合明显时降到 0.5需要说明的是latent_dim 并不是越大越好。隐变量维度太高重建损失很轻松就能优化到很小的值但隐空间没有足够的压缩压力KLD 几乎不起作用模型退化成 MLP。维度太低则可能丢失有效信号导致 Rank IC 始终上不去。32 是一个常见的平衡点适合 30~80 维的特征输入。5. 复现论文的避坑指南五个常见翻车现场与解决方法5.1 现象loss 降了但 Rank IC 为 0某开发者跑完 50 个 epoch训练 loss 从 2.1 降到 0.3看起来一切正常但验证集上的 Rank IC 始终在 0.01 附近几乎等于随机。原因是预测损失权重 lambda_pred 设得过高比如 5 或 10模型花全力拟合收益编码器和解码器很快进入“一个学一个忘”的状态隐变量 z 完全被预测任务绑架重建损失形同虚设。解决办法是把 lambda_pred 降回 1.0同时检查训练日志里重建 loss 的绝对值是否在逐步下降。如果重建 loss 几乎没有变化说明模型根本没有在学“特征的结构”只是在背收益。另一个快速诊断是直接看编码器输出的 z 在不同样本上的方差如果近似为 0说明编码器把所有样本都映射到了同一个点这样的 z 自然无法提供排序信息。5.2 现象全样本归一化造成隐性未来函数训练时指标很好Rank IC 能到 0.06但一放到新数据上就崩到 0。最常见原因是在做特征标准化时直接用了df.mean()和df.std()而 df 包含了验证集和测试集日期。标准化参数一旦用了未来数据模型在训练时就“见过”测试集的分布回测结果自然虚高实盘中数据分布与测试集不完全一致立刻显原形。解决方法是严格按时间划分先用训练集日期拟合 mean 和 std然后保存下来应用到验证集和测试集。每次做完一步我都习惯问自己一句“这一步有没有用到未来信息”如果用了哪怕只是一丁点结果都不能信。5.3 现象KLD 塌缩隐空间失去区分度KLD 项在训练几百个 step 后迅速降到 0.01 以下看起来是“模型已经完美对齐先验”实际上意味着编码器输出的后验分布几乎就是标准正态分布不同股票的 z 没有差异预测头只能输出一个常数级别的预测。这个现象叫 posterior collapse在 VAE 里很常出现。主要原因有几种β 太大KLD 在总损失里权重过高解码器能力太强可以不用 z 也能重建特征数据特征本身信息量小模型选择“忽略输入”作为最省力的策略。解决方法是先调小 β比如从 1.0 降到 0.1 甚至 0.01观察重建 loss 是否明显下降。如果还不行就削减解码器的容量把中间层从 128 改成 32逼迫模型必须利用 z 才能完成重建。还有一种方法是 KL annealing前 20 个 epoch 让 β 从 0 线性升到目标值给编码器一个先学会编码的时间窗口。5.4 现象推理时分布漂移预测随市场状态失效模型在验证集上表现稳定但进入测试期的某一段后 Rank IC 突然转负。原因是股票特征分布不是平稳的市场牛熊切换时均值、方差都会变化。模型如果用了 BatchNorm训练阶段的 running_stat 属于训练分布推理时如果输入分布漂移BatchNorm 计算出来的归一化结果会偏离预期。解决方法是推理阶段固定 BatchNorm 的统计量。PyTorch 里model.eval()会让 BatchNorm 使用训练阶段累计的 running_mean 和 running_var但如果训练阶段的统计量已经陈旧就需要定期用最近的训练窗口重新估计。另一个做法是不用 BatchNorm改用 LayerNorm 或纯 Dropout避免统计量过度依赖训练集的分布。附带的提醒是截面标准化参数也需要定期滚动更新不能一套参数用半年。5.5 现象随机种子敏感同一代码结果差异很大VAE 的训练过程涉及采样本身就带随机性。即便固定了全局随机种子PyTorch 的 CUDA 卷积或矩阵运算在不同设备上也可能产生微小差异。在金融数据里信号本身很弱Rank IC 的差异容易被放大。一次复现时固定 seed 得到的 Rank IC 是 0.035换一个 seed 变成 0.018这种情况并不罕见。解决方法是固定所有能固定的随机源Python 的 random、NumPy 的 seed、PyTorch 的 manual_seed以及 DataLoader 里的 worker seed。评估模型时统一用 μ 而不是采样 z减少推理阶段的随机性。更稳妥的做法是每个超参数组合跑 3 到 5 个随机种子取平均值作为该组合的代表值而不是用单次结果做决策。6. 从复现到实盘研究最短验证脚本与最值得调的三组参数6.1 一份能直接跑的验证脚本IC、分组收益和换手率Rank IC 只能说明排序能力最终要落到分组收益和换手率上才敢继续讨论实盘。下面的代码把每天每只股票的预测值按横截面分成 10 组计算每组当期的平均收益再把多空组合的收益和近似换手率一并输出。def cross_section_report(pred_df, ret_df, n_groups10): dates pred_df.index ic_list [] daily_long_short {} turnover_list [] prev_top None for dt in dates: p pred_df.loc[dt] r ret_df.loc[dt] mask p.notna() r.notna() p, r p[mask], r[mask] ic_day spearmanr(p, r).correlation ic_list.append(ic_day) group pd.qcut(p.rank(methodfirst), n_groups, labelsFalse) group_ret r.groupby(group).mean() top set(group[group n_groups - 1].index) if prev_top is not None: turnover 1 - len(top prev_top) / len(prev_top) turnover_list.append(turnover) prev_top top daily_long_short[dt] group_ret.iloc[-1] - group_ret.iloc[0] report { mean_ic: pd.Series(ic_list).mean(), rank_ic: pd.Series(ic_list).median(), long_short_ret: pd.Series(daily_long_short).mean(), turnover: pd.Series(turnover_list).mean() if turnover_list else None, } return report分组收益的意义在于看模型的排序是否在不同收益率区间都有效。如果只有第 1 组和第 10 组有区分度中间组完全随机说明模型可能只捕捉到了极端特征稳健性不如单调递增的分组曲线。换手率则是组合层面的成本指标日频换手率超过 30% 的信号扣掉手续费之后大概率不赚钱。6.2 先调这三个参数beta、latent_dim 与预测周期复现论文时最容易消耗时间的环节是“不知道调什么”。我调参的习惯是先锁死数据、锁死模型结构只动三个最敏感的参数beta、latent_dim 和预测周期。beta 控制的是隐空间的正则强度直接影响 KLD 是否塌缩。先跑 beta 网格 [0.01, 0.05, 0.1, 0.5]每个值固定跑 30 个 epoch记录验证集 Rank IC 和重建 loss。latent_dim 在 beta 定了之后再调从 16、32、64 三个值里选。预测周期需要配合标签构造短的预测周期如 1 日信号衰减慢但换手率高长的预测周期如 10 日换手率低但 alpha 容易被市场吸收通常要结合手续费来定。这三个参数相互影响所以最好不要同时改两个。每轮只动一个其他保持默认然后观察验证集上的表现变化这样能快速定位是模型约束出了问题还是信息瓶颈容量不够或者标签周期本身就不合适。6.3 写在最后一次翻车后我养成的复现习惯有一回我复现一个截面收益预测的模型训练集 Rank IC 做到 0.055测试集也有 0.04数字比很多公开基准都好。后来做模拟盘上线前的数据审查发现我在标准化时不小心把全样本 mean 和 std 存了下来等于模型在训练阶段已经间接看到了测试集的分布。修复泄漏之后真实 Rank IC 只有 0.02。那一次让我养成了一个习惯每写完一段数据处理代码都会回头检查有没有任何一个统计量是在全样本上计算的每跑完一轮实验都先问一句“如果这个结果放到新数据上还能站得住吗”。这种对信息泄漏的敏感度比调参能力更值钱。希望这篇笔记能帮你在复现 VAE 截面收益预测时少走一点弯路把时间花在真正有效的 alpha 验证上而不是花在听上去合理的指标上。祝你复现顺利。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?
咨询建站