交易中的神经网络:搭配区段注意力的参数效率变换器(PSformer)(基础篇)
「用区段注意力给交易 Transformer 瘦身」
在 MT5 里跑序列模型,最头疼的是长周期 K 线序列把显存和推理时间吃光。PSformer 的思路是把输入切成若干固定长度的区段(segment),只在段内和段间做稀疏注意力,参数规模相比标准 Transformer 能压到原来的 30%–40%,这对本地终端实时推理很关键。 区段注意力不是简单降采样。它先对每个 segment 做线性投影得到查询、键、值,再在段内算局部依赖,段间只保留少数路由 token 做全局传递,避免 O(n²) 复杂度。这样 500 根 H1 蜡烛也能在普通笔记本上秒级出信号。 外汇与贵金属杠杆高、滑点突变频繁,这类模型只提供概率倾向,实盘前务必用策略测试器跑至少 3 个月 tick 数据验证过拟合。
多元时序预测里的参数共享思路
做外汇或贵金属的多变量行情预测时,很多人直觉是堆大模型,但研究里有个反直觉现象:简单线性模型在有限数据下反而更稳,原因是复杂度低、不容易对噪声过拟合。对 MT5 上跑 AI 辅助判断的交易者来说,这意味着别一上来就调超大参数量网络,小样本周线/日线态很容易训崩。 Transformer 类架构靠补片(patch)拆序列提取局部语义,PatchTST 用通道无关结构已有不错效果;但多变量时序的时空维度和文本、图像差异很大,仍有大量未挖掘空间。PSformer 这篇工作把参数共享(PS)塞进 Transformer 编码器,每层放一个共享参数模块,含三个带残差连接的全连接层,总体参数量压下来还能保住信息交换。 具体做法是把变量序列拆补片,同位置补片归成一个「区段」,在区段内做注意力抓局部时空关系,再跨区段整合提升精度,并上了 SAM 优化抗过拟合。在长时序预测基准里,PSformer 在 8 个关键数据集中的 6 个优于此前前沿模型——这个比例说明参数高效路线不是玩具,值得在 MT5 用 Python/R 桥接自测一遍。外汇与贵金属杠杆高、滑点突变频繁,任何模型输出都只是概率倾向,实盘前务必小资金验证。
◍ PSformer 怎么把多品种序列喂进注意力
假设输入多元时间序列 X ∈ R^{M×L},M 个变量、回溯窗口长度 L。把 L 均分成 N 个大小为 P 的非重叠补片,L = P×N;来自 M 个变量同一位置上的 P 值拼成第 i 个区段,区段长度 C = M×P。这一步先把横截面维度压进区段,后续才能跨通道融合。 区段时空注意力(SegAtt)先把 X 重塑为 X ∈ R^{C×N},在变换空间用两个雷同架构的模块处理,中间用 ReLU 隔开。每个模块含一个参数共享(PS)块加自注意力;Q、K、V 都 ∈ R^{C×N},由输入沿区段做非线性变换得到,缩放点积注意力把焦点铺在 C 维度上,从而同时学跨通道与跨时间的依赖。 PS 模块由三个带残差连接的全连接层组成,用 W_j ∈ R^{N×N}(j=1,2,3)做可学习线性映射,结构近似带残差的 FeedForward。关键在:整个 PS 模块在编码器里被复用——两个 SegAtt 模块和最终 PS 模块共用同一组参数,参数量降下去但表达力保留。外汇与贵金属行情分布漂移明显,原作者在编码器外调用了 RevIN 做归一化修正,实盘前建议先在 MT5 用历史 tick 验证 RevIN 对该品种的稳定性。 跑完 n 层编码器后,用 W_F ∈ R^{L×F} 把输出投影到预测窗 F,得 X_pred ∈ R^{M×F}。想复现可先按 C=M×P、L=P×N 切数据,再对照 SegAtt 的两阶段残差连法逐层打印张量维度,看哪层形状不对。
「在 MT5 里搭参数共享模块的坑与解法」
PSformer 的 PS 模块原版用三个全连接层,我们换成卷积层做非重叠窗口分析,真正的麻烦不在层本身,而是跨区块共享参数时反向传播的数据保留问题。单层多次重用会让结果缓冲区覆盖前一次前馈输出,打乱前向后向交替后,必须为每次前馈保留中间值或重算,这会直接推高模型计算复杂度。 我们选了第二条路:在雷同神经层之间共享单一参数缓冲区。这里藏着两个陷阱——除了权重矩阵,动量缓冲区也得共享,否则各层更新向量会偏向某一内部层;更隐蔽的是,前馈用的 W 和更新后的 W' 若不一致,误差梯度 G 立刻失配,直接套用会令训练失真。作者推荐 SAM 优化,正是因为它在参数更新前重算梯度,容忍这种不匹配。 具体落地从 CNeuronConvSAMOCL 改起,只替换参数和动量缓冲区的指针,其余维度必须匹配。两个辅助方法 InitBufferLike 和 ReplaceBuffer 负责建零值缓冲和安全的指针替换,后者会删掉多余缓冲以降低 OpenCL 显存占用。 新对象 CNeuronPSBlock 内含两层卷积加残差连接,前两层间用 GELU,第二层后加原始输入残差。Init 方法允许改输出维度,通过交换窗口大小和过滤器数量参数保维度一致;InitPS 则按引用对象复制指针。前馈时我们把残差张量归一化再送进最终卷积层,和原版略不同。 calcInputGradients 里残差分支不显式传梯度,靠之前的指针替换保信息完整;updateInputWeights 用 SAM 时必须逆序更新内部层参数,否则第二次前馈改了结果缓冲会断掉后续层更新。外汇与贵金属模型训练高风险,共享参数逻辑写错可能让整个 EA 在 MT5 回测中 silently 发散。 下面这段是 InitBufferLike 的原样代码,逐行看:先判 master 指针有效,否则退出;buffer 空就 new 一个,失败退出;按 master 长度建零值缓冲,再绑 OpenCL 环境,任一步失败都返回 false,全过才返回 true。 开 MT5 把这段塞进你的卷积层类,先单测 InitBufferLike 能否在 OpenCL 上下文建出同长零缓冲,再接 PS 模块才不会在训练第一步崩。
class="type">bool CNeuronConvSAMOCL::InitBufferLike(CBufferFloat *&buffer, CBufferFloat *master) { if(!master) class="kw">return false; if(!buffer) { buffer = new CBufferFloat(); if(!buffer) class="kw">return false; } if(!buffer.BufferInit(master.Total(), class="num">0)) class="kw">return false; if(!buffer.BufferCreate(master.GetOpenCL())) class="kw">return false; class=class="str">"cmt">//--- class="kw">return true; }