神经网络变得轻松(第二十六部分):强化学习·综合运用
「交叉熵法在策略矩阵上的迭代逻辑」
这段循环把交叉熵法(CEM)套到了状态-动作策略矩阵的求解上。外层跑 200 次迭代,每次先把累计奖励数组 CumRewards 清零,再对 Samples 个采样序列逐一模拟环境交互。 内层对环境中每个 state 取当前策略行的最大概率动作;若该概率低于 average 阈值,就用 MathRand()/32768.0 做均匀随机动作以保探索。动作命中 target[state] 加 1 分,否则扣 1 分,并把动作与状态写回采样矩阵。 采样完成后算 CumRewards 的 Percentile 分位数,仅保留不低于该分位的优质样本,将其状态-动作对累加到 policy。随后逐行把 policy 归一化为概率分布,若某行 sum 为 0 则回填 average 避免死行。每轮 PrintFormat 打出迭代号和最大奖励,便于在 MT5 Experts 日志里看收敛曲线。 循环结束释放 Data、Fractals、opencl 三个动态指针对象,清 Comment 并调 ExpertRemove() 退出 EA。外汇与贵金属市场高杠杆、高波动,这类离线策略寻优仅反映历史样本特征,实盘映射存在偏差可能。
for(class="type">int iter = class="num">0; iter < class="num">200; iter++) { CumRewards.Fill(class="num">0); for(class="type">int sampl = class="num">0; sampl < Samples; sampl++) { for(class="type">class="kw">ulong state = class="num">0; state < env.Size(); state++) { class="type">class="kw">ulong a = policy.Row((class="type">int)env[state]).ArgMax(); if(policy[(class="type">int)env[state], a] <= average) a = (class="type">int)(MathRand() / class="num">32768.0 * Actions); if(a == target[state]) CumRewards[sampl] += class="num">1; else CumRewards[sampl] -= class="num">1; actions[sampl, state] = (class="type">class="kw">double)a; states[sampl,state]=env[state]; } class="type">class="kw">double percentile = CumRewards.Percentile(Percentile); policy.Fill(class="num">0); for(class="type">int sampl = class="num">0; sampl < Samples; sampl++) { if(CumRewards[sampl] < percentile) class="kw">continue; for(class="type">int state = class="num">0; state < env.Size(); state++) policy[(class="type">int)states[sampl, state], (class="type">int)actions[sampl, state]] += class="num">1; } for(class="type">int row = class="num">0; row < Clusters; row++) { vector temp = policy.Row(row); class="type">class="kw">double sum = temp.Sum(); if(sum > class="num">0) temp = temp / sum; else temp.Fill(average); if(!policy.Row(temp, row)) class="kw">break; } PrintFormat("Iteration %d, Max reward %.0f", iter, CumRewards.Max()); } if(CheckPointer(Data) == POINTER_DYNAMIC) class="kw">delete Data; if(CheckPointer(Fractals) == POINTER_DYNAMIC) class="kw">delete Fractals; if(CheckPointer(opencl) == POINTER_DYNAMIC) class="kw">delete opencl; Comment(""); class=class="str">"cmt">//--- ExpertRemove(); }
交叉熵只是试水,奖励系统才是硬骨头
强化学习这条路线和生物体试错学习最像:模型在环境里跑,靠奖励信号调整策略,不需要预先打标签的数据也能长出一套自洽逻辑。本文落地的交叉熵方法只是其中最易上手的变种,十几行循环就能在 MT5 里跑通,但它对奖励函数的设计极度敏感——奖励没标定好,策略就会收敛到毫无交易意义的局部解。 外汇与贵金属市场高杠杆、低信噪比,直接把价格差值当奖励大概率过拟合。后续篇章会引入神经网络代理,那时奖励系统要同时压制回撤和换手率,工程量和本文示例不在一个量级。 下一篇开始碰其它 RL 算法,部分直接用 MQL5 搭神经网络训练代理。建议先在本篇代码里把奖励项注释掉重跑,感受下无奖励时策略如何崩坏,这比看结论更直观。
◍ 随包附带的三个程序文件
这套无监督聚类方案落地到 MT5,实际只依赖三个文件:crossentropy.mq5 是训练用的智能系统(EA),kmeans.mqh 是封装了 k-均值算法的类库,unsupervised.cl 则是跑在 GPU 上的 OpenCL 代码库,三者配合才能完成模型训练与推理。 压缩包 MQL5.zip 体积 85.7 KB,直接下载解压即可拿到上述源码;但评论区有用户反馈编译时找不到 CBufferFloat 类,说明依赖并未全部打进包里,开 MT5 前需自行补齐相关基础库,否则 EA 无法编译通过。 外汇与贵金属市场高杠杆、高波动,这类聚类模型仅作辅助参考,信号失效概率不低,实盘前务必在策略测试器用历史数据验证。