從RNN到Sequence2Sequence(二) LSTM


前言:由於梯度消失的存在,在實際應用中,RNN很難處理長距離的依賴。RNN的一種改進版本:長短時記憶網絡(Long Short Term Memory Network, LSTM)。 LSTM就是用來解決RNN中梯度消失問題的。
怎么解決的呢?
LSTM增加了一個可以相隔多個timesteps來傳遞信息的方法。想想有一個傳送帶在你處理sequences時一起運轉。每個時間節點的信息都可以放到傳送帶上,或者從傳送帶上拿下來,當然你也可以更新傳送帶上的信息。這樣就保存了很久之前的信息,防止了信息的丟失。

LSTM

一、概述


如果把LSTM當成黑盒子看待,可以分為以下關鍵變量(參考上圖):

  1. 輸入:\(h_{t-1}\) (t-1時刻的隱藏層向量)和 \(x_t\)(t時刻的特征向量)
  2. 輸出:\(h_t\)(加softmax即可作為真正輸出,否則作為隱藏層)
  3. 主線/記憶: \(c_{t-1}\)\(c_t\)
    LSTM分為三個部分:
  • 遺忘門:決定了上一時刻的單元狀態\(c_{t-1}\)有多少保留到當前時刻\(c_t\)。如果之前單元狀態中有主語,而輸入中又有了主語,那么原來存在的主語就應該被遺忘。concatenate的輸入和上一時刻的輸出經過sigmoid函數后,越接近於0被遺忘的越多,越接近於1被遺忘的越少。
  • 輸入門:決定了當前時刻網絡的輸入\(x_t\)有多少保存到單元狀態\(c_t\);即哪些新的狀態應該被加入。新進來的主語自然就是應該被加入到細胞狀態的內容,同理也是靠sigmoid函數來決定應該記住哪些內容。
  • 輸出門:控制單元狀態\(c_t\)有多少輸出到LSTM的當前輸出值\(h_t\)。根據當前的狀態和現在的輸入,確定輸出的比例。

  • \(h_{t-1}\)\(x_t\)聯合起來作為最終的輸入數據。
  • \(c_{t-1}\)\(c_t\)始終與外界隔離開來,顯然是作為LSTM記憶或者主線劇情的存在。
  • \(f_t\)為遺忘門的輸出。主線進來后,首先受到遺忘門的衰減作用。
  • \(i_t\)為輸入門的輸出。輸入門控制“補給大小”,給主線補充能量生成全新的主線。
  • \(o_t\)為輸出門的輸出,其經過變換得到當前時刻的隱層向量\(h_t\),同時也為當前時刻的輸出。

二、三個門的計算公式,在時間步t。

假設1個batch,輸入為[1,length,d]。length是預定義的最大序列長度, \(d\)是序列中每個step的維度。隱層神經元個數為\(h\)

  • 遺忘門部分

\[f_t = \sigma(W_{if}x_t + W_{hf}h_{t-1}) \qquad (遺忘門)\\ k_t = c_{t-1} \odot f_t \qquad (主線遺忘)\]

\(x_t = [1,d]\)\(h_{t-1} = [1,h]\),則遺忘門權重矩陣的形狀 \(W_f = [d+h,h]\),遺忘門的輸出\(f_t = [1,h]\)

  • 輸入門部分

\[i_t = \sigma (W_{ii}x_t + W_{hi}h_{t-1}) \qquad (輸入門) \\ g_t = tanh(W_{ig}x_t + W_{hg}h_{t-1}) \qquad (補給來源) \\ j_t = i_t \odot g_t \qquad (門控制補給大小) \\ c_t= j_t+ k_t \qquad (補給主線) \\\]

輸入門矩陣\(W_i = [d+h,h]\),輸入門矩陣的輸出\(i_t =[1,h]\);
補給矩陣\(W_g=[d+h,h]\),補給輸出\(g_t=[1,h]\);
補給主線\(c_t=[1,h]\)

  • 輸出門部分

\[o_t = \sigma (W_{io}x_t + W_{ho}h_{t-1}) \qquad (輸出門) \\ h_t= tanh(c_t)\odot o_t \qquad (主線最終輸出) \\\]

輸出門矩陣\(W_o = [d+h,h]\),輸出門輸出\(o_t=[1,h]\)
最終的輸出\(h_t=[1,h]\)

三、LSTM參數的數量

LSTM參數應該指包括embedding層的整個網絡的參數的數量。
LSTM的參數計算公式:

\[num(Embedding)+num(LSTM)=Word embedding dim * Vocab size +(hidden size * (hidden size + x_dim ) + hidden size) *4 \]

四、LSTM 和 RNN 結構對比


LSTM實現:時間序列預測

數據集:AirPassengers。1949 到 1960 一共 12 年,每年 12 個月的數據,一共 144 個數據,單位是 1000
數據集經過處理后得到訓練樣本

train_x : array([[x1,...x12],...]) 每個樣本為長度為12的數組,代表連續12個月份的乘客人數。因為輸入數據形狀為:  [batch,時間步長,每個時刻的維度]
train_y : array([[y1],...]) 因為是時間序列預測,標簽為一個具體的數值。

一、構建LSTM模型

'''定義LSTM cell組件,該組件將在訓練過程中被不斷更新參數'''
def LstmCell():
    lstm_cell = rnn.BasicLSTMCell(HIDDEN_SIZE, state_is_tuple=True)#
    return lstm_cell

'''定義LSTM模型'''
def lstm_model(X, y):
    # 輸入x的shape 為: (?, 1, 12),表示 (batch_size,序列長度為1,序列每步的維度為12)
    '''以前面定義的LSTM cell為基礎定義多層堆疊的LSTM,我們這里只有1層'''
    cell = rnn.MultiRNNCell([LstmCell() for _ in range(NUM_LAYERS)])

    '''將已經堆疊起的LSTM單元轉化成動態的可在訓練過程中更新的LSTM單元'''
    output, _ = tf.nn.dynamic_rnn(cell, X, dtype=tf.float32)
    # output 的shape為:  (?, 1, 40),表示 (batch_size,序列長度為1,隱層大小為40)
    '''根據預定義的每層神經元個數來生成隱層每個單元'''
    output = tf.reshape(output, [-1, HIDDEN_SIZE])
  
    '''通過無激活函數的全連接層計算線性回歸,並將數據壓縮成一維數組結構'''
    predictions = tf.contrib.layers.fully_connected(output, 1, None)

    '''統一預測值與真實值的形狀'''
    labels = tf.reshape(y, [-1])
    predictions = tf.reshape(predictions, [-1])

    '''定義損失函數,這里為正常的均方誤差'''
    loss = tf.losses.mean_squared_error(predictions, labels)

    '''定義優化器各參數'''
    train_op = tf.contrib.layers.optimize_loss(loss,
                                               tf.contrib.framework.get_global_step(),
                                               optimizer='Adagrad',
                                               learning_rate=0.6)
    '''返回預測值、損失函數及優化器'''
    return predictions, loss, train_op

二、訓練所用的模塊

learn = tf.contrib.learn
regressor = SKCompat(learn.Estimator(model_fn=lstm_model, model_dir='Models/model_2'))

tf.contrib.learn.Estimaor(模型,保存路徑),以sklearn的方式定義了一個模型,可以調用fit和predict方法完成訓練和預測。
Estimator里面還有一個叫SKCompat的類,如果使用x,y而不是input_fn來傳參數的形式,需要用這個類包裝一下。這里我們使用了x,y的輸入形式。

三、訓練和預測

'''以仿sklearn的形式訓練模型,這里指定了訓練批尺寸和訓練輪數'''
regressor.fit(train_X, train_y, batch_size=BATCH_SIZE, steps=TRAINING_STEPS)
'''利用已訓練好的LSTM模型,來生成對應測試集的所有預測值'''
predicted = np.array([pred for pred in regressor.predict(test_X)])

參考資料

  1. 快速理解LSTM,從懵逼到裝逼
    https://zhuanlan.zhihu.com/p/88892937
  2. 零基礎入門深度學習(6) - 長短時記憶網絡(LSTM)
    https://zybuluo.com/hanbingtao/note/581764
  3. (數據科學學習手札40)tensorflow實現LSTM時間序列預測
    https://www.cnblogs.com/feffery/p/9130728.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM