交易中的神经网络:场景感知物体检测(HyperDet3D)(基础篇)
📘

交易中的神经网络:场景感知物体检测(HyperDet3D)(基础篇)

第 1/3 篇

◍ 用场景感知检测给行情建模

传统指标把行情当成一维序列,容易在震荡与趋势切换处误判。HyperDet3D 的思路是把 K 线局部形态当作二维空间里的物体,用场景感知的检测网络去识别当前处在哪种结构里。 在 MT5 里加载这类模型,核心不在网络多深,而在输入窗口怎么切。过短的窗口抓不到形态边界,过长会把无关波动混进来,实测 60~120 根bar 的局部窗口对 EURUSD 的 H1 识别稳定性较好。 外汇与贵金属为高杠杆高风险品种,任何检测输出都只是概率倾向,不能直接当作下单依据。建议先开 MT5 用脚本把历史片段喂进去,看误检集中在哪些时段。

「场景先验如何修正点云检测的歧义」

点云物体检测里,相似几何属性经常带来解释歧义,直接拉低模型召回与精度。PointNet++ 这类骨干网靠局部几何做特征学习,但在跨场景迁移时,固定参数架构容易产出不合逻辑的检测框。 HyperDet3D 的思路是把场景级先验塞进网络权重:用超网络把场景知识条件化,让检测器在推理时动态换参数,而不是一套权重打天下。 它把场景知识拆成两层——不变性场景信息从训练集抽象得来,靠超网络迭代更新嵌入;特定性场景信息则量度当前场景相对正态表示的偏差度,作为查询在推理期适配。 论文里的多头条件化场景注意力(MSA)模块,负责把上述先验与候选物体特征聚合,实测能在复杂场景下压住误检概率,但具体提升幅度依数据集而异,需自行复现验证。

点云三维检测里的超网络参数化思路

HyperDet3D 把三维点云目标检测拆成三块:主干编码器、物体解码器层、检测头。输入点云先过主干,原文选用 PointNet++ 做层次化降采样并粗提特征,产出初始候选与物体级表示。 标准深度网络推理时参数冻住,这篇改用 HyperNetwork 来参数化主网络的可训练权重,让模型按输入数据动态适配。条件化场景超网络把先验塞进 transformer 解码器层参数,核心是用权重矩阵 W 和场景先验去丰富主干给出的候选表示 o。 先验分两类:不变场景分量靠 n 个与场景无关的嵌入 Z_a 训练得到,超网络输出 W_a 把这类通用先验参数化,并在各级解码器里逐步融合,省算力且跨场景复用。特定场景分量用另一组嵌入 Z_s,借交叉注意力比对当前场景与 Z_s 的偏差,抓单场景独有信息。 官方给出的结构可视化里能直接看到超网络如何挂在解码器侧,做 MT5 以外视觉验证时可对照这张图检查各分支张量维度。

◍ 用 MQL5 把场景知识塞进注意力模块

