多层感知机与反向传播算法(基础篇)
📘

多层感知机与反向传播算法(基础篇)

第 1/3 篇

在MT5里搭一个能反向传播的多层感知机

MetaTrader 5 的 MQL5 环境本身没有现成的神经网络库,但用结构体加数组就能手搓一个多层感知机(MLP),核心是靠反向传播(backpropagation)在线更新权重。

  • 年 3 月 23 日那篇社区示例贴被查看了 3439 次、收到 11 条讨论,说明用 MQL5 写原生 NN 的需求一直有人在碰,只是官方没封装。

反向传播的本质是:前向算输出误差,再沿层反向把误差按权重比例摊给前一层,用学习率步进修正。下面这段是 MLP 权重初始化的骨架,跑之前先把层宽和层数定死,否则数组越界会直接崩 EA。 外汇与贵金属行情具有高杠杆与跳空风险,这类模型只适合做离线特征实验或信号过滤,实盘前务必在策略测试器用真实点差回测。

MQL5 / C++
class="kw">struct Neuron { class="type">class="kw">double value; class="type">class="kw">double bias; class="type">class="kw">double delta; };
class="kw">struct Layer { Neuron neurons[]; class="type">class="kw">double weights[][]; };
Layer net[];
class="type">void InitNet(class="type">int layers[], class="type">int count) {
   ArrayResize(net, count);
   for(class="type">int i=class="num">0;i<count;i++) {
      ArrayResize(net[i].neurons, layers[i]);
      if(i>class="num">0) ArrayResize(net[i].weights, layers[i], layers[i-class="num">1]);
   }
}

「从零造一个能看懂的神经网络」

现成库把训练集丢进去就吐出网络,但黑箱化让交易者很难弄清优化到底怎么发生。Matlab、R、Python、C++ 里这类封装早已泛滥,可一旦依赖现成方案,你对模型底层假设的掌控力就归零。 本文不堆复杂架构,只搭一个极简神经网络结构,把单神经元感知机和多层感知机的运转逻辑拆开看。梯度下降与反向传播是这类网络的训练内核,现有复杂模型多是从这种简单基底长出来的。 对外汇、贵金属量化而言,搞懂基底比直接调库更重要:前者让你在 MT5 上改一行激活函数就能试新逻辑,后者只能祈祷别人写的网络别在极端行情崩。

◍ 从电路神经元到多层网络

  • 年,Warren McCulloch 与 Walter Pitts 用电路搭出了第一个可被计算的神经元模型,这篇论文把「神经元如何工作」第一次落成了数学与电路结构,而不是哲学描述。
  • 年 Kunihiko Fukushima 做出第一个真正的多层神经网络,距离麦卡洛赫—皮茨模型隔了 37 年,说明单层线性阈值模型在很长一段时间里卡住了工程化进度。

早期神经网络的目标只是模仿人脑解通用问题,后来研究重心转向特定任务:如今 MT5 使用者更熟悉的是时间序列预测、图像与文本识别、社交媒体过滤这类垂直应用,而非通用推理。 计算机里的神经元基础单元叫感知机(perceptron),它是后续多层网络反向传播的唯一积木;在 MQL5 里做信号模型时,理解感知机的加权求和—激活结构,比背网络名词更实用。

单神经元分类器的输入输出链路

感知机本质是一个只有单个神经元的二分类模型,靠线性方程把两类样本劈开。它接收一组已加权的输入向量 x=[x1,x2,…,xN],这些分量可以是价格序列、技术指标或者图像像素;每个输入乘上对应突触权重 w_i,再叠一个不受输入约束的偏置 b,得到激活电位 z = Σ(w_i·x_i) + b。 z 随后送进激活函数 σ 压到特定区间,输出神经元最终值。常用 σ 有阶跃、sigmoid、tanh、softmax、ReLU;最原始的 perceptron 用阶跃:z≥0 输出 1.0,否则 0.0,因此只能做二元判定。这与线性回归、逻辑回归同宗,都是输入的加权和映射。 权重的求解不靠解析解,而用随机梯度下降在训练集上迭代估计。若只取两个输入 {x1,x2} 观察,算法会持续调整 w、b 直到两类线性可分并收敛到稳定边界;外汇与贵金属行情里这类线性可分往往只是局部窗口现象,实盘高杠杆下误分风险极大。

