1. 程式人生 > >Tensorflow例項:利用LSTM預測股票每日最高價(一)

Tensorflow例項:利用LSTM預測股票每日最高價(一)

這一部分主要涉及迴圈神經網路的理論,講的可能會比較簡略。
什麼是RNN

RNN全稱迴圈神經網路(Recurrent Neural Networks),是用來處理序列資料的。在傳統的神經網路模型中,從輸入層到隱含層再到輸出層,層與層之間是全連線的,每層之間的節點是無連線的。但是這種普通的神經網路對於很多關於時間序列的問題卻無能無力。例如,你要預測句子的下一個單詞是什麼,一般需要用到前面的單詞,因為一個句子中前後單詞並不是獨立的。RNN之所以稱為迴圈神經網路,即一個序列當前的輸出與前面的輸出也有關。具體的表現形式為網路會對前面時刻的資訊進行記憶並應用於當前輸出的計算中,即隱藏層之間的節點不再無連線而是有連線的,並且隱藏層的輸入不僅包括輸入層的輸出還包括上一時刻隱藏層的輸出。
說了這麼多,用一張圖表示,就是這個樣子。

這裡寫圖片描述
傳統的神經網路中,資料從輸入層輸入,在隱藏層加工,從輸出層輸出。RNN不同的就是在隱藏層的加工方法不一樣,後一個節點不僅受輸入層輸入的影響,還包受上一個節點的影響。
展開來就是這個樣子:
這裡寫圖片描述

圖中的xt−1 ,xt , xt+1就是不同時刻的輸入,每個x都具有input layer的n維特徵,依次進入迴圈神經網路以後,隱藏層輸出st受到上一時刻st−1的隱藏層輸出以及此刻輸入層輸入xt 的兩方影響。
如果要更詳細地瞭解tensorflow對RNN的解釋,清戳官方tensorflow.RNN
另外推薦的學習資料:WildML
什麼是LSTM

LSTM全稱長短期記憶人工神經網路(Long-Short Term Memory),是對RNN的變種。舉個例子,假設我們試著去預測“I grew up in France… 中間隔了好多好多字……I speak fluent __”下劃線的詞。我們拍腦瓜子想這個詞應該是French。對於迴圈神經網路來說,當前的資訊建議下一個詞可能是一種語言的名字,但是如果需要弄清楚是什麼語言,我們是需要離當前下劃線位置很遠的“France” 這個詞資訊。相關資訊和當前預測位置之間的間隔變得相當的大,在這個間隔不斷增大時,RNN 會喪失學習到連線如此遠的資訊的能力。
這個時候就需要LSTM登場了。在LSTM中,我們可以控制丟棄什麼資訊,存放什麼資訊。
具體的理論這裡就不多說了,推薦一篇博文Understanding LSTM Networks,裡面有對LSTM詳細的介紹,有網友作出的翻譯請戳[譯] 理解 LSTM 網路
股票預測

在對理論有理解的基礎上,我們使用LSTM對股票每日最高價進行預測。在本例中,僅使用一維特徵。
資料格式如下:
這裡寫圖片描述

本例取每日最高價作為輸入特徵[x],後一天的最高價最為標籤[y]
獲取資料,請戳stock_dataset.csv,密碼:md9l
匯入資料:

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())

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

出來的train_x就是像這個樣子:

[[[-1.59618],……中間還有18個……, [-1.56340]]
……
[[-1.59202] [-1.58244]]]

1
2
3

是一個shape為[-1,time_step,input__size]的矩陣
定義神經網路變數

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,]))
}

1
2
3
4
5
6
7
8
9
10
11
12

定義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

1
2
3
4
5
6
7
8
9
10
11
12
13
14

訓練模型

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