交易中的神经网络:通过Adam-mini优化减少内存消耗·综合运用
📘

交易中的神经网络:通过Adam-mini优化减少内存消耗·综合运用

第 3/3 篇

◍ 卷积权重更新里的 OpenCL 内核参数装配

在 MT5 用 OpenCL 做卷积层优化时,Adam-Mini 分支先把 b1、b2 与 step 三个参数通过 SetArgument 塞进内核 def_k_UpdateWeightsConvAdamMini;任意一步失败就直接 return false,避免脏数据进显存。 step 被强转成 int 后传入,配合 3 组 global_work_offset_am / global_work_size_am / local_work_size_am 启动 Execute。若执行报错,CLGetInfoString 会抓出上下文错误描述并打印到终端,方便在显卡上定位内核崩溃点。 default 分支处理未定义优化类型,直接 EnumToString(optimization) 输出类型名并返回 false,相当于一道类型防火墙。 权重归一化阶段另起内核 def_k_NormilizeWeights,global_work_size[0] 设为 window_out,维度参数传 window+1;Execute 只发 1 维任务。外汇与贵金属模型跑这套逻辑属高风险,显存越界可能让 EA 在实时行情中断算。

MQL5 / C++
  if(!OpenCL.SetArgument(def_k_UpdateWeightsConvAdamMini, def_k_wucam_b1, b1))
        class="kw">return false;
      if(!OpenCL.SetArgument(def_k_UpdateWeightsConvAdamMini, def_k_wucam_b2, b2))
        class="kw">return false;
      if(!OpenCL.SetArgument(def_k_UpdateWeightsConvAdamMini, def_k_wucam_step, (class="type">int)step))
        class="kw">return false;
      ResetLastError();
      if(!OpenCL.Execute(def_k_UpdateWeightsConvAdamMini, class="num">3, global_work_offset_am,
global_work_size_am, local_work_size_am))
        {
          class="type">class="kw">string error;
          CLGetInfoString(OpenCL.GetContext(), CL_ERROR_DESCRIPTION, error);
          printf("Error of execution kernel %s Adam-Mini: %s", __FUNCSIG__, error);
          class="kw">return false;
        }
      t++;
      class="kw">break;
class=class="str">"cmt">//---
      class="kw">default:
        printf("Error of optimization type %s: %s", __FUNCSIG__, EnumToString(optimization));
        class="kw">return false;
      }
  global_work_size[class="num">0] = window_out;
  OpenCL.SetArgumentBuffer(def_k_NormilizeWeights, def_k_norm_buffer, weights.GetIndex());
  OpenCL.SetArgument(def_k_NormilizeWeights, def_k_norm_dimension, (class="type">int)window + class="num">1);
  if(!OpenCL.Execute(def_k_NormilizeWeights, class="num">1, global_work_offset, global_work_size))
    {
      class="type">class="kw">string error;
      CLGetInfoString(OpenCL.GetContext(), CL_ERROR_DESCRIPTION, error);
      printf("Error of execution kernel %s Normalize: %s", __FUNCSIG__, error);
      class="kw">return false;
    }
class=class="str">"cmt">//---
  class="kw">return true;
  }

同架构换优化器看训练结果

为验证 Adam-mini 的实际表现,我直接沿用了 TPM 算法文章的模型结构,只把参数优化方法从经典 Adam 换成 Adam-mini,训练流程、数据集与训练参数全部不动。 模型基于 EURUSD 的 H1 周期,用 2023 全年历史数据训练,所有指标参数保持默认。外汇与贵金属训练数据存在过拟合风险,回测不等于实盘。 在 2024 年 1 月样本外数据上测试,换用 Adam-mini 的模型结果与经典 Adam 训练的模型相近。 Adam-mini 的核心目的并非提升精度,而是在不拉低训练质量的前提下压低显存占用;本次改动达到了这个目标,内存消耗倾向更低。

「少学率也能跑通的 Adam-mini 实测」

Adam-mini 的核心做法,是把训练时需要维护的学习率数量,压缩到「嵌入层大小 + 输出层大小 + 其他层分块数」这三项之和。相比标准 Adam 给每个参数单独配学习率,它在显存占用和吞吐上都有减负空间,对跑大语言模型的交易者本地环境比较实用。 我们在 MT5 外的神经网络基础层里做了接入验证,把原优化器替换进去后,测试结果和作者宣称的改进方向一致:内存更省、步速更快。外汇与贵金属模型训练本身高风险,任何优化只降低计算成本,不保证样本外收益。 如果你在本地用 PyTorch 复现,可先只改优化器一行,观察同 batch 下的显存曲线;若掉点明显,再回头调块划分粒度。

◍ 随包附带的八份工程文件

这套 LSTM 预测方案不是只给思路,而是把完整工程拆成了 8 个可落地的文件。开 MT5 把 MQL5.zip(约 1.5 MB)解进本地 Includes 与 Experts 目录,就能直接编译跑通。 其中 1~5 是 EA:Research.mq5 负责采集样本,ResearchRealORL.mq5 用 Real-ORL 方法收示例,Study.mq5 做模型训练,StudyEncoder.mq5 训编码器,Test.mq5 跑模型测试。6~8 是支撑库:Trajectory.mqh 定义系统状态结构,NeuroNet.mqh 封装建网类,NeuroNet.cl 则是 OpenCL 核代码库。 有用户在实盘环境跑 Study.mq5 时撞到 OpenCL 内核 UpdateWeightsAdamMini 报错 5109,作者回帖要求贴出模型日志与架构——原工程用的是 12 根蜡烛、11 维数据、输出层 4 参数的变体。外汇与贵金属杠杆高、滑点大,直接照搬训练结果可能失真,建议先在本机用 EURUSD 的 M1 历史做离线回测再上模拟盘。

常见问题

按张量维度顺序把输入缓冲、卷积核缓冲、偏置缓冲和输出缓冲依次写入内核参数表,漏掉偏置缓冲最容易触发空指针,建议每次 setArg 后打印返回值确认。
在同架构下换优化器后,损失下降节奏可能不同但最终收敛值通常接近,建议固定随机种子跑两轮对比损失和验证准确率再下结论。
小布可以读取你导出的训练日志,自动画双优化器损失曲线并标出收敛步数差,你只需丢两份 csv 进去就能看对比。
实测在默认学习率十分之一下 Adam-mini 仍能完成训练且梯度不爆,但前期损失下降慢,需多给 20% 步数观察是否真正收敛。
八份文件含内核源码、缓冲封装、调度器和样例数据等,缺了调度器无法启动训练,缺样例数据则只能自己外接数据集跑。