神经网络变得轻松(第四十五部分):训练状态探索技能·综合运用
🧠

神经网络变得轻松(第四十五部分):训练状态探索技能·综合运用

(3/3)· 从 DIAYN 到 DADS 的状态覆盖盲区,EDL 如何三步补上并落地 MT5

新手友好 第 3/3 篇

很多人在用分层强化学习训技能时,发现代理者总在熟悉状态里打转,碰到没见过的行情环境就失灵。问题往往不在模型容量,而是前期技能探索没铺满状态空间。本篇顺着前两篇的脉络,把 EDL 这套无监督发现方法拆给你看。

◍ 把账户状态塞进神经网络做训练

这段逻辑干的事很直接:把下一根 K 线对应的账户快照,按 9 个维度喂给 State 数组,再走一遍前馈、取隐层输出、反推 Actor 权重。注意 account[1] 到 account[8] 大多除以 PrevBalance 做了归一,只有 account[5] 和 account[6] 是裸值入栈,这两个字段若本身量纲偏大,可能让梯度更新节奏偏粗。 前馈若失败(feedForward 返回 false),立刻 PrintFormat 打出函数名加行号并 ExpertRemove 退出,说明这套训练不允许静默降级,实盘加载时若日志出现 "-> 行号" 基本就是网络层维度对不上。 训练循环里有个 500 毫秒的节流:每超过 500ms 才用 Comment 刷一次 Actor 的进度和近期平均误差(getRecentAverageError)。这个数字能直观看收敛,若跑几百代还停在 10^-2 量级,倾向是折扣因子或状态归一有问题,不是行情数据不够。 全部跑完会再 PrintFormat 一次最终平均误差并强制 ExpertRemove,意味着它本质是个离线训练片段,不会在图表上常驻盯盘。外汇与贵金属杠杆高,这类自研网络权重仅反映历史样本,换周期可能完全失效。

MQL5 / C++
  State.Add(Buffer[tr].States[i+class="num">1].account[class="num">1] / PrevBalance);
  State.Add((Buffer[tr].States[i+class="num">1].account[class="num">1] - PrevEquity) / PrevEquity);
  State.Add(Buffer[tr].States[i+class="num">1].account[class="num">2] / PrevBalance);
  State.Add(Buffer[tr].States[i+class="num">1].account[class="num">4] / PrevBalance);
  State.Add(Buffer[tr].States[i+class="num">1].account[class="num">5]);
  State.Add(Buffer[tr].States[i+class="num">1].account[class="num">6]);
  State.Add(Buffer[tr].States[i+class="num">1].account[class="num">7] / PrevBalance);
  State.Add(Buffer[tr].States[i+class="num">1].account[class="num">8] / PrevBalance);
  class=class="str">"cmt">//---
  if(!Scheduler.feedForward(GetPointer(State), class="num">1, class="kw">false))
    {
     PrintFormat("%s -> %d", __FUNCTION__, __LINE__);
     ExpertRemove();
     class="kw">break;
    }
  if(!Scheduler.GetLayerOutput(LatentLayer, Result))
    {
     PrintFormat("%s -> %d", __FUNCTION__, __LINE__);
     ExpertRemove();
     class="kw">break;
    }
  State.AssignArray(Result);
  Result.AssignArray(ActorResult);
  if(!Actor.backProp(Result,DiscountFactor,GetPointer(State),class="num">1,class="kw">false))
    {
     PrintFormat("%s -> %d", __FUNCTION__, __LINE__);
     ExpertRemove();
     class="kw">break;
    }
  if(GetTickCount() - ticks > class="num">500)
    {
     class="type">class="kw">string str = StringFormat("%-15s %class="num">5.2f%% -> Error %class="num">15.8f\n",
                                   "Actor", iter * class="num">100.0 / (class="type">class="kw">double)(Iterations),
Actor.getRecentAverageError());
     Comment(str);
     ticks = GetTickCount();
    }
   }
  Comment("");
class=class="str">"cmt">//---
  PrintFormat("%s -> %d -> %-15s %class="num">10.7f", __FUNCTION__, __LINE__, "Actor",
Actor.getRecentAverageError());
  ExpertRemove();
class=class="str">"cmt">//---
  }

「改奖励函数后 EURUSD 回测才平缓走正」

在 EURUSD 的 H1 周期上,用 2023 年前 4 个月历史数据训练自动编码器与代理者,指标取默认参数,样本库放了 50 次验算(含盈利与无盈利),目的是让模型认识回撤。外汇与贵金属杠杆交易高风险,回撤本身就可能吞掉本金。 用 2023 年 5 月数据(未进训练集)在策略测试器验证,初版模型跑出的余额曲线与预期相去甚远,多次迭代仍无法在训练集上盈利,疑点落在自动编码器对状态的预测精度不够。 另写 EA「EDL\StudyActor2.mq5」只改奖励算法:仍用循环预测账户状态变化,但把相对余额变化当作奖励。可比条件下,改奖励的代理者贯穿测试区间显示出相当平缓的盈利增长能力,说明不必重训编码器或改架构,仅调奖励形成方式就可能抬升模型效率。 下面这段是替代代理者里生成奖励的核心循环,关键在把 reward[0] 除以 PrevBalance 再减 1,得到相对余额变化率。

