【轉(zhuǎn)】教你打造股市晴雨表——通過LSTM神經(jīng)網(wǎng)絡(luò)預(yù)測(cè)股市

摘要:神經(jīng)網(wǎng)絡(luò)是機(jī)器學(xué)習(xí)中的熱門話題河哑。但是網(wǎng)絡(luò)上有關(guān)LSTM在時(shí)間序列上的應(yīng)用卻很少洞就,我們不妨透過本文來開拓LSTM的應(yīng)用視野夕膀。

作者介紹:

Jakob Aungiers 現(xiàn)就職于匯豐銀行倫敦總部功蜓,擔(dān)任全球資產(chǎn)管理的開發(fā)副總裁逝撬。擅長機(jī)器學(xué)習(xí)冷溃,神經(jīng)網(wǎng)絡(luò)等領(lǐng)域钱磅。

(以下為譯文)

談及機(jī)器學(xué)習(xí),神經(jīng)網(wǎng)絡(luò)無疑是當(dāng)前的熱門話題似枕。因此盖淡,在網(wǎng)絡(luò)上圍繞神經(jīng)網(wǎng)絡(luò)的教程和社區(qū)多不勝數(shù)。現(xiàn)在雖然有大量的公共研究論文和文章涉及LSTM凿歼,但我發(fā)現(xiàn)褪迟,這些理論和例子并沒有顯示出LSTM在時(shí)間序列預(yù)測(cè)上的真正實(shí)力。有鑒于此答憔,我決定以本文作拋磚引玉之用味赃,使用LSTM來預(yù)測(cè)一些時(shí)間序列—例如股市(使用Keras包,對(duì)應(yīng)Python版本為2.7)虐拓。

此項(xiàng)目的完整代碼可以在GitHub頁面上找到(鏈接)心俗。

簡單的正弦波

讓我們從最基本的事情開始----標(biāo)準(zhǔn)正弦波函數(shù)。首先創(chuàng)建數(shù)據(jù)侯嘀,然后模擬這個(gè)函數(shù)的多個(gè)振蕩另凌,以便進(jìn)行LSTM網(wǎng)絡(luò)訓(xùn)練谱轨。我做了一個(gè)excel電子表格,這是一個(gè)幅度和頻率為1(給出角頻率為6.28)的正弦波吠谢,我使用該函數(shù)獲得超過5001個(gè)數(shù)據(jù)點(diǎn)的時(shí)間段土童,時(shí)間增量為0.01。其結(jié)果看起來是這樣的:

(用作訓(xùn)練/測(cè)試文件的鏈接在這里

這些數(shù)據(jù)有什么用呢工坊?LSTM將從這一組窗口大小數(shù)據(jù)值來學(xué)習(xí)正弦波献汗,然后LSTM會(huì)據(jù)此來進(jìn)行時(shí)序預(yù)測(cè)以畫出n步后的波形圖。

我們首先從CSV文件中轉(zhuǎn)換和載入數(shù)據(jù)到numpy數(shù)組中王污,然后喂食LSTM罢吃。Keras LSTM層的工作方式是通過接收3維(N,W昭齐,F(xiàn))的數(shù)字陣列尿招,其中N是訓(xùn)練序列的數(shù)目,W是序列長度阱驾,F(xiàn)是每個(gè)序列的特征數(shù)目就谜。我選擇的一個(gè)序列長度(讀取窗口大小)為50里覆,這可讓網(wǎng)絡(luò)在每個(gè)序列中知道正弦波的形狀丧荐,從而教會(huì)自身基于先前窗口信息的前提下建立序列的模式。序列本身是滑動(dòng)的窗口喧枷,因此每次移動(dòng)1長度后虹统,會(huì)保持與先前窗口的恒定重疊。

長度為50的序列的示例

下面是將訓(xùn)練數(shù)據(jù)CSV加載到正確形狀numpy數(shù)組中的代碼:

def load_data(filename):? ? f =open('sinwave.csv','rb').read()? ? data = f.split('\r\n')? ? sequence_length =50result= []forindexinrange(len(data) - sequence_length):result.append(data[index: index + sequence_length])result= np.array(result)? ? row =round(0.9*result.shape[0])? ? train =result[:row, :]? ? np.random.shuffle(train)? ? x_train = train[:, :-1]? ? y_train = train[:,-1]? ? x_test =result[row:, :-1]? ? y_test =result[row:,-1]? ? x_train = np.reshape(x_train, (x_train.shape[0], x_train.shape[1],1))? ? x_test = np.reshape(x_test, (x_test.shape[0], x_test.shape[1],1))return[x_train, y_train, x_test, y_test]

接下來隧甚,我們需要實(shí)際構(gòu)建網(wǎng)絡(luò)本身车荔。我使用了[1,50,100,1]的網(wǎng)絡(luò)結(jié)構(gòu),其中我們有1個(gè)輸入層(由大小為50的序列組成)呻逆,該輸入層喂食50個(gè)神經(jīng)元給LSTM層夸赫,接著該LSTM層喂食100個(gè)神經(jīng)元給另一個(gè)LSTM層,然后使用一個(gè)線性激活函數(shù)來喂食一個(gè)完全連接的正常層以用于下一個(gè)時(shí)間步的預(yù)測(cè)咖城。

模型構(gòu)建函數(shù)代碼如下:

def build_model(layers):? ? model = Sequential()? ? model.add(LSTM(? ? ? ? input_dim=layers[0],? ? ? ? output_dim=layers[1],? ? ? ? return_sequences=True))? ? model.add(Dropout(0.2))? ? model.add(LSTM(? ? ? ? layers[2],? ? ? ? return_sequences=False))? ? model.add(Dropout(0.2))? ? model.add(Dense(? ? ? ? output_dim=layers[3]))? ? model.add(Activation("linear"))start=time.time()? ? model.compile(loss="mse", optimizer="rmsprop")? ? print"Compilation Time : ",time.time() -startreturnmodel

最后是訓(xùn)練網(wǎng)絡(luò)上的數(shù)據(jù)茬腿,看看我們得到了什么。在該LSTM我只使用了1個(gè)訓(xùn)練時(shí)期宜雀,這有別于需要大量訓(xùn)練數(shù)據(jù)的傳統(tǒng)網(wǎng)絡(luò)切平。因?yàn)槲覀兪褂玫氖呛喌木呖深A(yù)測(cè)模式的正弦波,1訓(xùn)練時(shí)期將足夠獲得非常近似的全sin函數(shù)辐董。

