1. 程式人生 > >LSTM股票預測模型

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時刻:       是啟用函式

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 同樣是這樣的結構,但是重複的模組擁有一個不同的結構。不同於單一神經網路

層,這裡是有四個,以一種非常特殊的方式進行互動。

 

 

 

  1. 黃色的矩形是學習得到的神經網路層粉色的圓形表示一些運算操作,諸如加法乘法
  2. 黑色的單箭頭表示向量的傳輸
  3. 兩個箭頭合成一個表示向量的連線
  4. 一個箭頭分開表示向量的複製

3.LSTM核心思想

LSTM的關鍵在於細胞的狀態整個(綠色的圖表示的是一個cell),和穿過細胞的那條水平線。細胞狀態類似於傳送帶。直接在整個鏈上執行,只有一些少量的線性互動。資訊在上面流傳保持不變會很容易。

 

https://ws1.sinaimg.cn/large/005BVyzmly1fotnwop43ej30jg060aab.jpg

 

若只有上面的那條水平線是沒辦法實現新增或者刪除資訊的。而是通過一種叫做 門(gates) 的結構來實現的。

門可以實現選擇性地讓資訊通過,主要是通過一個 sigmoid 的神經層 和一個逐點相乘的操作來實現的。

 

https://ws1.sinaimg.cn/large/005BVyzmly1fotnxtqjlmj305i06q3yd.jpg

 

sigmoid 層輸出(是一個向量)的每個元素都是一個在 0 和 1 之間的實數,表示讓對應資訊通過的權重(或者佔比)。比如, 0 表示“不讓任何資訊通過”, 1 表示“讓所有資訊通過”。

LSTM通過三個這樣的本結構來實現資訊的保護和控制。這三個門分別輸入門、遺忘門和輸出門。

 

 

遺忘門:

作用物件:細胞狀態

作用:使細胞狀態中的資訊選擇性遺忘

http://upload-images.jianshu.io/upload_images/42741-96b387f711d1d12c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240

輸入門:

作用物件:細胞狀態

作用:將新的資訊選擇性的記錄到細胞狀態中

http://upload-images.jianshu.io/upload_images/42741-7fa07e640593f930.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240

 

http://upload-images.jianshu.io/upload_images/42741-d88caa3c4faf5353.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240

輸出門

作用物件:隱層ht

 

http://upload-images.jianshu.io/upload_images/42741-4c9186bf786063d6.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240

 

 

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