神经网络变得轻松(第二十六部分):强化学习·综合运用
📘

神经网络变得轻松(第二十六部分):强化学习·综合运用

第 3/3 篇

「交叉熵法在策略矩阵上的迭代逻辑」

这段循环把交叉熵法(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。外汇与贵金属市场高杠杆、高波动,这类离线策略寻优仅反映历史样本特征,实盘映射存在偏差可能。

MQL5 / C++
   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 无法编译通过。 外汇与贵金属市场高杠杆、高波动,这类聚类模型仅作辅助参考,信号失效概率不低,实盘前务必在策略测试器用历史数据验证。

常见问题

先随机生成一批策略矩阵跑环境,按收益排序取前段样本,用这些样本的平均分布刷新原矩阵,反复几轮让高收益策略概率变高。
交叉熵只是无梯度地筛样本,而奖励函数直接决定模型学偏还是学对,贵金属外汇高风险下错设奖励会放大亏损概率。
小布可替你加载附带程序、自动跑多轮策略矩阵并标出高概率样本,你只需看结果调奖励参数。
一个管环境交互采样本,一个算交叉熵更新矩阵,一个做回测统计,分开便于改其中一块不碰其余逻辑。
别把历史样本当未来,前段筛选比例设太小易过拟合,建议先用小周期验证再上实盘,风险自负。