数据科学和机器学习第 12(自训练神经网络能否帮助您跑赢股市?)
概述
如果您已经从事过一段时间的算法交易者,您很有可能听说过神经网络。 似乎它们总是制造圣杯交易机器人的一种推进途径,关于这一点我不太确定,因为最终获得一个可盈利的系统不光是将神经网络添加到交易机器人之中。 更不用说,您需要了解在使用神经网络时您自己的得失,因为即使是再小的细节也可能意味着成功或失败,即盈利或亏损。

编辑切换为居中
坦率地讲,我认为神经网络对任何人都不起啥作用,特别若您不愿意弄脏自己的手,因为很多时候您需要花时间分析模型、预处理和缩放输入数据产生的错,以及我将在本文中讨论的更多内容。 我们从人工神经网络的定义开始本文。 什么是人工神经网络? 简而言之,人工神经网络,通常称为神经网络,是受到构成动物大脑的生物神经网络启发的一种计算系统。 若要理解神经网络的基本组件,请参阅本系列的上一篇文章。 在之前关于神经网络的文章中,我解释了有关前馈神经网络的基本知识。 在本文中,赫兹量化将探讨神经网络的前向验算和后向验算,即神经网络训练和测试。 赫兹量化还将根据最后讨论的所有内容创建一个交易机器人,并将见识我们的交易机器人的表现。 在多层感知器神经网络中,前层的所有神经元/节点都与第二层的节点互连,依此类推到从输入到输出的所有层。 这就是神经网络能够找出数据集中复杂关系的原因。 您拥有的神经层越多,您的模型就越能够理解数据集中的复杂关系。 这需要付出高昂的计算成本,并且不一定能保证模型的准确性,特别是如果模型过于复杂而问题却很简单。 在大多数情况下,单隐藏层就足以解决人们试图使用这些花哨的神经网络解决的大多数问题。 这就是为什么我们打算采用单层神经网络。 前向验算 前向验算中涉及的操作很简单,只需几行代码即可实现。 不过,为了令您的神经网络更灵活,您需要对矩阵和向量运算有深入的了解,因为它们是神经网络、以及我们在本系列中讨论的许多机器学习算法的构建模块。 需要知道的一件重要事情是人们试图使用神经网络解决的问题类型,因为不同的问题需要具有不同配置和不同输出的不同类型神经网络。 对于那些不知道以下问题类型的人,譬如是
回归问题
分类问题
01: 回归问题
回归问题是我们试图预测连续变量的问题,例如在交易中,赫兹量化经常试图预测市场的下一个价格点。 对于那些还没概念的人,我建议阅读线性回归。
这类问题可由回归神经网络解决。
02: 分类问题
分类问题是我们试图预测离散/非连续变量的问题。 在交易中,我们可以预测信号,比如 0 信号表示市场朝下,而 1 表示市场朝上。
这类问题由分类神经网络或形态识别神经网络解决,在 MATLAB 中它们被称为形态网络(patternnets)。
在本文中,我将通过尝试预测下一阶段市场价格走向来解决回归问题。
matrix CRegNeuralNets::ForwardPass(vector &input_v) { matrix INPUT = this.matrix_utils.VectorToMatrix(input_v); matrix OUTPUT; OUTPUT = W.MatMul(INPUT); //Weight X Inputs OUTPUT = OUTPUT + B; //Outputs + Bias OUTPUT.Activation(OUTPUT, ENUM_ACTIVATION_FUNCTION(A_FX)); //Activation Function return (OUTPUT); }
该前向验算函数易于阅读,但是当您尝试操作一切顺利时,您应该密切关注的最重要的地方是每一步的矩阵大小。
matrix INPUT = this.matrix_utils.VectorToMatrix(input_v);
这部分值得解释。由于此函数 VectorToMatrix 在向量中获取输入,这是由于即将发生矩阵运算,故这些输入需要采用矩阵形式。
始终记住:
第一个神经网络输入矩阵是 nx1 矩阵
权重矩阵为 HN x n;其中 HN 是当前隐藏层中的节点数,n 是来自前一层的输入数或来自输入矩阵的行数。
偏置矩阵的大小与层的输出大小相同。
了解这一点非常重要。 它将令您免于有一天在试图自己解决这个问题时淹没在不确定性之中。 我来展示一下赫兹量化正在研究的神经网络的架构,以便您清楚地明白我们正在做什么。

编辑切换为居中
它只是一个单层神经网络,这就是为什么在我刚刚展示的函数中,您在前向验算中没有见到循环。 不过,如果您遵循相同的矩阵方法,并确保我上面解释的维度,您将能够实现任何复杂的架构。 您已经看到了 W 矩阵的前向验算,赫兹量化来看看如何为模型生成权重。 生成权重 为神经网络生成合适的权重不仅仅是初始化随机值的问题。 我学到了艰难的方式;得到错误结果会在反向验算中给您带来各种各样的麻烦,这会导致您怀疑,并开始调试您的已经硬编码且很复杂的代码。 不正确的权重初始化会令整个学习过程变得乏味和耗时。 网络可能会卡陷在局部最小值,并且收敛速度可能非常缓慢。 第一步是选择随机值,我更喜欢 42 的随机状态。 this.W = matrix_utils.Random(0.0, 1.0,1,m_inputs, RANDOM_STATE); 大多数人最终停在这一步,他们生成权重,并认为仅此而已。 选择随机变量后,赫兹量化需要使用 Glorot 或 He 初始化来初始化我们的权重。 Xavier/Glorot 初始化最适合 sigmoid 和 tanh 激活函数,而 He 初始化适用于 RELU 及其变体。He 初始化Xavier 初始化方法计算为具有均匀正态分布(U)的随机数。 其公式如下:

其中: n = 节点的输入数。故此,在初始化权重后,权重归一化随之而来。 this.W = matrix_utils.Random(0.0, 1.0,1,m_inputs, RANDOM_STATE); this.W = this.W * 1/sqrt(m_inputs); //He initialization 由于该神经网络仅有一层,因此只有一个矩阵来承载权重。 激活函数 由于这是回归类型的神经网络,因此该网络的激活函数只是回归激活函数的变体。 RELU: enum activation { AF_ELU_ = AF_ELU, AF_EXP_ = AF_EXP, AF_GELU_ = AF_GELU, AF_LINEAR_ = AF_LINEAR, AF_LRELU_ = AF_LRELU, AF_RELU_ = AF_RELU, AF_SELU_ = AF_SELU, AF_TRELU_ = AF_TRELU, AF_SOFTPLUS_ = AF_SOFTPLUS }; 这些红色的激活函数,以及更多内容默认由标准库的矩阵提供,阅读更多。 损失函数 此回归神经网络的损失函数为: enum loss { LOSS_MSE_ = LOSS_MSE, LOSS_MAE_ = LOSS_MAE, LOSS_MSLE_ = LOSS_MSLE, LOSS_HUBER_ = LOSS_HUBER }; 标准库提供了更多激活函数,阅读更多。 使用增量规则的反向传播 增量(Delta)规则是一种梯度下降学习规则,用于更新单层神经网络中人工神经元输入的权重。 这是更通用的反向传播算法的特例。 对激活函数 g(x) 的神经元 j,第 j 神经元的权重 Wji 的增量规则给出如下:
编辑
其中:

是一个称为学习率的小常数
是 g 的导数g(x) 是神经元的激活函数
是目标输出
是实际输出

是第 i 个输入 这太棒了,赫兹量化现在有一个公式,如此我们只需要实现它,对吗? 错!!! 这个公式的问题在于,尽管看起来很简单,但在将其转换为代码时却非常复杂,并且需要您编写一对 for 循环,神经网络中的这种练习会活生生地蚕食掉您的余生。我们需要拥有的正确公式是向我们显示矩阵运算的公式。 我来为您打造这个:
其中:
= 权重矩阵的变化

= 损失函数的导数

= 逐元素矩阵乘法/哈达玛(Hadamard)乘积

= 神经元激活矩阵的导数

= 输入矩阵。 L 矩阵始终与 O 矩阵具有相同的大小,并且右侧生成的矩阵需要与 W 矩阵具有相同的大小。 否则,您就抓瞎了。赫兹量化看看转换为代码后的样子。 for (ulong iter=0; iter<m_rows; iter++) { OUTPUT = ForwardPass(m_x_matrix.Row(iter)); //forward pass pred = matrix_utils.MatrixToVector(OUTPUT); actual[0] = m_y_vector[iter]; preds[iter] = pred[0]; actuals[iter] = actual[0]; //--- INPUT = matrix_utils.VectorToMatrix(m_x_matrix.Row(iter)); vector loss_v = pred.LossGradient(actual, ENUM_LOSS_FUNCTION(L_FX)); LOSS_DX.Col(loss_v, 0); OUTPUT.Derivative(OUTPUT, ENUM_ACTIVATION_FUNCTION(A_FX)); OUTPUT = LOSS_DX * OUTPUT; INPUT = INPUT.Transpose(); DX_W = OUTPUT.MatMul(INPUT); this.W -= (alpha * DX_W); //Weights update by gradient descent } 使用 MQL5 提供的矩阵库替代·数组进行机器学习的好处是,您不必担心微积分,我的意思是您不必担心去寻找损失函数的导数,激活函数的导数 — 什么都没有。
为了训练模型,我们需要考虑两件事,至少目前,世代和学习率表示为 alpha。 如果您阅读过我之前关于梯度下降的文章,您就会知道我在说什么。Epochs:单个 epoch 是指整个数据集完全向前和向后循环贯穿网络。 简单来说,当网络看到所有数据时。 世代数量越大,训练神经网络所需的时间就越长,学习效果就越好。Alpha: 是您希望梯度下降算法在达到全局和局部最小值时采用的步长大小。 Alpha 通常是介于 0.1 和 0.00001 之间的小值。 此值越大,网络收敛越快,但跳过局部最小值的风险就越高。