LSTM股票預測模型
1.LSTM簡介
LSTM(Long Short-Term Memory)是長短期記憶網路,是一種時間遞迴神經網路,適合於處理和預測時間序列中間隔和延遲相對較長的重要事件。
LSTM已經在科技領域有了多種應用。基於LSTM的系統可以學習翻譯語言、控制機器人、影象分析、文件摘要、語音識別、影象識別、手寫識別、控制聊天機器人、預測疾病、點選率和股票、合成音樂等等任務。
------百度百科 https://baike.baidu.com/item/LSTM/17541102?fr=aladdin
2.LSTM工作原理
LSTM是RNN的特殊型別,因此我們先來介紹RNN的工作原理。
RNN(Recurrent Neural Network)是一類用於處理序列資料的神經網路。(時間序列資料是指在不同時間點上收集到的資料,這類資料反映了某一事物、現象等隨時間的變化狀態或程度。
神經網路包含了輸入層、隱層、輸出層,通過啟用函式控制輸出,層與層之間通過權值連線。啟用函式是事先確定好的,那麼神經網路模型通過訓練“學”到的東西就蘊含在權值中。基礎的神經網路只在層與層之間建立了權連線,RNN最大的不同之處就是在層之間的神經元之間也建立了權連線。如圖:
X是輸入,h是隱層單元,o是輸出,L是損失函式,y是訓練集的標籤,U、V、W是權值
T時刻: ∅ 是啟用函式
最終模型輸出: σ
RNN的訓練方法——BPTT
BPTT(back-propagation through time)演算法是常用的訓練RNN的方法,其實本質還是BP演算法,只不過RNN是處理時間序列資料,所以要基於時間反向傳播,故叫隨時間反向傳播。BPTT的中心思想和BP演算法相同,沿著需要優化的引數的負梯度方向不斷尋找更優的點直至收斂。
需要尋優的引數有三個,分別是U、V、W。與BP演算法不同的是,其中W和U兩個引數的尋優過程要追溯到之前的歷史資料,引數V相對簡單隻須關注目前。
引數V的偏導數:
RNN的損失函式是隨時間累加的,所以不能只求t時刻的偏導
LSTM是RNN的一種變體,RNN由於梯度消失的原因只能有短期記憶,LSTM網路通過精妙的門控制將短期記憶與長期記憶結合起來,並且一定程度上解決了梯度消失的問題。
所有的RNN都具有一種重複神經網路模組的鏈式形式。在標準RNN中,這個重複的結構模組只有一個非常簡單的結構,例如一個tanh層。
LSTM 同樣是這樣的結構,但是重複的模組擁有一個不同的結構。不同於單一神經網路
層,這裡是有四個,以一種非常特殊的方式進行互動。
- 黃色的矩形是學習得到的神經網路層粉色的圓形表示一些運算操作,諸如加法乘法
- 黑色的單箭頭表示向量的傳輸
- 兩個箭頭合成一個表示向量的連線
- 一個箭頭分開表示向量的複製
3.LSTM核心思想
LSTM的關鍵在於細胞的狀態整個(綠色的圖表示的是一個cell),和穿過細胞的那條水平線。細胞狀態類似於傳送帶。直接在整個鏈上執行,只有一些少量的線性互動。資訊在上面流傳保持不變會很容易。
若只有上面的那條水平線是沒辦法實現新增或者刪除資訊的。而是通過一種叫做 門(gates) 的結構來實現的。
門可以實現選擇性地讓資訊通過,主要是通過一個 sigmoid 的神經層 和一個逐點相乘的操作來實現的。
sigmoid 層輸出(是一個向量)的每個元素都是一個在 0 和 1 之間的實數,表示讓對應資訊通過的權重(或者佔比)。比如, 0 表示“不讓任何資訊通過”, 1 表示“讓所有資訊通過”。
LSTM通過三個這樣的本結構來實現資訊的保護和控制。這三個門分別輸入門、遺忘門和輸出門。
遺忘門:
作用物件:細胞狀態
作用:使細胞狀態中的資訊選擇性遺忘
輸入門:
作用物件:細胞狀態
作用:將新的資訊選擇性的記錄到細胞狀態中
輸出門
作用物件:隱層ht
利用LSTM進行股票預測的程式碼:
輸入:
Date:日期
Time:具體時刻
High:最高價
Low:最低價
Close:收盤價
Adj Close:已調整的收盤價
Volume:交易量
Label:下一時刻最高價
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import tensorflow as tf
rnn_unit=10 #隱層神經元的個數
lstm_layers=2 #隱層層數
input_size=6
output_size=1
lr=0.0006 #學習率
#——————————匯入資料———---------
f=open('SH000001.csv')
df=pd.read_csv(f) #讀入股票資料
data=df.iloc[:,2:9].values #取第3-10列
data[:1]
def get_train_data(batch_size=60,time_step=20,train_begin=0,train_end=5800):
batch_index=[]
data_train=data[train_begin:train_end]
normalized_train_data=(data_train-np.mean(data_train,axis=0))/np.std(data_train,axis=0) #標準化
train_x,train_y=[],[] #訓練集
for i in range(len(normalized_train_data)-time_step):
if i % batch_size==0:
batch_index.append(i)
x=normalized_train_data[i:i+time_step,:6]
y=normalized_train_data[i:i+time_step,6,np.newaxis]
train_x.append(x.tolist())
train_y.append(y.tolist())
batch_index.append((len(normalized_train_data)-time_step))
return batch_index,train_x,train_y
#獲取測試集
def get_test_data(time_step=20,test_begin=5800):
data_test=data[test_begin:9800]
mean=np.mean(data_test,axis=0)
std=np.std(data_test,axis=0)
normalized_test_data=(data_test-mean)/std #標準化
size=(len(normalized_test_data)+time_step-1)//time_step #有size個sample
test_x,test_y=[],[]
for i in range(size-1):
x=normalized_test_data[i*time_step:(i+1)*time_step,:6]
y=normalized_test_data[i*time_step:(i+1)*time_step,6]
test_x.append(x.tolist())
test_y.extend(y)
test_x.append((normalized_test_data[(i+1)*time_step:,:6]).tolist())
test_y.extend((normalized_test_data[(i+1)*time_step:,6]).tolist())
return mean,std,test_x,test_y
#——————————定義神經網路變數————————————
#輸入層、輸出層權重、偏置、dropout引數
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,]))
}
keep_prob = tf.placeholder(tf.float32, name='keep_prob')
#—————————定義神經網路變數————————————
def lstmCell():
#basicLstm單元
basicLstm = tf.nn.rnn_cell.BasicLSTMCell(rnn_unit)
# dropout
drop = tf.nn.rnn_cell.DropoutWrapper(basicLstm, output_keep_prob=keep_prob)
return basicLstm
def lstm(X):
batch_size=tf.shape(X)[0]
time_step=tf.shape(X)[1]
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.MultiRNNCell([lstmCell() for i in range(lstm_layers)])
init_state=cell.zero_state(batch_size,dtype=tf.float32)
output_rnn,final_states=tf.nn.dynamic_rnn(cell, input_rnn,initial_state=init_state, dtype=tf.float32)
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
def lstm(X):
batch_size=tf.shape(X)[0]
time_step=tf.shape(X)[1]
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.MultiRNNCell([lstmCell() for i in range(lstm_layers)])
init_state=cell.zero_state(batch_size,dtype=tf.float32)
output_rnn,final_states=tf.nn.dynamic_rnn(cell, input_rnn,initial_state=init_state, dtype=tf.float32)
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
#————————————————預測模型————————————————————
def prediction(time_step=20):
X=tf.placeholder(tf.float32, shape=[None,time_step,input_size])
mean,std,test_x,test_y=get_test_data(time_step)
with tf.variable_scope("sec_lstm",reuse=tf.AUTO_REUSE):#reuse=tf.AUTO_REUSE
pred,_=lstm(X)
saver=tf.train.Saver(tf.global_variables())
with tf.Session() as sess:
#引數恢復
module_file = tf.train.latest_checkpoint('model_save2')
saver.restore(sess, module_file)
test_predict=[]
for step in range(len(test_x)-1):
prob=sess.run(pred,feed_dict={X:[test_x[step]],keep_prob:1})
predict=prob.reshape((-1))
test_predict.extend(predict)
test_y=np.array(test_y)*std[6]+mean[6]
test_predict=np.array(test_predict)*std[6]+mean[6]
acc=np.average(np.abs(test_predict-test_y[:len(test_predict)])/test_y[:len(test_predict)]) #偏差程度
print("The accuracy of this predict:",acc)
#以折線圖表示結果
plt.figure()
plt.plot(list(range(len(test_predict))), test_predict, color='b',)
plt.plot(list(range(len(test_y))), test_y, color='r')
plt.show()
prediction()