「感知机里的随机梯度怎么落到 MT5 代码」

随机梯度下降在感知机里就是每次喂一条样本、算误差、按 w(t+1)=w(t)+learning_rate*(expected-predicted)*x(t) 更新权重,偏差则去掉输入项单独走 bias(t+1)=bias(t)+learning_rate*(expected-predicted)。学习率限制单步修正幅度,epoch 控制全量数据刷几遍,这两者和训练集一起进函数,里面套三层循环:epoch 层、样本层、权重层。 MQL5 的多维数组只有第一维能动态,其余维度得在声明时定死,所以例子里用 #define nINPUT 3 把输入列数锁住。predict 函数把首权重当偏差(不乘输入),其余权重和 X 的对应列做点积后送 activation:大于等于 0 返回 1,否则 0,这就是最原始的神经元输出门。 数组不能按值返回,只能引用传参,train_weights 里直接改原数组,每个 epoch 累加平方误差看下降曲线。下面这段脚本用手写权重 {-0.1, 0.2065, -0.2342} 在 5 行小数据集上跑,学习率 0.1、仅 5 个 epoch 就能看到误差平方和逐轮缩小,说明收敛很快。开 MT5 把代码贴进脚本,改 random.seed(42) 之后的数据集,就能复现这套感知机预测。 外汇与贵金属行情受杠杆与跳空影响,用此类线性分类器做信号前务必在模拟盘验证,过拟合概率不低。

MQL5 / C++
class="macro">#define nINPUT class="num">3
class=class="str">"cmt">// Make a prediction with weights
class="kw">template <class="kw">typename Array>
class="type">class="kw">double predict(class="kw">const Array &X[][nINPUT], class="kw">const Array &weights[], class="kw">const class="type">int row=class="num">0)
  {
   class="type">class="kw">double z = weights[class="num">0];
   for(class="type">int i=class="num">0; i<ArrayRange(X, class="num">1)-class="num">1; i++)
     {
      z+=weights[i+class="num">1]*X[row][i];
     }
   class="kw">return activation(z);
  }
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//|                    Transfer neuron activation                    |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">class="kw">double activation(class="kw">const class="type">class="kw">double activation) class=class="str">"cmt">//#
  {
   class="kw">return activation>=class="num">0.0?class="num">1.0:class="num">0.0;
  }
class="type">class="kw">double weights[] = {-class="num">0.1, class="num">0.20653640140000007, -class="num">0.23418117710000003};
class="macro">#define nINPUT class="num">3
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Script program start function                                    |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void OnStart()
  {
class=class="str">"cmt">//---
   random.seed(class="num">42);
   class="type">class="kw">double dataset[][nINPUT] = {      class=class="str">"cmt">//X1     //X2   //Y
                                 {class="num">2.7810836,class="num">2.550537003,class="num">0},
                                 {class="num">1.465489372,class="num">2.362125076,class="num">0},
                                 {class="num">3.396561688,class="num">4.400293529,class="num">0},

常见问题

先搞清单神经元的输入输出链路和激活函数,再扩展到多层结构,最后理解误差如何逐层回传。
输入可取归一化后的价格或指标序列,输出用 0/1 表示涨跌分类,中间经权重求和与激活函数。
小布可读取你的品种页数据,辅助比对预测信号与真实走势,省去手动回测的重复劳动。
常见从 0.01 起做小步长试验,配合批量归一;外汇贵金属波动大,需严控高风险。
层数多提升拟合但易过拟合与梯度消失,建议先用 1~2 隐藏层跑通再逐步加压。