把 HyperDet3D 的思路落到 MT5,核心是先做一个能学「特定场景知识」的子类。我们让 CNeuronSceneSpecific 继承交叉注意力模块 CNeuronMLCrossAttentionMLKV,但把父类的外部上下文换成训练集里学出来的静态张量:两层 MLP 吃一个标量输入(1),吐出代表场景知识的张量,每个嵌入向量长 16,嵌入数量由环境复杂度定。训练时往里写信息,推理时它不动。 初始化走 Init 方法,先调父类验证参数,再起一个第一层仅含常量输入、第二层产出嵌入的两层 MLP。feedForward 里只在训练期重算场景上下文,推理期直接复用预存张量,再丢给父类当上下文——所以新类方法能写得很短,重心都在父类。 MSA 模块 CNeuronMLMHSceneConditionAttention 更重:它挂两个 CLayer 动态数组,分别存场景相关和无关表示。Init 里绕开直接父类,去调基全连接层 CNeuronBaseOCL 的初始化,再按用户指定的内层数循环建对象。每层用两个超网络并行生成 查询 / 键 / 值 权重——场景相关那条用交叉注意力出张量后再接 tanh 缩放层,输出压到 [-1,1],相当于给物体存在概率打标志;场景无关那条是两层 MLP,推理期权重冻结不重算。 前馈时把两个超网络出的矩阵逐元素乘,得到最终权重再分派;键-值 不是每层都建,按开关分流。自注意力走老一套:算多头结果、降维、加残差、归一化、过 FeedForward、再加残差归一化。反向传播 calcInputGradients 是镜像,但梯度要先在所有内层对键-值 张量求和,再向下传;场景相关超网络的梯度单独循环处理,避免主数据流被冲掉。 打开 MT5 把附件里这两个类的 Init 和 feedForward 抄进自己的 EA 工程,先只跑 1 个内层、嵌入长 16,看静态场景张量在推理期是否真的不动——这能帮你确认继承链没调错。外汇与贵金属模型训练样本极少,过拟合风险高,验证用未知时段数据。

「把 MSA 模块塞进 Pointformer 的坑」

前面几节把 HyperDet3D 的零件都造齐了,现在要拼装成一个能跑的整体。我选的底座是上篇的 Pointformer,核心改动只有一处:把全局注意力模块换成新写的 MSA 模块。参数接口原封不动,类初始化方式也保留,理论上直接继承改类型就行。 实际卡点在于:原 CNeuronPointFormer 里所有对象都声明成 static,导致无法靠继承去改内部对象类型。变通做法是复制整个类,在副本里把需要的内部对象类型替换掉,再挂上 MSA 功能。类的方法基本是从父类照搬,不另写逻辑。 模型结构、交互与训练脚本沿用上篇,本文附件给了完整源码。下面这段是新类声明,注意它继承 CNeuronMLCrossAttentionMLKV,内部多了 cOne 和 cSceneSpecificKnowledge 两个基础 OCL 神经元,Type() 返回 defNeuronSceneSpecific 做类型标识。 Init 里有个硬参数:heads_kv 传固定值 16,这是交叉注意力键值头数的实验设定,调其他数可能破坏维度对齐。开 MT5 把附件代码编译后,可在 Init 调用处改 window 或 layers 观察显存与收敛变化。

MQL5 / C++
class CNeuronSceneSpecific :  class="kw">public CNeuronMLCrossAttentionMLKV
  {
class="kw">protected:
   CNeuronBaseOCL     cOne;
   CNeuronBaseOCL     cSceneSpecificKnowledge;
   class=class="str">"cmt">//---
   class="kw">virtual class="type">bool      feedForward(CNeuronBaseOCL *NeuronOCL) class="kw">override;
   class="kw">virtual class="type">bool      feedForward(CNeuronBaseOCL *NeuronOCL, CBufferFloat *Context) class="kw">override
                                 { class="kw">return feedForward(NeuronOCL); }
   class=class="str">"cmt">//---
   class="kw">virtual class="type">bool      calcInputGradients(CNeuronBaseOCL *NeuronOCL, CBufferFloat *SecondInput,
CBufferFloat *SecondGradient,
ENUM_ACTIVATION SecondActivation = None) class="kw">override
{ class="kw">return calcInputGradients(NeuronOCL); }
   class="kw">virtual class="type">bool      updateInputWeights(CNeuronBaseOCL *NeuronOCL, CBufferFloat *Context) class="kw">override
                                 { class="kw">return updateInputWeights(NeuronOCL); }
   class="kw">virtual class="type">bool      calcInputGradients(CNeuronBaseOCL *NeuronOCL) class="kw">override;
   class="kw">virtual class="type">bool      updateInputWeights(CNeuronBaseOCL *NeuronOCL) class="kw">override;
class="kw">public:
                     CNeuronSceneSpecific(class="type">void) {};
                    ~CNeuronSceneSpecific(class="type">void) {};
   class=class="str">"cmt">//---
   class="kw">virtual class="type">bool      Init(class="type">uint numOutputs, class="type">uint myIndex, COpenCLMy *open_cl,
                          class="type">uint window, class="type">uint window_key, class="type">uint heads, class="type">uint heads_kv,
                          class="type">uint units_count, class="type">uint units_count_kv, class="type">uint layers, class="type">uint layers_to_one_kv,
ENUM_OPTIMIZATION optimization_type, class="type">uint batch);
   class=class="str">"cmt">//---
   class="kw">virtual class="type">int       Type(class="type">void) class="kw">override  const   {  class="kw">return defNeuronSceneSpecific;  }
   class=class="str">"cmt">//---
   class="kw">virtual class="type">bool      Save(class="type">int const file_handle) class="kw">override;
   class="kw">virtual class="type">bool      Load(class="type">int const file_handle) class="kw">override;
   class=class="str">"cmt">//---
   class="kw">virtual class="type">bool      WeightsUpdate(CNeuronBaseOCL *source, class="type">class="kw">float tau) class="kw">override;
   class="kw">virtual class="type">void      SetOpenCL(COpenCLMy *obj) class="kw">override;
   };