放入run.py模塊后的代碼:

epochs? =1seq_len =50print'Loading data... 'X_train, y_train, X_test, y_test = lstm.load_data('sinwave.csv')print'\nData Loaded. Compiling...\n'model= lstm.build_model([1,50,100,1])model.fit(? ? X_train,? ? y_train,? ? batch_size=512,? ? nb_epoch=epochs,? ? validation_split=0.05)predicted = lstm.predict_point_by_point(model, X_test)

如果你注意到你會(huì)注意到我們?cè)谏厦娴膌oad_data()函數(shù)中悴品,我們將數(shù)據(jù)分為訓(xùn)練/測(cè)試集,這是機(jī)器學(xué)習(xí)問題的標(biāo)準(zhǔn)做法。然而苔严,我們需要注意的是定枷,我們實(shí)際上想要在時(shí)間序列實(shí)現(xiàn)預(yù)測(cè)。

如果我們使用測(cè)試集届氢,我們將運(yùn)行每個(gè)窗口的真實(shí)數(shù)據(jù)來預(yù)測(cè)下一個(gè)時(shí)間步欠窒。下圖是使用該方法后的結(jié)果:

epochs = 1, window size = 50

然而,如果我們想要預(yù)測(cè)許更多的時(shí)間步退子,我們需使用來自測(cè)試數(shù)據(jù)的第一個(gè)窗口作為啟動(dòng)窗口岖妄。 在每個(gè)時(shí)間步,彈出窗口后面的最先條目寂祥,并將下一個(gè)時(shí)間步預(yù)測(cè)附加到窗口的前面荐虐,實(shí)質(zhì)上是移動(dòng)窗口,所以它是慢慢地用預(yù)測(cè)建立自己丸凭,直到窗口都是預(yù)測(cè)值(在我們的例子中福扬,因?yàn)槲覀兊拇翱诖笮?0,這將發(fā)生在50個(gè)時(shí)間步之后)惜犀。 然后忧换,我們無限期地保持這一點(diǎn),預(yù)測(cè)下一步對(duì)未來時(shí)間步驟的預(yù)測(cè)向拆,從而實(shí)現(xiàn)看到趨勢(shì)預(yù)測(cè)。

下圖顯示了僅從真實(shí)測(cè)試數(shù)據(jù)的初始開始窗口預(yù)測(cè)的正弦波時(shí)間序列酪耳,然后預(yù)測(cè)約500步:

epochs = 1, window size = 50

除了簡單的正弦波預(yù)測(cè)浓恳,LSTM還能做更復(fù)雜的預(yù)測(cè)嗎?答案是肯定的碗暗,例如以下的有關(guān)股票市場(chǎng)的時(shí)間序列預(yù)測(cè)颈将。什么?言疗!股票預(yù)測(cè)G缁!是的噪奄。這是LSTM另一個(gè)技能--潛在隱藏趨勢(shì)預(yù)判死姚。

