层次化向量变换器基础:从模块到单一复杂结构的合并逻辑(基础篇)
🧠

层次化向量变换器基础:从模块到单一复杂结构的合并逻辑(基础篇)

(1/3)· 把智驾轨迹预测的 HiVT 拆成可复用的局部与全局建模阶段,交易端该怎么拼回去

偏理论 第 1/3 篇
很多交易者拿到多智能体预测算法就直接套价格序列,忽略局部上下文必须先有至少 2 个时间步的动态参照。少了这一步,向量化过程连变化率都算不出,后面全局交互全是空中楼阁。

「在 MT5 里跑通一套分层向量变换器」

把神经网络塞进 EA 并不玄学,核心是把行情特征做层次化向量映射,再交给变换器做非线性组合。MetaTrader 5 的 MQL5 环境原生支持矩阵与向量运算,足以承载轻量级的在线推断。 下面这段初始化代码在 OnInit 里建了两个权重矩阵:第一层把 10 维行情特征压到 16 维,第二层再升到 8 维。外汇与贵金属杠杆高、滑点随机,实盘前务必用策略测试器跑至少 3 个月 tick 数据验证推断延迟。 权重用 MathRandom 做初始化只是占位,真实训练应在 Python 侧完成再导出常量;直接让 EA 在盘中去梯度下降,大概率因报价事件间隔不稳而发散。

MQL5 / C++
matrix w1 = matrix(class="num">10, class="num">16);
matrix w2 = matrix(class="num">16, class="num">8);
for(class="type">int i=class="num">0;i<w1.Rows();i++)
  for(class="type">int j=class="num">0;j<w1.Cols();j++)
    w1[i][j] = MathRandom();
for(class="type">int i=class="num">0;i<w2.Rows();i++)
  for(class="type">int j=class="num">0;j<w2.Cols();j++)
    w2[i][j] = MathRandom();

◍ HiVT 怎么把多车轨迹预测拆开做

上篇讲过层次化矢量变换器(HiVT)的原理论述,它本是为汽车智驾里多个体运动预测而设计的。核心思路是把预测问题拆成局部上下文提取、全局互动建模等几个阶段,而不是一把梭哈全部场景。 作者把流程分成 3 个阶段。第一阶段提取对象局部上下文:整个场景被切成一组以某个个体为中心的局部区域,每个区域单独抽特征。第二阶段在这些以个体为中心的局部区域之间传信息,记下场景级的全局大范围依赖。 局部加全局的表示合并后,解码器在模型单次前向里就能把场上所有个体的未来轨迹都测出来。上篇我们已经把各个模块分别实现了一遍,本篇要做的就是把它们并成一个完整结构,方便直接在 MT5 外接验证。

在 CNeuronHiVTOCL 里搭 HiVT 主干

HiVT 的整套前向与反向逻辑,被收进 CNeuronHiVTOCL 类,它直接继承全连接基类 CNeuronBaseOCL。所有嵌套对象都声明为静态,构造函数和析构函数留空,真正的初始化全压在 Init 方法里:调用父类初始化之后,先卡一道硬性检查——序列元素至少要有 2 个,因为状态矢量化依赖当前步与前一步两个参考点算动态变化。 内部对象按前馈使用顺序创建,先建环境状态的三维张量(T 时间步 / A 个体 / D 描述向量),单变量序列每个元素的描述向量长度等于序列数乘 2。卷积层生成嵌入后,先转置成 ATD 布局,再用注意力层抓单时间步内的个体-个体局部依赖;这里用了两个注意力子层,键值张量的头数是查询张量的一半。 局部依赖之后回原始布局、加可训练定位编码,接 CNeuronMVMHAttentionMLKV 抓时间依赖。路线图信息在外汇/贵金属场景没有硬约束(RSI 仅在 0–100 是孤立例外),所以用实际轨迹补片嵌入代替:当前状态动态覆盖 1 步,轨迹补片用 3 元素、步长 1 的模块,再经交叉注意力融合。全局互动模块用 4 内层的注意力对整个场景建模,预测阶段转置后跑 3 个连续卷积层组成的 MLP,对外输出若干可能轨迹变体——变体数由外部参数指定,再用 SoftMax 投影到概率域、加权平均得最终轨迹。该多轨迹预测是 HiVT 特点,但外汇/贵金属高杠杆下仅代表概率倾向,非确定性结果。 反向通验 calcInputGradients 镜像前向、逆序分发误差梯度。加权平均层要把梯度同时分给轨迹张量和概率向量,但为避免概率分布误差污染独立轨迹预测,作者刻意不再往投影层深传,只把梯度送进 MLP 预测层,再经全局、局部、时态、个体-个体模块逐层转置回传。updateInputWeights 仅对含可训练参数的内部对象调对应方法,无参数层(如转置)直接跳过。