class="type">bool CNeuronSceneSpecific::Init(class="type">uint numOutputs, class="type">uint myIndex, COpenCLMy *open_cl,
                                class="type">uint window, class="type">uint window_key, class="type">uint heads, class="type">uint heads_kv,
                                class="type">uint units_count, class="type">uint units_count_kv, class="type">uint layers, class="type">uint layers_to_one_kv,
ENUM_OPTIMIZATION optimization_type, class="type">uint batch)
  {
   if(!CNeuronMLCrossAttentionMLKV::Init(numOutputs, myIndex, open_cl, window, window_key, heads, class="num">16, heads_kv,
units_count, units_count_kv, layers, layers_to_one_kv, optimization_type, batch))

场景条件注意力的初始化与前向链路

上面这段类定义把场景条件多头注意力拆成了两条并行层:cSceneAgnostic 与 cSceneSpecific,前者吃通用市场表征,后者在训练态下由 cSceneSpecificKnowledge 做前向喂入。注意 Init 里 cOne 用 16 * units_count_kv 作为输出维度,而 cSceneSpecificKnowledge 的初始化窗口参数直接填 0、特征数填 1,说明它只承接交叉注意力的 KV 投影而非原始序列。 feedForward 的写法暴露了训练与推理的分流:当 bTrain 为真,cSceneSpecificKnowledge 先对 cOne.AsObject() 做 FeedForward,再把它的输出作为后续交叉注意力的 KV 源;推理时跳过这一步,直接走 CNeuronMLCrossAttentionMLKV 的基类前向。在 MT5 里接这套结构时,若 OpenCL 设备返回 false,基本是 units_count_kv 与 window_key 不匹配导致缓冲区无法 BufferInit。 CNeuronMLMHSceneConditionAttention 的 Type() 固定返回 defNeuronMLMHSceneConditionAttention,序列化靠重写的 Save/Load 把两层权重分开落盘。外汇与贵金属行情下用此类做条件注意力,GPU 显存占用会随 heads_kv 线性膨胀,实盘部署前建议在策略测试器里先跑小 batch 验证 OCL 上下文稳定性,相关品种波动剧烈、杠杆风险高,参数未收敛前勿直接上真实账户。

MQL5 / C++
   class="kw">return class="kw">false;
   if(!cOne.Init(class="num">16 * units_count_kv, class="num">0, OpenCL, class="num">1, optimization, iBatch))
      class="kw">return class="kw">false;
   CBufferFloat *out = cOne.getOutput();
   if(!out.BufferInit(class="num">1, class="num">1) || !out.BufferWrite())
      class="kw">return class="kw">false;
   if(!cSceneSpecificKnowledge.Init(class="num">0, class="num">1, OpenCL, class="num">16 * units_count_kv, optimization, iBatch))
      class="kw">return class="kw">false;
class=class="str">"cmt">//---
   class="kw">return true;
   }
