第一部分:從RNN到LSTM網絡
一、什麼是RNNapp
RNN全稱循環神經網絡(Recurrent Neural Networks),是用來處理序列數據的。在傳統的神經網絡模型中,從輸入層到隱含層再到輸出層,層與層之間是全鏈接的,每層之間的節點是無鏈接的。可是這種普通的神經網絡對於不少關於時間序列的問題卻無能無力。例如,你要預測句子的下一個單詞是什麼,通常須要用到前面的單詞,由於一個句子中先後單詞並非獨立的。RNN之因此稱爲循環神經網路,即一個序列當前的輸出與前面的輸出也有關。具體的表現形式爲網絡會對前面時刻的信息進行記憶並應用於當前輸出的計算中,即隱藏層之間的節點再也不無鏈接而是有鏈接的,而且隱藏層的輸入不只包括輸入層的輸出還包括上一時刻隱藏層的輸出,以下圖所示: dom
傳統的神經網絡中,數據從輸入層輸入,在隱藏層加工,從輸出層輸出。RNN不一樣的就是在隱藏層的加工方法不同,後一個節點不只受輸入層輸入的影響,還包受上一個節點的影響。
展開來就是這個樣子:圖中的xt−1,xt, xt+1表明不一樣時刻的輸入,每一個x都具備input layer的n維特徵,依次進入循環神經網絡之後,隱藏層輸出st受到上一時刻st−1的隱藏層輸出以及此刻輸入層輸入xt函數
的兩方面影響。 學習
缺點:RNN利用內部的記憶來處理任意時序的輸入序列,而且在其處理單元之間既有內部的反饋鏈接又有前饋鏈接,這使得RNN能夠更加容易處理不分段的文本等。可是因爲RNN只能對部分序列進行記憶,因此在長序列上表現遠不如短序列,形成了一旦序列過長便使得準確率降低的結果。測試
二、什麼是LSTMspa
長短記憶神經網絡——一般稱做LSTM,是一種特殊的RNN,可以學習長的依賴關係。 他們由Hochreiter&Schmidhuber引入,並被許多人進行了改進和普及。他們在各類各樣的問題上工做的很是好,如今被普遍使用。設計
LSTM是爲了不長依賴問題而精心設計的。 記住較長的歷史信息其實是他們的默認行爲,而不是他們努力學習的東西。3d
全部循環神經網絡都具備神經網絡的重複模塊鏈的形式。 在標準的RNN中,該重複模塊將具備很是簡單的結構,例如單個tanh層。rest
LSTM也擁有這種鏈狀結構,可是重複模塊則擁有不一樣的結構。與神經網絡的簡單的一層相比,LSTM擁有四層,這四層以特殊的方式進行交互。
LSTM的關鍵是細胞狀態,表示細胞狀態的這條線水平的穿過圖的頂部。
細胞的狀態相似於輸送帶,細胞的狀態在整個鏈上運行,只有一些小的線性操做做用其上,信息很容易保持不變的流過整個鏈。
門(Gate)是一種可選地讓信息經過的方式。 它由一個Sigmoid神經網絡層和一個點乘法運算組成。
Sigmoid神經網絡層輸出0和1之間的數字,這個數字描述每一個組件有多少信息能夠經過, 0表示不經過任何信息,1表示所有經過
LSTM有三個門,用於保護和控制細胞的狀態。
LSTM的第一步是決定咱們要從細胞狀態中丟棄什麼信息。 該決定由被稱爲「忘記門」的Sigmoid層實現。它查看ht-1(前一個輸出)和xt(當前輸入),併爲單元格狀態Ct-1(上一個狀態)中的每一個數字輸出0和1之間的數字。1表明徹底保留,而0表明完全刪除。
讓咱們回到語言模型的例子,試圖根據之前的語料來預測下一個單詞。 在這樣的問題中,細胞狀態可能包括當前主題的性別,從而決定使用正確的代詞。 當咱們看到一個新主題時,咱們想要忘記舊主題的性別。
下一步是決定咱們要在細胞狀態中存儲什麼信息。 這部分分爲兩步。 首先,稱爲「輸入門層」的Sigmoid層決定了咱們將更新哪些值。 接下來一個tanh層建立候選向量Ct,該向量將會被加到細胞的狀態中。 在下一步中,咱們將結合這兩個向量來建立更新值。
在咱們的語言模型的例子中,咱們但願將新主題的性別添加到單元格狀態,以替換咱們忘記的舊對象。
如今是時候去更新上一個狀態值Ct−1了,將其更新爲Ct。簽名的步驟以及決定了應該作什麼,咱們只需實際執行便可。
咱們將上一個狀態值乘以ft,以此表達期待忘記的部分。以後咱們將獲得的值加上 it∗C̃ t。這個獲得的是新的候選值, 按照咱們決定更新每一個狀態值的多少來衡量.
在語言模型的例子中,對應着實際刪除關於舊主題性別的信息,並添加新信息,正如在以前的步驟中描述的那樣。
最後,咱們須要決定咱們要輸出什麼。 此輸出將基於咱們的細胞狀態,但將是一個過濾版本。 首先,咱們運行一個sigmoid層,它決定了咱們要輸出的細胞狀態的哪些部分。 而後,咱們將單元格狀態經過tanh(將值規範化到-1和1之間),並將其乘以Sigmoid門的輸出,至此咱們只輸出了咱們決定的那些部分。
對於語言模型的例子,因爲只看到一個主題,考慮到後面可能出現的詞,它可能須要輸出與動詞相關的信息。 例如,它可能會輸出主題是單數仍是複數,以便咱們知道動詞應該如何組合在一塊兒。
三、股票預測實戰1
在對理論有理解的基礎上,咱們使用LSTM對股票每日最高價進行預測。在本例中,僅使用一維特徵。
數據格式以下:
本例取每日最高價做爲輸入特徵[x],後一天的最高價最爲標籤[y]
步驟1、導入數據:
import pandas as pd import numpy as np import matplotlib.pyplot as plt import tensorflow f=open('stock_dataset.csv') df=pd.read_csv(f) #讀入股票數據 data=np.array(df['最高價']) #獲取最高價序列 data=data[::-1] #反轉,使數據按照日期前後順序排列 #以折線圖展現data plt.figure() plt.plot(data) plt.show() normalize_data=(data-np.mean(data))/np.std(data) #標準化 normalize_data=normalize_data[:,np.newaxis] #增長維度 #———————————————————造成訓練集————————————————————— #設置常量 time_step=20 #時間步 rnn_unit=10 #hidden layer units batch_size=60 #每一批次訓練多少個樣例 input_size=1 #輸入層維度 output_size=1 #輸出層維度 lr=0.0006 #學習率 train_x,train_y=[],[] #訓練集 for i in range(len(normalize_data)-time_step-1): x=normalize_data[i:i+time_step] y=normalize_data[i+1:i+time_step+1] train_x.append(x.tolist()) train_y.append(y.tolist())
出來的train_x就是像這個樣子:
[[[-1.59618],……中間還有18個……, [-1.56340]] …… [[-1.59202] [-1.58244]]]
是一個shape爲[-1,time_step,input__size]的矩陣
步驟2、定義神經網絡變量
X=tf.placeholder(tf.float32, [None,time_step,input_size]) #每批次輸入網絡的tensor Y=tf.placeholder(tf.float32, [None,time_step,output_size]) #每批次tensor對應的標籤 #輸入層、輸出層權重、偏置 weights={ 'in':tf.Variable(tf.random_normal([input_size,rnn_unit])), 'out':tf.Variable(tf.random_normal([rnn_unit,1])) } biases={ 'in':tf.Variable(tf.constant(0.1,shape=[rnn_unit,])), 'out':tf.Variable(tf.constant(0.1,shape=[1,])) }
步驟3、定義lstm網絡
def lstm(batch): #參數:輸入網絡批次數目 w_in=weights['in'] b_in=biases['in'] input=tf.reshape(X,[-1,input_size]) #須要將tensor轉成2維進行計算,計算後的結果做爲隱藏層的輸入 input_rnn=tf.matmul(input,w_in)+b_in input_rnn=tf.reshape(input_rnn,[-1,time_step,rnn_unit]) #將tensor轉成3維,做爲lstm cell的輸入 cell=tf.nn.rnn_cell.BasicLSTMCell(rnn_unit) init_state=cell.zero_state(batch,dtype=tf.float32) output_rnn,final_states=tf.nn.dynamic_rnn(cell, input_rnn,initial_state=init_state, dtype=tf.float32) #output_rnn是記錄lstm每一個輸出節點的結果,final_states是最後一個cell的結果 output=tf.reshape(output_rnn,[-1,rnn_unit]) #做爲輸出層的輸入 w_out=weights['out'] b_out=biases['out'] pred=tf.matmul(output,w_out)+b_out return pred,final_states
步驟4、訓練模型
def train_lstm(): global batch_size pred,_=rnn(batch_size) #損失函數 loss=tf.reduce_mean(tf.square(tf.reshape(pred,[-1])-tf.reshape(Y, [-1]))) train_op=tf.train.AdamOptimizer(lr).minimize(loss) saver=tf.train.Saver(tf.global_variables()) with tf.Session() as sess: sess.run(tf.global_variables_initializer()) #重複訓練10000次 for i in range(10000): step=0 start=0 end=start+batch_size while(end<len(train_x)): _,loss_=sess.run([train_op,loss],feed_dict={X:train_x[start:end],Y:train_y[start:end]}) start+=batch_size end=start+batch_size #每10步保存一次參數 if step%10==0: print(i,step,loss_) print("保存模型:",saver.save(sess,'stock.model')) step+=1
步驟5、預測模型
def prediction(): pred,_=lstm(1) #預測時只輸入[1,time_step,input_size]的測試數據 saver=tf.train.Saver(tf.global_variables()) with tf.Session() as sess: #參數恢復 module_file = tf.train.latest_checkpoint(base_path+'module2/') saver.restore(sess, module_file) #取訓練集最後一行爲測試樣本。shape=[1,time_step,input_size] prev_seq=train_x[-1] predict=[] #獲得以後100個預測結果 for i in range(100): next_seq=sess.run(pred,feed_dict={X:[prev_seq]}) predict.append(next_seq[-1]) #每次獲得最後一個時間步的預測結果,與以前的數據加在一塊兒,造成新的測試樣本 prev_seq=np.vstack((prev_seq[1:],next_seq[-1])) #以折線圖表示結果 plt.figure() plt.plot(list(range(len(normalize_data))), normalize_data, color='b') plt.plot(list(range(len(normalize_data), len(normalize_data) + len(predict))), predict, color='r') plt.show()
例子中只有把最高價做爲特徵,去預測以後的最高價趨勢,下一講會增長輸入的特徵維度,把最低價、開盤價、收盤價、交易額等做爲輸入的特徵對以後的最高價進行預測。
最終運行結果顯示: