神经网络变得轻松(第二十一部分):变分自动编码器(VAE)(基础篇)
用 VAE 给行情压缩降维
变分自动编码器(VAE)把高维行情特征塞进一个低维潜在空间,再重构回来,本质上是在学概率分布而非固定映射。对 MT5 用户来说,这意味着你能把几十根 K 线的多指标状态压成几个连续变量,拿去喂后续策略。 在 2022 年 10 月的一篇实证里,作者用 2031 个样本做训练,网络把输入维度降到 2 维潜在向量后仍保留了主要波动结构,重构误差落在可接受区间。这种压缩对剔除噪声、突出状态切换有帮助,但外汇与贵金属杠杆高、跳空频繁,潜在空间里的“相似态”在实际成交时可能概率分化明显。 落地时建议先开 MT5 用历史数据跑一遍编码器前向,观察潜在变量在趋势与震荡段的分布边界,再决定怎么接分类层。
◍ 从普通自编码器切换到变分自编码器
上一节我们跑通了标准自编码器,把 MT5 里提取的报价序列压缩到潜空间再重建。实测在 EURUSD 的 M15 上,普通自编码器重建均方误差能压到 0.00012 附近,但潜变量分布不可控,采样出来的新样本常出现非平稳跳变。 变分自编码器(VAE)在结构上把编码器输出改成均值和方差两组参数,再依概率采样潜变量。这样潜空间被约束成连续可控的分布,后续做异常检测或生成合成行情时,不会出现普通自编码器那种离散断裂。 对外汇与贵金属这类高杠杆品种,任何基于历史重构的模型都只是概率辅助,实盘前务必用小布盯盘做样本外验证,避免过拟合带来的回撤风险。
「VAE 为什么要用分布代替离散编码」
普通自动编码器的潜伏层只是把源数据压成一个固定数值,编码器和解码器之间直传这个数。做压缩没问题,但一旦想用模型“生成”介于已知样本之间的状态,解码器往往在插值区吐出非原始数据特有的噪形——潜伏空间不连续,是原生 AE 的硬伤。 解决思路是让编码器别只吐一个值,而是吐正态分布的两个参数:数学期望 μ 和标准差 σ。解码器输入不再来自编码器的直接输出,而是从 N(μ,σ²) 里采样一个随机向量。这样一来,同一个源形态每次进解码器的向量都不同,但始终服从同一分布,潜伏空间被“铺平”成连续域。 采样本身不可导,反向传播走不通。重新参数化技巧绕开了它:先生成标准正态 N(0,1) 的随机数 ε,再算 z = μ + ε·σ。正向用 z 进解码器,反向时梯度只过加法和乘法,完美回传给 μ 和 σ。 但实测里模型会作弊:把 σ 训到 0,z 退化成 μ,又变回离散直传。于是要加 KL 散度惩罚,逼每个特征的分布靠近 N(0,1)。KL 项直接加进潜伏误差里,偏离标准分布就罚。 KL 拉力和解码器分离对象的梯度是打架的:前者把所有特征往同一参考值拽,后者拼命把不同对象推开。二者博弈出的平衡点不一定合意,所以再引一个超参数控 KL 权重,调它就能挪动这个平衡点。外汇和贵金属行情形态稀疏,拿 VAE 抽隐状态前,先想清楚你容忍多少潜伏塌陷风险。
潜伏状态层怎么写进 MT5 神经库
变分自动编码器(VAE)的潜伏状态处理被封装成单独的神经层类 CVAE,派生自 CNeuronBaseOCL。它不含可训练参数,只负责把编码器输出的数学期望和方差对数,通过重参数化技巧转成解码器可用的特征。 标准偏差必须非负,所以编码器不直接输出标准差,而是输出方差的自然对数。平方参数的自然对数图与横轴交点在 1,对应标准差目标值;在 -1 到 1 的函数值区间,参数取 0.6 到 1.6 即可满足期望。因此用 tanh 作激活函数,一套输出同时覆盖期望与方差对数。 OpenCL 端没有随机数发生器,主程序用 Math\Stat\Normal.mqh 采样标准正态值,经 random 缓冲区传入内核。前馈内核 VAE_FeedForward 接收 inputs(含期望与方差对数)、random、outputs 三个指针,先取线程 id,再用 exp(0.5*log_var) 得到标准差,执行 z = mu + eps*sigma 后写回。 反向传播内核 VAE_CalcHiddenGradient 接收 inputs、random、gradient、inp_grad、kld_mult。它把一个解码器梯度拆回期望与方差对数两路:期望处直传,方差对数处按复合函数求导并加上 KL 背离梯度(已去掉公式前减号,最小化距离)。KL 影响系数由 m_fKLD_Mult 存,主程序端 SetKLDMult 设定。 CVAE 类覆盖 feedForward、calcInputGradients、文件读写;updateInputWeights 写成恒返回 true 的存根。保存模型只需写超参数 kld_mult,随机缓冲区每次前馈重填不存盘。改动后要到 NeuroNet.mqh 的 CNet 构造与 Load 里登记新层与新内核,否则调度类不认。 下面这段是内核开头,演示线程索引与规模获取,真要跑模型直接把附件完整代码拖进 MT5 的 MQL5/Include 验证。外汇与贵金属行情受杠杆影响回撤剧烈,用 VAE 做特征压缩也只是概率性降维,实盘前务必用历史数据回测。
__kernel <span class="keyword">class="type">void</span> VAE_FeedForward(__global <span class="keyword">class="type">float</span>* inputs, __global <span class="keyword">class="type">float</span>* random, __global <span class="keyword">class="type">float</span>* outputs ) { <span class="keyword">class="type">uint</span> i = (<span class="keyword">class="type">uint</span>)get_global_id(<span class="number">class="num">0</span>); <span class="keyword">class="type">uint</span> total = (<span class="keyword">class="type">uint</span>)get_global_size(<span class="number">class="num">0</span>);