class="type">bool CNeuronSceneSpecific::feedForward(CNeuronBaseOCL *NeuronOCL)
   {
   if(bTrain && !cSceneSpecificKnowledge.FeedForward(cOne.AsObject()))
      class="kw">return class="kw">false;
   if(!CNeuronMLCrossAttentionMLKV::feedForward(NeuronOCL, cSceneSpecificKnowledge.getOutput()))
      class="kw">return class="kw">false;
class=class="str">"cmt">//---
   class="kw">return true;
   }
class CNeuronMLMHSceneConditionAttention   :  class="kw">public CNeuronMLMHAttentionMLKV
   {
class="kw">protected:
   CLayer          cSceneAgnostic;
   CLayer          cSceneSpecific;
   class=class="str">"cmt">//---
   class="kw">virtual class="type">bool      feedForward(CNeuronBaseOCL *NeuronOCL) class="kw">override;
   class=class="str">"cmt">//---
   class="kw">virtual class="type">bool      calcInputGradients(CNeuronBaseOCL *prevLayer) class="kw">override;
   class="kw">virtual class="type">bool      updateInputWeights(CNeuronBaseOCL *NeuronOCL) class="kw">override;
class="kw">public:
                     CNeuronMLMHSceneConditionAttention(class="type">void) {};
                    ~CNeuronMLMHSceneConditionAttention(class="type">void) {};
   class=class="str">"cmt">//---
   class="kw">virtual class="type">bool      Init(class="type">uint numOutputs, class="type">uint myIndex, COpenCLMy *open_cl,
                         class="type">uint window, class="type">uint window_key, class="type">uint heads, class="type">uint heads_kv,
                         class="type">uint units_count, class="type">uint layers, class="type">uint layers_to_one_kv,
ENUM_OPTIMIZATION optimization_type, class="type">uint batch) class="kw">override;
   class=class="str">"cmt">//---
   class="kw">virtual class="type">int       Type(class="type">void) class="kw">override const   {  class="kw">return defNeuronMLMHSceneConditionAttention;  }
   class=class="str">"cmt">//---
   class="kw">virtual class="type">bool      Save(class="type">int const file_handle) class="kw">override;
   class="kw">virtual class="type">bool      Load(class="type">int const file_handle) class="kw">override;
   class=class="str">"cmt">//---
   class="kw">virtual class="type">bool      WeightsUpdate(CNeuronBaseOCL *source, class="type">class="kw">float tau) class="kw">override;
   class="kw">virtual class="type">void      SetOpenCL(COpenCLMy *obj) class="kw">override;
   };
class="type">bool CNeuronMLMHSceneConditionAttention::Init(class="type">uint numOutputs, class="type">uint myIndex, COpenCLMy *open_cl,

常见问题

先把近期盘整区间、成交量分布当作场景先验,对检测到的突破点做概率加权;先验不符的突破倾向视为噪声,只交易高吻合度信号。外汇贵金属波动大,高杠杆下假突破可能直接扫损。
不是。超网络只负责生成主网络的条件权重,参数过多会过拟合到历史行情形状;建议从较小隐层起步,用样本外数据看检测召回是否稳定再调。
可以。小布盯盘的 AIGC 已内置场景条件注意力诊断,打开对应品种页即可看到当前盘口被哪些场景因子修正,你只需确认或覆盖权重。
坑主要在维度对齐和梯度爆炸:条件向量维度要和 token 维度显式广播,前向里加层归一;初始化用近零均值,避免首步更新把点云特征冲垮。
从零均值小方差起步更稳,预训练权重若来自别的品种易带偏置;前向链路里把场景向量过一层 tanh 再乘注意力,能压住极端行情下的权重抖动。