數(shù)據(jù)科學(xué)和機(jī)器學(xué)習(xí)第 12(自訓(xùn)練神經(jīng)網(wǎng)絡(luò)能否幫助您跑贏股市?)
概述
如果您已經(jīng)從事過(guò)一段時(shí)間的算法交易者,您很有可能聽(tīng)說(shuō)過(guò)神經(jīng)網(wǎng)絡(luò)。 似乎它們總是制造圣杯交易機(jī)器人的一種推進(jìn)途徑,關(guān)于這一點(diǎn)我不太確定,因?yàn)樽罱K獲得一個(gè)可盈利的系統(tǒng)不光是將神經(jīng)網(wǎng)絡(luò)添加到交易機(jī)器人之中。 更不用說(shuō),您需要了解在使用神經(jīng)網(wǎng)絡(luò)時(shí)您自己的得失,因?yàn)榧词故窃傩〉募?xì)節(jié)也可能意味著成功或失敗,即盈利或虧損。

編輯切換為居中
坦率地講,我認(rèn)為神經(jīng)網(wǎng)絡(luò)對(duì)任何人都不起啥作用,特別若您不愿意弄臟自己的手,因?yàn)楹芏鄷r(shí)候您需要花時(shí)間分析模型、預(yù)處理和縮放輸入數(shù)據(jù)產(chǎn)生的錯(cuò),以及我將在本文中討論的更多內(nèi)容。 我們從人工神經(jīng)網(wǎng)絡(luò)的定義開(kāi)始本文。 什么是人工神經(jīng)網(wǎng)絡(luò)? 簡(jiǎn)而言之,人工神經(jīng)網(wǎng)絡(luò),通常稱為神經(jīng)網(wǎng)絡(luò),是受到構(gòu)成動(dòng)物大腦的生物神經(jīng)網(wǎng)絡(luò)啟發(fā)的一種計(jì)算系統(tǒng)。 若要理解神經(jīng)網(wǎng)絡(luò)的基本組件,請(qǐng)參閱本系列的上一篇文章。 在之前關(guān)于神經(jīng)網(wǎng)絡(luò)的文章中,我解釋了有關(guān)前饋神經(jīng)網(wǎng)絡(luò)的基本知識(shí)。 在本文中,赫茲量化將探討神經(jīng)網(wǎng)絡(luò)的前向驗(yàn)算和后向驗(yàn)算,即神經(jīng)網(wǎng)絡(luò)訓(xùn)練和測(cè)試。 赫茲量化還將根據(jù)最后討論的所有內(nèi)容創(chuàng)建一個(gè)交易機(jī)器人,并將見(jiàn)識(shí)我們的交易機(jī)器人的表現(xiàn)。 在多層感知器神經(jīng)網(wǎng)絡(luò)中,前層的所有神經(jīng)元/節(jié)點(diǎn)都與第二層的節(jié)點(diǎn)互連,依此類推到從輸入到輸出的所有層。 這就是神經(jīng)網(wǎng)絡(luò)能夠找出數(shù)據(jù)集中復(fù)雜關(guān)系的原因。 您擁有的神經(jīng)層越多,您的模型就越能夠理解數(shù)據(jù)集中的復(fù)雜關(guān)系。 這需要付出高昂的計(jì)算成本,并且不一定能保證模型的準(zhǔn)確性,特別是如果模型過(guò)于復(fù)雜而問(wèn)題卻很簡(jiǎn)單。 在大多數(shù)情況下,單隱藏層就足以解決人們?cè)噲D使用這些花哨的神經(jīng)網(wǎng)絡(luò)解決的大多數(shù)問(wèn)題。 這就是為什么我們打算采用單層神經(jīng)網(wǎng)絡(luò)。 前向驗(yàn)算 前向驗(yàn)算中涉及的操作很簡(jiǎn)單,只需幾行代碼即可實(shí)現(xiàn)。 不過(guò),為了令您的神經(jīng)網(wǎng)絡(luò)更靈活,您需要對(duì)矩陣和向量運(yùn)算有深入的了解,因?yàn)樗鼈兪巧窠?jīng)網(wǎng)絡(luò)、以及我們?cè)诒鞠盗兄杏懻摰脑S多機(jī)器學(xué)習(xí)算法的構(gòu)建模塊。 需要知道的一件重要事情是人們?cè)噲D使用神經(jīng)網(wǎng)絡(luò)解決的問(wèn)題類型,因?yàn)椴煌膯?wèn)題需要具有不同配置和不同輸出的不同類型神經(jīng)網(wǎng)絡(luò)。 對(duì)于那些不知道以下問(wèn)題類型的人,譬如是
回歸問(wèn)題
分類問(wèn)題
01: 回歸問(wèn)題
回歸問(wèn)題是我們?cè)噲D預(yù)測(cè)連續(xù)變量的問(wèn)題,例如在交易中,赫茲量化經(jīng)常試圖預(yù)測(cè)市場(chǎng)的下一個(gè)價(jià)格點(diǎn)。 對(duì)于那些還沒(méi)概念的人,我建議閱讀線性回歸。
這類問(wèn)題可由回歸神經(jīng)網(wǎng)絡(luò)解決。
02: 分類問(wèn)題
分類問(wèn)題是我們?cè)噲D預(yù)測(cè)離散/非連續(xù)變量的問(wèn)題。 在交易中,我們可以預(yù)測(cè)信號(hào),比如 0 信號(hào)表示市場(chǎng)朝下,而 1 表示市場(chǎng)朝上。
這類問(wèn)題由分類神經(jīng)網(wǎng)絡(luò)或形態(tài)識(shí)別神經(jīng)網(wǎng)絡(luò)解決,在 MATLAB 中它們被稱為形態(tài)網(wǎng)絡(luò)(patternnets)。
在本文中,我將通過(guò)嘗試預(yù)測(cè)下一階段市場(chǎng)價(jià)格走向來(lái)解決回歸問(wèn)題。
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); }
該前向驗(yàn)算函數(shù)易于閱讀,但是當(dāng)您嘗試操作一切順利時(shí),您應(yīng)該密切關(guān)注的最重要的地方是每一步的矩陣大小。
matrix INPUT = this.matrix_utils.VectorToMatrix(input_v);
這部分值得解釋。由于此函數(shù) VectorToMatrix 在向量中獲取輸入,這是由于即將發(fā)生矩陣運(yùn)算,故這些輸入需要采用矩陣形式。
始終記?。?/p>
第一個(gè)神經(jīng)網(wǎng)絡(luò)輸入矩陣是 nx1 矩陣
權(quán)重矩陣為 HN x n;其中 HN 是當(dāng)前隱藏層中的節(jié)點(diǎn)數(shù),n 是來(lái)自前一層的輸入數(shù)或來(lái)自輸入矩陣的行數(shù)。
偏置矩陣的大小與層的輸出大小相同。
了解這一點(diǎn)非常重要。 它將令您免于有一天在試圖自己解決這個(gè)問(wèn)題時(shí)淹沒(méi)在不確定性之中。 我來(lái)展示一下赫茲量化正在研究的神經(jīng)網(wǎng)絡(luò)的架構(gòu),以便您清楚地明白我們正在做什么。

