選自Medium 機(jī)器之心編譯 參與:蔣思源、李亞洲、劉曉坤
本文非常適合初學(xué)者了解如何使用 TensorFlow 構(gòu)建基本的神經(jīng)網(wǎng)絡(luò),它全面展示了構(gòu)建一個(gè) TensorFlow 模型所涉及的概念與模塊。本文所使用的數(shù)據(jù)集可以直接下載,所以有一定基礎(chǔ)的讀者也可以嘗試使用更強(qiáng)的循環(huán)神經(jīng)網(wǎng)絡(luò)處理這一類(lèi)時(shí)序數(shù)據(jù)。 數(shù)據(jù)集地址:http://files./sp500.zip 導(dǎo)入和預(yù)處理數(shù)據(jù) STATWORX 團(tuán)隊(duì)從服務(wù)器爬取股票數(shù)據(jù),并將它們保存為 csv 格式的文件。該數(shù)據(jù)集包含 n=41266 分鐘的記錄,范圍從 2017 年的 4 月到 8 月的 500 支股票和 S&P 500 指數(shù),股票和股指的范圍分布十分廣。
該數(shù)據(jù)集已經(jīng)經(jīng)過(guò)了清理與預(yù)處理,即損失的股票和股指都通過(guò) LOCF'ed 處理(下一個(gè)觀測(cè)數(shù)據(jù)復(fù)制前面的),所以該數(shù)據(jù)集沒(méi)有任何缺損值。 我們可以使用 pyplot.plot('SP500') 語(yǔ)句繪出 S&P 時(shí)序數(shù)據(jù)。 S&P 500 股指時(shí)序繪圖 預(yù)備訓(xùn)練和測(cè)試數(shù)據(jù) 該數(shù)據(jù)集需要被分割為訓(xùn)練和測(cè)試數(shù)據(jù),訓(xùn)練數(shù)據(jù)包含總數(shù)據(jù)集 80% 的記錄。該數(shù)據(jù)集并不需要擾亂而只需要序列地進(jìn)行切片。訓(xùn)練數(shù)據(jù)可以從 2017 年 4 月選取到 2017 年 7 月底,而測(cè)試數(shù)據(jù)再選取剩下到 2017 年 8 月的數(shù)據(jù)。
時(shí)序交叉驗(yàn)證有很多不同的方式,例如有或沒(méi)有再擬合(refitting)而執(zhí)行滾動(dòng)式預(yù)測(cè)、或者如時(shí)序 bootstrap 重采樣等更加詳細(xì)的策略等。后者涉及時(shí)間序列周期性分解的重復(fù)樣本,以便模擬與原時(shí)間序列相同周期性模式的樣本,但這并不不是簡(jiǎn)單的復(fù)制他們的值。 數(shù)據(jù)標(biāo)準(zhǔn)化 大多數(shù)神經(jīng)網(wǎng)絡(luò)架構(gòu)都需要標(biāo)準(zhǔn)化數(shù)據(jù),因?yàn)?tanh 和 sigmoid 等大多數(shù)神經(jīng)元的激活函數(shù)都定義在 [-1, 1] 或 [0, 1] 區(qū)間內(nèi)。目前線性修正單元 ReLU 激活函數(shù)是最常用的,但它的值域有下界無(wú)上界。不過(guò)無(wú)論如何我們都應(yīng)該重新縮放輸入和目標(biāo)值的范圍,這對(duì)于我們使用梯度下降算法也很有幫助。縮放取值可以使用 sklearn 的 MinMaxScaler 輕松地實(shí)現(xiàn)。
注意,我們必須謹(jǐn)慎地確定什么時(shí)候該縮放哪一部分?jǐn)?shù)據(jù)。比較常見(jiàn)的錯(cuò)誤就是在拆分測(cè)試和訓(xùn)練數(shù)據(jù)集之前縮放整個(gè)數(shù)據(jù)集。因?yàn)槲覀冊(cè)趫?zhí)行縮放時(shí)會(huì)涉及到計(jì)算統(tǒng)計(jì)數(shù)據(jù),例如一個(gè)變量的最大和最小值。但在現(xiàn)實(shí)世界中我們并沒(méi)有來(lái)自未來(lái)的觀測(cè)信息,所以必須對(duì)訓(xùn)練數(shù)據(jù)按比例進(jìn)行統(tǒng)計(jì)計(jì)算,并將統(tǒng)計(jì)結(jié)果應(yīng)用于測(cè)試數(shù)據(jù)中。不然的話(huà)我們就使用了未來(lái)的時(shí)序預(yù)測(cè)信息,這常常令預(yù)測(cè)度量偏向于正向。 TensorFlow 簡(jiǎn)介 TensorFlow 是一個(gè)十分優(yōu)秀的框架,目前是深度學(xué)習(xí)和神經(jīng)網(wǎng)絡(luò)方面用戶(hù)最多的框架。它基于 C 的底層后端,但通常通過(guò) Python 進(jìn)行控制。TensorFlow 利用強(qiáng)大的靜態(tài)圖表征我們需要設(shè)計(jì)的算法與運(yùn)算。這種方法允許用戶(hù)指定運(yùn)算為圖中的結(jié)點(diǎn),并以張量的形式傳輸數(shù)據(jù)而實(shí)現(xiàn)高效的算法設(shè)計(jì)。由于神經(jīng)網(wǎng)絡(luò)實(shí)際上是數(shù)據(jù)和數(shù)學(xué)運(yùn)算的計(jì)算圖,所以 TensorFlow 能很好地支持神經(jīng)網(wǎng)絡(luò)和深度學(xué)習(xí)。 總的來(lái)說(shuō),TensorFlow 是一種采用數(shù)據(jù)流圖(data flow graphs),用于數(shù)值計(jì)算的開(kāi)源軟件庫(kù)。其中 Tensor 代表傳遞的數(shù)據(jù)為張量(多維數(shù)組),F(xiàn)low 代表使用計(jì)算圖進(jìn)行運(yùn)算。數(shù)據(jù)流圖用「結(jié)點(diǎn)」(nodes)和「邊」(edges)組成的有向圖來(lái)描述數(shù)學(xué)運(yùn)算。「結(jié)點(diǎn)」一般用來(lái)表示施加的數(shù)學(xué)操作,但也可以表示數(shù)據(jù)輸入的起點(diǎn)和輸出的終點(diǎn),或者是讀取/寫(xiě)入持久變量(persistent variable)的終點(diǎn)。邊表示結(jié)點(diǎn)之間的輸入/輸出關(guān)系。這些數(shù)據(jù)邊可以傳送維度可動(dòng)態(tài)調(diào)整的多維數(shù)據(jù)數(shù)組,即張量(tensor)。 執(zhí)行加法的簡(jiǎn)單計(jì)算圖 在上圖中,兩個(gè)零維張量(標(biāo)量)將執(zhí)行相加任務(wù),這兩個(gè)張量?jī)?chǔ)存在兩個(gè)變量 a 和 b 中。這兩個(gè)值流過(guò)圖形在到達(dá)正方形結(jié)點(diǎn)時(shí)被執(zhí)行相加任務(wù),相加的結(jié)果被儲(chǔ)存在變量 c 中。實(shí)際上,a、b 和 c 可以被看作占位符,任何輸入到 a 和 b 的值都將會(huì)相加到 c。這正是 TensorFlow 的基本原理,用戶(hù)可以通過(guò)占位符和變量定義模型的抽象表示,然后再用實(shí)際的數(shù)據(jù)填充占位符以產(chǎn)生實(shí)際的運(yùn)算,下面的代碼實(shí)現(xiàn)了上圖簡(jiǎn)單的計(jì)算圖:
如上在導(dǎo)入 TensorFlow 庫(kù)后,使用 tf.placeholder() 定義兩個(gè)占位符來(lái)預(yù)儲(chǔ)存張量 a 和 b。隨后定義運(yùn)算后就能執(zhí)行運(yùn)算圖得出結(jié)果。 占位符 正如前面所提到的,神經(jīng)網(wǎng)絡(luò)的初始源自占位符。所以現(xiàn)在我們先要定義兩個(gè)占位符以擬合模型,X 包含神經(jīng)網(wǎng)絡(luò)的輸入(所有 S&P 500 在時(shí)間 T=t 的股票價(jià)格),Y 包含神經(jīng)網(wǎng)絡(luò)的輸出(S&P 500 在時(shí)間 T=t 1 的指數(shù)值)。 因此輸入數(shù)據(jù)占位符的維度可定義為 [None, n_stocks],輸出占位符的維度為 [None],它們分別代表二維張量和一維張量。理解輸入和輸出張量的維度對(duì)于構(gòu)建整個(gè)神經(jīng)網(wǎng)絡(luò)十分重要。
以上代碼中的 None 指代我們暫時(shí)不知道每個(gè)批量傳遞到神經(jīng)網(wǎng)絡(luò)的數(shù)量,所以使用 None 可以保持靈活性。我們后面會(huì)定義控制每次訓(xùn)練時(shí)使用的批量大小 batch_size。 變量 除了占位符,變量是 TensorFlow 表征數(shù)據(jù)和運(yùn)算的另一個(gè)重要元素。雖然占位符在計(jì)算圖內(nèi)通常用于儲(chǔ)存輸入和輸出數(shù)據(jù),但變量在計(jì)算圖內(nèi)部是非常靈活的容器,它可以在執(zhí)行中進(jìn)行修改與傳遞。神經(jīng)網(wǎng)絡(luò)的權(quán)重和偏置項(xiàng)一般都使用變量定義,以便在訓(xùn)練中可以方便地進(jìn)行調(diào)整,變量需要進(jìn)行初始化,后文將詳細(xì)解釋這一點(diǎn)。 該模型由四個(gè)隱藏層組成,第一層包含 1024 個(gè)神經(jīng)元,然后后面三層依次以 2 的倍數(shù)減少,即 512、256 和 128 個(gè)神經(jīng)元。后面的層級(jí)的神經(jīng)元依次減少就壓縮了前面層級(jí)中抽取的特征。當(dāng)然,我們還能使用其它神經(jīng)網(wǎng)絡(luò)架構(gòu)和神經(jīng)元配置以更好地處理數(shù)據(jù),例如卷積神經(jīng)網(wǎng)絡(luò)架構(gòu)適合處理圖像數(shù)據(jù)、循環(huán)神經(jīng)網(wǎng)絡(luò)適合處理時(shí)序數(shù)據(jù),但本文只是為入門(mén)者簡(jiǎn)要地介紹如何使用全連接網(wǎng)絡(luò)處理時(shí)序數(shù)據(jù),所以那些復(fù)雜的架構(gòu)本文并不會(huì)討論。
理解輸入層、隱藏層和輸出層之間變量的維度變換對(duì)于理解整個(gè)網(wǎng)絡(luò)是十分重要的。作為多層感知機(jī)的一個(gè)經(jīng)驗(yàn)性法則,后面層級(jí)的第一個(gè)維度對(duì)應(yīng)于前面層級(jí)權(quán)重變量的第二個(gè)維度。這可能聽(tīng)起來(lái)比較復(fù)雜,但實(shí)際上只是將每一層的輸出作為輸入傳遞給下一層。偏置項(xiàng)的維度等于當(dāng)前層級(jí)權(quán)重的第二個(gè)維度,也等于該層中的神經(jīng)元數(shù)量。 設(shè)計(jì)神經(jīng)網(wǎng)絡(luò)的架構(gòu) 在定義完神經(jīng)網(wǎng)絡(luò)所需要的權(quán)重矩陣與偏置項(xiàng)向量后,我們需要指定神經(jīng)網(wǎng)絡(luò)的拓?fù)浣Y(jié)構(gòu)或網(wǎng)絡(luò)架構(gòu)。因此占位符(數(shù)據(jù))和變量(權(quán)重和偏置項(xiàng))需要組合成一個(gè)連續(xù)的矩陣乘法系統(tǒng)。 此外,網(wǎng)絡(luò)隱藏層中的每一個(gè)神經(jīng)元還需要有激活函數(shù)進(jìn)行非線性轉(zhuǎn)換。激活函數(shù)是網(wǎng)絡(luò)體系結(jié)構(gòu)非常重要的組成部分,因?yàn)樗鼈儗⒎蔷€性引入了系統(tǒng)。目前有非常多的激活函數(shù),其中最常見(jiàn)的就是線性修正單元 ReLU 激活函數(shù),本模型也將使用該激活函數(shù)。
下圖將展示本文構(gòu)建的神經(jīng)網(wǎng)絡(luò)架構(gòu),該模型主要由三個(gè)構(gòu)建塊組成,即輸入層、隱藏層和輸出層。這種架構(gòu)被稱(chēng)為前饋網(wǎng)絡(luò)或全連接網(wǎng)絡(luò),前饋表示輸入的批量數(shù)據(jù)只會(huì)從左向右流動(dòng),其它如循環(huán)神經(jīng)網(wǎng)絡(luò)等架構(gòu)也允許數(shù)據(jù)向后流動(dòng)。 前饋網(wǎng)絡(luò)的核心架構(gòu) 損失函數(shù) 該網(wǎng)絡(luò)的損失函數(shù)主要是用于生成網(wǎng)絡(luò)預(yù)測(cè)與實(shí)際觀察到的訓(xùn)練目標(biāo)之間的偏差值。對(duì)回歸問(wèn)題而言,均方誤差(MSE)函數(shù)最為常用。MSE 計(jì)算預(yù)測(cè)值與目標(biāo)值之間的平均平方誤差。
然而,MSE 的特性在常見(jiàn)的優(yōu)化問(wèn)題上很有優(yōu)勢(shì)。 優(yōu)化器 優(yōu)化器處理的是訓(xùn)練過(guò)程中用于適應(yīng)網(wǎng)絡(luò)權(quán)重和偏差變量的必要計(jì)算。這些計(jì)算調(diào)用梯度計(jì)算結(jié)果,指示訓(xùn)練過(guò)程中,權(quán)重和偏差需要改變的方向,從而最小化網(wǎng)絡(luò)的代價(jià)函數(shù)。穩(wěn)定、快速的優(yōu)化器的開(kāi)發(fā),一直是神經(jīng)網(wǎng)絡(luò)和深度學(xué)習(xí)領(lǐng)域的重要研究。
以上是用到了 Adam 優(yōu)化器,是目前深度學(xué)習(xí)中的默認(rèn)優(yōu)化器。Adam 表示適應(yīng)性矩估計(jì),可被當(dāng)作 AdaGrad 和 RMSProp 這兩個(gè)優(yōu)化器的結(jié)合。 初始化器 初始化器被用于在訓(xùn)練之前初始化網(wǎng)絡(luò)的變量。因?yàn)樯窠?jīng)網(wǎng)絡(luò)是使用數(shù)值優(yōu)化技術(shù)訓(xùn)練的,優(yōu)化問(wèn)題的起點(diǎn)是找到好的解決方案的重點(diǎn)。TensorFlow 中有不同的初始化器,每個(gè)都有不同的初始化方法。在這篇文章中,我使用的是 tf.variance_scaling_initializer(),是一種默認(rèn)的初始化策略。
注意,用 TensorFlow 的計(jì)算圖可以對(duì)不同的變量定義多個(gè)初始化函數(shù)。然而,在大多數(shù)情況下,一個(gè)統(tǒng)一的初始化函數(shù)就夠了。 擬合神經(jīng)網(wǎng)絡(luò) 完成對(duì)網(wǎng)絡(luò)的占位符、變量、初始化器、代價(jià)函數(shù)和優(yōu)化器的定義之后,就可以開(kāi)始訓(xùn)練模型了,通常會(huì)使用小批量訓(xùn)練方法。在小批量訓(xùn)練過(guò)程中,會(huì)從訓(xùn)練數(shù)據(jù)隨機(jī)提取數(shù)量為 n=batch_size 的數(shù)據(jù)樣本饋送到網(wǎng)絡(luò)中。訓(xùn)練數(shù)據(jù)集將分成 n/batch_size 個(gè)批量按順序饋送到網(wǎng)絡(luò)中。此時(shí)占位符 X 和 Y 開(kāi)始起作用,它們保存輸入數(shù)據(jù)和目標(biāo)數(shù)據(jù),并在網(wǎng)絡(luò)中分別表示成輸入和目標(biāo)。 X 的一個(gè)批量數(shù)據(jù)會(huì)在網(wǎng)絡(luò)中向前流動(dòng)直到到達(dá)輸出層。在輸出層,TensorFlow 將會(huì)比較當(dāng)前批量的模型預(yù)測(cè)和實(shí)際觀察目標(biāo) Y。然后,TensorFlow 會(huì)進(jìn)行優(yōu)化,使用選擇的學(xué)習(xí)方案更新網(wǎng)絡(luò)的參數(shù)。更新完權(quán)重和偏差之后,下一個(gè)批量被采樣并重復(fù)以上過(guò)程。這個(gè)過(guò)程將一直進(jìn)行,直到所有的批量都被饋送到網(wǎng)絡(luò)中去,即完成了一個(gè) epoch。 當(dāng)訓(xùn)練達(dá)到了 epoch 的最大值或其它的用戶(hù)自定義的停止標(biāo)準(zhǔn)的時(shí)候,網(wǎng)絡(luò)的訓(xùn)練就會(huì)停止。
在訓(xùn)練過(guò)程中,我們?cè)跍y(cè)試集(沒(méi)有被網(wǎng)絡(luò)學(xué)習(xí)過(guò)的數(shù)據(jù))上評(píng)估了網(wǎng)絡(luò)的預(yù)測(cè)能力,每訓(xùn)練 5 個(gè) batch 進(jìn)行一次,并展示結(jié)果。此外,這些圖像將被導(dǎo)出到磁盤(pán)并組合成一個(gè)訓(xùn)練過(guò)程的視頻動(dòng)畫(huà)。模型能迅速學(xué)習(xí)到測(cè)試數(shù)據(jù)中的時(shí)間序列的位置和形狀,并在經(jīng)過(guò)幾個(gè) epoch 的訓(xùn)練之后生成準(zhǔn)確的預(yù)測(cè)。太棒了! 可以看到,網(wǎng)絡(luò)迅速地適應(yīng)了時(shí)間序列的基本形狀,并能繼續(xù)學(xué)習(xí)數(shù)據(jù)的更精細(xì)的模式。這歸功于 Adam 學(xué)習(xí)方案,它能在模型訓(xùn)練過(guò)程中降低學(xué)習(xí)率,以避免錯(cuò)過(guò)最小值。經(jīng)過(guò) 10 個(gè) epoch 之后,我們完美地?cái)M合了測(cè)試數(shù)據(jù)!最后的測(cè)試 MSE 等于 0.00078,這非常低,因?yàn)槟繕?biāo)被縮放過(guò)。測(cè)試集的預(yù)測(cè)的平均百分誤差率等于 5.31%,這是很不錯(cuò)的結(jié)果。 預(yù)測(cè)和實(shí)際 S&P 價(jià)格的散點(diǎn)圖(已縮放) 請(qǐng)注意其實(shí)還有很多種方法能進(jìn)一步優(yōu)化這個(gè)結(jié)果:層和神經(jīng)元的設(shè)計(jì)、不同的初始化和激活方案的選擇、引入神經(jīng)元的 dropout 層、早期停止法的應(yīng)用,等等。此外,其它不同類(lèi)型的深度學(xué)習(xí)模型,比如循環(huán)神經(jīng)網(wǎng)絡(luò)也許能在這個(gè)任務(wù)中達(dá)到更好的結(jié)果。不過(guò),這在我們的討論范圍之外。 結(jié)論和展望 TensorFlow 的發(fā)布是深度學(xué)習(xí)研究的里程碑事件,其高度的靈活性和強(qiáng)大的性能使研究者能開(kāi)發(fā)所有種類(lèi)的復(fù)雜神經(jīng)網(wǎng)絡(luò)架構(gòu)以及其它機(jī)器學(xué)習(xí)算法。然而,相比使用高級(jí) API 如 Keras 或 MxNet,靈活性的代價(jià)是更長(zhǎng)的建模時(shí)間。盡管如此,我相信 TensorFlow 將繼續(xù)發(fā)展,并成為神經(jīng)網(wǎng)路和和深度學(xué)習(xí)開(kāi)發(fā)的研究和實(shí)際應(yīng)用的現(xiàn)實(shí)標(biāo)準(zhǔn)。我們很多客戶(hù)都已經(jīng)在使用 TensorFlow,或正在開(kāi)發(fā)應(yīng)用 TensorFlow 模型的項(xiàng)目。我們的 STATWORX 的數(shù)據(jù)科學(xué)顧問(wèn)(https://www./de/data-science/)基本都是用 TensorFlow 研究課開(kāi)發(fā)深度學(xué)習(xí)以及神經(jīng)網(wǎng)絡(luò)。 谷歌未來(lái)針對(duì) TensorFlow 的計(jì)劃會(huì)是什么呢?至少在我看來(lái),TensorFlow 缺少一個(gè)簡(jiǎn)潔的圖形用戶(hù)界面,用于在 TensorFlow 后端設(shè)計(jì)和開(kāi)發(fā)神經(jīng)網(wǎng)絡(luò)架構(gòu)。也許這就是谷歌未來(lái)的一個(gè)目標(biāo):) 原文鏈接:https:///mlreview/a-simple-deep-learning-model-for-stock-price-prediction-using-tensorflow-30505541d877 |
|
來(lái)自: 昵稱(chēng)42427018 > 《算法與培訓(xùn)》