MQL5 / C++
class CNeuronHiVTOCL    :  class="kw">public CNeuronBaseOCL
  {
class="kw">protected:
   class="type">uint                iHistory;

「把层级时序网络拼成可调用类」

上面这段声明把 HiVT 风格的网络骨架落到了一个 CNeuronHiVTOCL 类里:时间维、轨迹维、预测维三层注意力分别由 cTemporalEncoder、cALEncoder、cGlobalEncoder 承载,cDecoder[3] 注释直接写明是 Agent * Traj * Forecast 三路并行卷积。想验证结构,开 MT5 的 MetaEditor 搜 defNeuronHiVTOCL 就能看到这个类挂进了神经元类型枚举。 Init 里有条硬约束容易踩坑:units_count 小于 2 直接返回 false,且基类初始化要求 window * forecast 作为可见宽度。也就是说时间窗口乘预测步数才是输入张量总维度,调参时若把 forecast 从 1 改成 12,输入规模会等比放大。 iNumTraj 用 MathMax(num_traj, 1) 兜了底,意味着即便外部传 0 轨迹数,内部也至少留 1 条,避免后续转置层 cTransposeTA 出现空维崩溃。外汇与贵金属行情用这类模型推理属于高风险,过拟合历史可能导致样本外表现显著衰减。

MQL5 / C++
class="type">uint iVariables;
class="type">uint iForecast;
class="type">uint iNumTraj;
class=class="str">"cmt">//---
CNeuronBaseOCL           cDataTAD;
CNeuronConvOCL           cEmbeddingTAD;
CNeuronTransposeRCDOCL       cTransposeATD;
CNeuronHiVTAAEncoder         cAAEncoder;
CNeuronTransposeRCDOCL       cTransposeTAD;
CNeuronLearnabledPE        cPosEmbeddingTAD;
CNeuronMVMHAttentionMLKV     cTemporalEncoder;
CNeuronLearnabledPE        cPosLineEmbeddingTAD;
CNeuronPatching            cLineEmbeddibg;
CNeuronMVCrossAttentionMLKV  cALEncoder;
CNeuronMLMHAttentionMLKV     cGlobalEncoder;
CNeuronTransposeOCL          cTransposeADT;
CNeuronConvOCL           cDecoder[class="num">3]; class=class="str">"cmt">// Agent * Traj * Forecast
CNeuronConvOCL           cProbProj;
CNeuronSoftMaxOCL            cProbability; class=class="str">"cmt">// Agent * Traj
CNeuronBaseOCL           cForecast;
CNeuronTransposeOCL          cTransposeTA;
class=class="str">"cmt">//---
class="kw">virtual class="type">bool      Prepare(const CNeuronBaseOCL *history);
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 *NeuronOCL) class="kw">override;
class="kw">virtual class="type">bool      updateInputWeights(CNeuronBaseOCL *NeuronOCL) class="kw">override;
class="kw">public:
                    CNeuronHiVTOCL(class="type">void) {};
                   ~CNeuronHiVTOCL(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 units_count,
                      class="type">uint forecast, class="type">uint num_traj,
ENUM_OPTIMIZATION optimization_type, class="type">uint batch);
class=class="str">"cmt">//---
class="kw">virtual class="type">int       Type(class="type">void)  const   {  class="kw">return defNeuronHiVTOCL; }
class=class="str">"cmt">//---
class="kw">virtual class="type">bool      Save(class="type">int const file_handle);
class="kw">virtual class="type">bool      Load(class="type">int const file_handle);
class=class="str">"cmt">//---
class="kw">virtual class="type">bool      WeightsUpdate(CNeuronBaseOCL *source, class="type">float tau);
class="kw">virtual class="type">void      SetOpenCL(COpenCLMy *obj);
};
class="type">bool CNeuronHiVTOCL::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 units_count,
                      class="type">uint forecast, class="type">uint num_traj,
ENUM_OPTIMIZATION optimization_type, class="type">uint batch)
  {
  if(units_count < class="num">2 ||
     !CNeuronBaseOCL::Init(numOutputs, myIndex, open_cl, window * forecast, optimization_type, batch))
     class="kw">return false;
  iVariables = window;
  iHistory = units_count - class="num">1;
  iForecast = forecast;
  iNumTraj = MathMax(num_traj, class="num">1);
交给小布把模块拼装可视化
这些 HiVT 各阶段的结构关系,小布盯盘的 AIGC 已内置示意图,打开对应品种页即可对照局部与全局层怎么接。

常见问题

因为初始状态向量化伴随动态值操作,需要当前和前一个时间步两个引用来计算数值变化,否则局部上下文特征无法提取。
可以,小布盯盘对应品种页内置了模块结构可视化,把局部上下文提取与全局互动的拼装逻辑画了出来,省去手绘框架。
静态声明令构造函数和析构函数留空,所有嵌套对象和变量统一在 Init 方法初始化,顺序与前馈通验使用顺序呼应,确保对象充分必要。
序列每个元素以二维空间运动及余下个体相对位置变化为特征,故每时间步每元素描述向量维度翻倍。
关于训练与推理的完整讨论见《层次化向量变换器实战:训练流程与推理部署·实战篇》。