首先我準(zhǔn)備了一個(gè)CSV文件(鏈接),其保存的是標(biāo)準(zhǔn)普爾500股權(quán)指數(shù)從2000年1月到2016年8月的收盤數(shù)據(jù)勤篮。我使它與我們的正弦波數(shù)據(jù)具完全相同的格式都毒,然后運(yùn)行相同的模型。

這之前我們需要對(duì)我們的數(shù)據(jù)做一個(gè)微小的改變碰缔,因?yàn)檎也ㄒ呀?jīng)是一個(gè)很規(guī)范的重復(fù)模式账劲,但股票數(shù)據(jù)是不規(guī)范的。因此為了應(yīng)對(duì)這種情況,我們需要使訓(xùn)練/測(cè)試數(shù)據(jù)的每個(gè)n大小的窗口進(jìn)行標(biāo)準(zhǔn)化瀑焦,以反映從該窗口開始的百分比變化(因此點(diǎn)i = 0處的數(shù)據(jù)將始終為0)腌且。我們將使用以下方程式進(jìn)行歸一化,然后在預(yù)測(cè)過程結(jié)束時(shí)進(jìn)行反標(biāo)準(zhǔn)化榛瓮,以得到預(yù)測(cè)中的真實(shí)世界數(shù):

n =價(jià)格變化的標(biāo)準(zhǔn)化列表[窗口]

p =原始列表[窗口]調(diào)整的每日回報(bào)價(jià)格

標(biāo)準(zhǔn)化公式:

-1)

反標(biāo)準(zhǔn)化公式:

)

在代碼中添加一個(gè)normalise_windows(window_data)函數(shù)铺董,并更新load_data(filename)函數(shù)以包含一個(gè)條件調(diào)用,以及獲取序列長度和規(guī)范化標(biāo)志load_data(filename榆芦,seq_len柄粹,normalise_window):

代碼如下:

def load_data(filename, seq_len, normalise_window):? ? f =open(filename,'rb').read()? ? data = f.split('\r\n')? ? sequence_length = seq_len +1result= []forindexinrange(len(data) - sequence_length):result.append(data[index: index + sequence_length])ifnormalise_window:result= normalise_windows(result)result= np.array(result)? ? row =round(0.9*result.shape[0])? ? train =result[:row, :]? ? np.random.shuffle(train)? ? x_train = train[:, :-1]? ? y_train = train[:,-1]? ? x_test =result[row:, :-1]? ? y_test =result[row:,-1]? ? x_train = np.reshape(x_train, (x_train.shape[0], x_train.shape[1],1))? ? x_test = np.reshape(x_test, (x_test.shape[0], x_test.shape[1],1))return[x_train, y_train, x_test, y_test]def normalise_windows(window_data):? ? normalised_data = []forwindowinwindow_data:? ? ? ? normalised_window = [((float(p) / float(window[0])) -1)forpinwindow]? ? ? ? normalised_data.append(normalised_window)returnnormalised_data

歸一化了如上所述的窗口后,我們現(xiàn)在可以通過LSTM網(wǎng)絡(luò)運(yùn)行我們的股票數(shù)據(jù)匆绣。 讓我們看看它的運(yùn)行情況:

在如上所述的單個(gè)逐點(diǎn)預(yù)測(cè)上運(yùn)行數(shù)據(jù)給出了與實(shí)際相當(dāng)接近的圖形驻右。但這是欺騙性的!為什么崎淳?如果你更仔細(xì)地看堪夭,預(yù)測(cè)線由單一的預(yù)測(cè)點(diǎn)組成,它們?cè)谒鼈冎缶哂姓麄€(gè)先前的真實(shí)歷史窗口拣凹。因此森爽,網(wǎng)絡(luò)并不依賴時(shí)間序列本身,除了每下一個(gè)點(diǎn)可能不會(huì)離最后一點(diǎn)太遠(yuǎn)嚣镜。因此爬迟,即使它得到錯(cuò)誤預(yù)測(cè)的點(diǎn),下一個(gè)預(yù)測(cè)可在考慮真實(shí)歷史后忽略不正確的預(yù)測(cè)菊匿,并允許再次出現(xiàn)錯(cuò)誤付呕。

那么,我們來看看是否真的有一些潛在的模式在價(jià)格中變動(dòng)切可辨別跌捆?接下來讓我們做對(duì)正弦波問題做的同樣事情徽职,讓網(wǎng)絡(luò)預(yù)測(cè)點(diǎn)序列而不是下一個(gè)點(diǎn)。