MQL5 / C++
        ActorResult = vector<class="type">class="kw">float>::Zeros(NActions);
        for(action = class="num">0; action < NActions; action++)
          {
           reward = GetNewState(Buffer[tr].States[i].account, action, prof_1l);
           ActorResult[action] = reward[class="num">0]/PrevBalance-class="num">1.0f;
          }

EDL 框架在随机行情里的真实瓶颈

前面几节把 EDL(探索-发现-学习)的链路拆开了:变分自动编码器先把环境状态压成潜在向量,同时当技能标识符,编码器和解码器之间就建起状态↔技能的映射函数。 代理训练时不是追真实 tick,而是追自动编码器给的「预测状态」。这等于把真实市场的随机噪声先滤掉一层,训练稳定性和收敛速度确实会好一些——但代价是,代理上限被自动编码器的状态重建质量死死卡住。 测试阶段跑下来的现象很直接:AE 预测偏差一大,策略在样本外就明显飘。金融市场本身就是高随机、弱可预测的 environment,外汇和贵金属杠杆品种尤其如此,高风险不是修饰词。 真要拿这套去 MT5 做验证,建议先单独测 AE 的重建误差曲线,再决定要不要接 RL 代理;盲目端到端训,大概率是给编码器背锅。

◍ 延伸阅读线索

想继续深挖状态覆盖与无监督技能发现,可顺着三条线走:一条是状态覆盖技能的无监督发现方法,另一条是变分自动编码器(VAE)在特征压缩与重建里的工程实现,还有两条聚焦无奖励函数与动态学习下的技能精通路径。 这些材料原载于 MQL5 系列技术文章,编号分别对应神经网络轻松系列的第 21、43、44 部分,加上独立的一篇状态覆盖技能研究。对做 MT5 端 AIGC 策略原型的人,VAE 那篇值得优先翻,它能直接解释行情隐空间怎么压成低维向量再还原。 贵金属与外汇品种做这类实验波动剧烈、滑点不可控,回测结论只代表历史样本,实盘前务必用策略测试器跑一遍多周期验证。

「随包附带的十个程序文件」

这套基于神经网络的行情建模方案,落地到 MT5 里靠的是一组分工明确的 mq5 与 mqh 文件。样本收集由 Research.mq5 完成,自动编码器训练交给 StudyModel.mq5,代理策略本身则由 StudyActor.mq5 与改了奖励函数的 StudyActor2.mq5 分别承担,最终用 Test.mq5 做模型推演。 底层结构定义放在 Trajectory.mqh,完全参数化调度逻辑在 FQF.mqh,神经网络搭建依赖 NeuroNet.mqh,其 OpenCL 加速代码单独存为 NeuroNet.cl,变分自动编码器的潜伏层由 VAE.mqh 封装。整套压缩包体积 318.64 KB,直接丢进 MT5 的 MQL5 目录即可调阅。 有读者在欧元兑美元 H1 上跑 2023 年前 4 个月的研究优化,真实点数模式下只拿到 4 个样本(2 正 2 负),作者回应称首次运行网络随机初始化、出正负样本属正常,且须用完全优化而非快速优化做全枚举。另一名用户连跑 40–50 个循环仍只得到直线或不平仓的净值曲线,社区指出是跳过了 Research→StudyModel→StudyActor 的顺序,直接跑了 tester 所致。 外汇与贵金属杠杆高、模型过拟合风险大,任何训练结果都只是概率倾向,实盘前务必用策略测试器复跑确认。文件权利归原开发者,部分转载受限,下载后先读 ReadMe 再动参数。

交给小布把 EDL 诊断跑起来
这些诊断小布盯盘的 AIGC 已内置,打开对应品种页即可看到状态覆盖热力与技能触发分布,你专注调参决策就好。

常见问题

DIAYN 追求行为多样性,DADS 预测环境动态收益,二者都因固定技能输入导致状态覆盖不足;EDL 分探索、发现、训练三阶段,用变分自动编码器从状态样本里无监督找技能映射,覆盖更全。
统一采样只是基础办法,重点是让初始集尽量横跨品种不同波动机制;外汇贵金属高风险,极端跳空状态也要纳入,否则技能在实盘容易断片。
它用环境状态同时做输入输出,在潜在空间里逼近状态空间与应触发技能的隐映射,不需要教导员标签,纯从样本里压出结构。
文末给出的程序是 MT5 脚本形态,小布盯盘目前提供状态覆盖看板而非训练后端,你可把跑出的日志丢给小布做覆盖诊断。
它的探索阶段只要求状态样本覆盖,不依赖优秀操作示范;发现阶段靠生成模型找状态-技能联系,训练阶段再 refin 策略,所以冷启动也可行。