編輯切換為居中
它只是一個(gè)單層神經(jīng)網(wǎng)絡(luò),這就是為什么在我剛剛展示的函數(shù)中,您在前向驗(yàn)算中沒(méi)有見(jiàn)到循環(huán)。 不過(guò),如果您遵循相同的矩陣方法,并確保我上面解釋的維度,您將能夠?qū)崿F(xiàn)任何復(fù)雜的架構(gòu)。 您已經(jīng)看到了 W 矩陣的前向驗(yàn)算,赫茲量化來(lái)看看如何為模型生成權(quán)重。 生成權(quán)重 為神經(jīng)網(wǎng)絡(luò)生成合適的權(quán)重不僅僅是初始化隨機(jī)值的問(wèn)題。 我學(xué)到了艱難的方式;得到錯(cuò)誤結(jié)果會(huì)在反向驗(yàn)算中給您帶來(lái)各種各樣的麻煩,這會(huì)導(dǎo)致您懷疑,并開(kāi)始調(diào)試您的已經(jīng)硬編碼且很復(fù)雜的代碼。 不正確的權(quán)重初始化會(huì)令整個(gè)學(xué)習(xí)過(guò)程變得乏味和耗時(shí)。 網(wǎng)絡(luò)可能會(huì)卡陷在局部最小值,并且收斂速度可能非常緩慢。 第一步是選擇隨機(jī)值,我更喜歡 42 的隨機(jī)狀態(tài)。 this.W = matrix_utils.Random(0.0, 1.0,1,m_inputs, RANDOM_STATE); 大多數(shù)人最終停在這一步,他們生成權(quán)重,并認(rèn)為僅此而已。 選擇隨機(jī)變量后,赫茲量化需要使用 Glorot 或 He 初始化來(lái)初始化我們的權(quán)重。 Xavier/Glorot 初始化最適合 sigmoid 和 tanh 激活函數(shù),而 He 初始化適用于 RELU 及其變體。He 初始化Xavier 初始化方法計(jì)算為具有均勻正態(tài)分布(U)的隨機(jī)數(shù)。 其公式如下:

其中: n = 節(jié)點(diǎn)的輸入數(shù)。故此,在初始化權(quán)重后,權(quán)重歸一化隨之而來(lái)。 this.W = matrix_utils.Random(0.0, 1.0,1,m_inputs, RANDOM_STATE); ? ?this.W = this.W * 1/sqrt(m_inputs); //He initialization 由于該神經(jīng)網(wǎng)絡(luò)僅有一層,因此只有一個(gè)矩陣來(lái)承載權(quán)重。 激活函數(shù) 由于這是回歸類型的神經(jīng)網(wǎng)絡(luò),因此該網(wǎng)絡(luò)的激活函數(shù)只是回歸激活函數(shù)的變體。 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 ? }; 這些紅色的激活函數(shù),以及更多內(nèi)容默認(rèn)由標(biāo)準(zhǔn)庫(kù)的矩陣提供,閱讀更多。 損失函數(shù) 此回歸神經(jīng)網(wǎng)絡(luò)的損失函數(shù)為: enum loss ? { ? ? LOSS_MSE_ = LOSS_MSE, ? ? LOSS_MAE_ = LOSS_MAE, ? ? LOSS_MSLE_ = LOSS_MSLE, ? ? LOSS_HUBER_ = LOSS_HUBER ? }; 標(biāo)準(zhǔn)庫(kù)提供了更多激活函數(shù),閱讀更多。 使用增量規(guī)則的反向傳播 增量(Delta)規(guī)則是一種梯度下降學(xué)習(xí)規(guī)則,用于更新單層神經(jīng)網(wǎng)絡(luò)中人工神經(jīng)元輸入的權(quán)重。 這是更通用的反向傳播算法的特例。 對(duì)激活函數(shù) g(x) 的神經(jīng)元 j,第 j 神經(jīng)元的權(quán)重 Wji 的增量規(guī)則給出如下:
編輯
其中: ?

是一個(gè)稱為學(xué)習(xí)率的小常數(shù)
是 g 的導(dǎo)數(shù)g(x) 是神經(jīng)元的激活函數(shù)
是目標(biāo)輸出
是實(shí)際輸出

是第 i 個(gè)輸入 這太棒了,赫茲量化現(xiàn)在有一個(gè)公式,如此我們只需要實(shí)現(xiàn)它,對(duì)嗎? 錯(cuò)?。。?這個(gè)公式的問(wèn)題在于,盡管看起來(lái)很簡(jiǎn)單,但在將其轉(zhuǎn)換為代碼時(shí)卻非常復(fù)雜,并且需要您編寫(xiě)一對(duì) for 循環(huán),神經(jīng)網(wǎng)絡(luò)中的這種練習(xí)會(huì)活生生地蠶食掉您的余生。我們需要擁有的正確公式是向我們顯示矩陣運(yùn)算的公式。 我來(lái)為您打造這個(gè):
其中:
= 權(quán)重矩陣的變化

= 損失函數(shù)的導(dǎo)數(shù)

= 逐元素矩陣乘法/哈達(dá)瑪(Hadamard)乘積

= 神經(jīng)元激活矩陣的導(dǎo)數(shù)

= 輸入矩陣。 L 矩陣始終與 O 矩陣具有相同的大小,并且右側(cè)生成的矩陣需要與 W 矩陣具有相同的大小。 否則,您就抓瞎了。赫茲量化看看轉(zhuǎn)換為代碼后的樣子。 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 提供的矩陣庫(kù)替代·數(shù)組進(jìn)行機(jī)器學(xué)習(xí)的好處是,您不必?fù)?dān)心微積分,我的意思是您不必?fù)?dān)心去尋找損失函數(shù)的導(dǎo)數(shù),激活函數(shù)的導(dǎo)數(shù) — 什么都沒(méi)有。
為了訓(xùn)練模型,我們需要考慮兩件事,至少目前,世代和學(xué)習(xí)率表示為 alpha。 如果您閱讀過(guò)我之前關(guān)于梯度下降的文章,您就會(huì)知道我在說(shuō)什么。Epochs:?jiǎn)蝹€(gè) epoch 是指整個(gè)數(shù)據(jù)集完全向前和向后循環(huán)貫穿網(wǎng)絡(luò)。 簡(jiǎn)單來(lái)說(shuō),當(dāng)網(wǎng)絡(luò)看到所有數(shù)據(jù)時(shí)。 世代數(shù)量越大,訓(xùn)練神經(jīng)網(wǎng)絡(luò)所需的時(shí)間就越長(zhǎng),學(xué)習(xí)效果就越好。Alpha: 是您希望梯度下降算法在達(dá)到全局和局部最小值時(shí)采用的步長(zhǎng)大小。 Alpha 通常是介于 0.1 和 0.00001 之間的小值。 此值越大,網(wǎng)絡(luò)收斂越快,但跳過(guò)局部最小值的風(fēng)險(xiǎn)就越高。