這樣佩厚,我們現(xiàn)在可以看到姆钉,與作為正弦波序列的正弦波不同,它與真實(shí)數(shù)據(jù)幾乎相同抄瓦,我們的股票數(shù)據(jù)預(yù)測(cè)很快地收斂到某種平衡潮瓶。

epochs = 50, window size = 50

epochs = 1, window size = 50

讓我們進(jìn)一步研究回歸收斂,將我們的預(yù)測(cè)序列限制到50個(gè)未來時(shí)間步長钙姊,然后每次將啟動(dòng)窗口移動(dòng)50單位:

epochs = 1, window size = 50, sequence shift = 50

而當(dāng)epochs增加到400時(shí)(這應(yīng)該使模型模式更準(zhǔn)確)筋讨,我們看到,實(shí)際上它現(xiàn)在只是試圖預(yù)測(cè)幾乎每個(gè)時(shí)間段的向上動(dòng)量摸恍。

epochs = 400, window size = 50, sequence shift = 50

小結(jié):

LSTM的應(yīng)用日益廣泛悉罕,例如文本預(yù)測(cè)赤屋,AI智能聊天,自駕車等許多前沿領(lǐng)域壁袄。 希望本文能有助你開拓LSTM在時(shí)間序列中應(yīng)用的視野类早。

本文由北郵@愛可可-愛生活老師推薦,阿里云云棲社區(qū)組織翻譯嗜逻。

文章原標(biāo)題《LSTM NEURAL NETWORK FOR TIME SERIES PREDICTION》涩僻,作者:Jakob Aungiers ,譯者:伍昆

文章為簡譯栈顷,更為詳細(xì)的內(nèi)容逆日,請(qǐng)查看**原文**

注:本文轉(zhuǎn)自網(wǎng)絡(luò),僅供交流學(xué)習(xí)使用萄凤,權(quán)利歸原作者所有室抽,如有侵權(quán),請(qǐng)聯(lián)系刪除靡努。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末坪圾,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子惑朦,更是在濱河造成了極大的恐慌兽泄,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,743評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件漾月,死亡現(xiàn)場(chǎng)離奇詭異病梢,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)梁肿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門飘千,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人栈雳,你說我怎么就攤上這事〉蘖” “怎么了哥纫?”我有些...
    開封第一講書人閱讀 157,285評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長痴奏。 經(jīng)常有香客問我蛀骇,道長,這世上最難降的妖魔是什么读拆? 我笑而不...
    開封第一講書人閱讀 56,485評(píng)論 1 283
  • 正文 為了忘掉前任擅憔,我火速辦了婚禮,結(jié)果婚禮上檐晕,老公的妹妹穿的比我還像新娘暑诸。我一直安慰自己蚌讼,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,581評(píng)論 6 386
  • 文/花漫 我一把揭開白布个榕。 她就那樣靜靜地躺著篡石,像睡著了一般。 火紅的嫁衣襯著肌膚如雪西采。 梳的紋絲不亂的頭發(fā)上凰萨,一...
    開封第一講書人閱讀 49,821評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音械馆,去河邊找鬼胖眷。 笑死,一個(gè)胖子當(dāng)著我的面吹牛霹崎,可吹牛的內(nèi)容都是我干的珊搀。 我是一名探鬼主播,決...
    沈念sama閱讀 38,960評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼仿畸,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼食棕!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起错沽,我...
    開封第一講書人閱讀 37,719評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤簿晓,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后千埃,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體憔儿,經(jīng)...
    沈念sama閱讀 44,186評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,516評(píng)論 2 327
  • 正文 我和宋清朗相戀三年放可,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了谒臼。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,650評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡耀里,死狀恐怖蜈缤,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情冯挎,我是刑警寧澤底哥,帶...
    沈念sama閱讀 34,329評(píng)論 4 330
  • 正文 年R本政府宣布,位于F島的核電站房官,受9級(jí)特大地震影響趾徽,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜翰守,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,936評(píng)論 3 313
  • 文/蒙蒙 一孵奶、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蜡峰,春花似錦了袁、人聲如沸朗恳。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,757評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽僻肖。三九已至,卻和暖如春卢鹦,著一層夾襖步出監(jiān)牢的瞬間臀脏,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,991評(píng)論 1 266
  • 我被黑心中介騙來泰國打工冀自, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留揉稚,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,370評(píng)論 2 360
  • 正文 我出身青樓熬粗,卻偏偏與公主長得像搀玖,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子驻呐,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,527評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容