萬物皆可LSTM

大家好,我是XFXZ,咱今天吃頓好的(搶一下B站碳水教父徐大騷的臺詞),不過,咱今天,是在我的博客裏吃頓好的。豬蹄鎮樓。
在這裏插入圖片描述
這裏我先聲明我這篇博客的定位,屬於應用篇,理論不是重點,我要全,而追求精的童鞋們可以去查其他人的博客。

什麼是LSTM?

全名爲長短時記憶網絡,英文是Long short term memory,屬於循環神經網絡中非常常用和重要的一類循環層。(在我的上一篇博客上有講過層的概念,之所以是循環層,因爲神經元會在時間軸上有次序連接,而非無序無連接的全連接層神經元)
循環層
循環層
全連接層
全連接層

LSTM在深度學習中的地位?

在最近十年,大部分AI都是關於長期短期記憶(LSTM)的神經網絡。世界本質上是序列性的(這其實不對,世界本質沒有時間的,爲了能理解這個世界,時間才存在的),而LSTM徹底改變了序列數據處理,例如語音識別、機器翻譯、視頻識別,聯機手寫識別、機器人、視頻遊戲、時間序列預測、聊天機器人、醫療保健應用等。到2019年,LSTM每年獲得的引用量超過過去一千年間任何其他計算機科學論文。(引自:LSTM之父,深度學習元老,Jürgen Schmidhuber:2010-2020,我眼中的深度學習十年簡史,https://mp.weixin.qq.com/s/vK87vUUGfjPs4Ys6V-shWw)

LSTM的應用?

遍欄衆多博客與學術論文,我發現LSTM層,簡直就是萬金油!

1.迴歸,用一羣結構化數據迴歸出一個或者多個數。

1.分類,用一羣結構化數據輸入,最後一層加softmax或者全連接層做分類。
3.數據特徵壓縮重構。自動編碼機也可以用全連接層,更可以用LSTM層,形成序列自動編碼機。
4.編碼/解碼作用。有做過自然語言處理NLP的小夥伴,肯定熟悉seq2seq結構,其可以全部爲LSTM層,對輸入詞向量做編碼和再解碼,直接用途就是不同語言翻譯。

LSTM的機理分析?

在這裏插入圖片描述
如上圖,LSTM 單元是組成LSTM的基本單元,包括遺忘門,輸入門,輸出門。像她們一樣時序串聯接就可以組成LSTM層
一、我們可以從本質上分析,一個LSTM網絡視爲如下所示的複合函數,y是輸出,x爲輸入,T就是你輸入數據的時序長度。括號內的就是廣義的記憶,有時間屬性,本質上是多維時間序列數據(2維張量)。一般什麼交通事故數據,沒有動態性,這是單純記錄一個事故的發生地點、人數、傷亡程度等變量屬性。沒有任何時序信息,是不能用LSTM處理的哦。在這裏插入圖片描述
注意Jürgen Schmidhuber提出LSTM的目的是爲了解決一個問題:LSTM以前的神經網絡沒有記憶,無法根據之前的輸入來預測出輸出。那怎麼給神經網絡加上記憶?記憶就是過去發生的事情,那麼如果神經網絡現在的輸出受到過去輸入的影響,是不是就可以說神經網絡擁有了記憶於是就有了這樣的神經網絡,而普通RNN沒有門式結構,容易發生梯度爆炸或梯度彌散問題。
二、從輸入到輸出:
在這裏插入圖片描述
有5種模式,這裏以多對一爲例。
X:數據維度[batchsize,time_step,input_dim]
Y:數據維度[batchsize,1] #return_sequences爲false
batchsize就是你在輸入LSTM訓練每次用幾個樣本,time_step就是你的T,考慮的序列長度(時間軸數據點數量),input_dim就是你用的數據有幾個變量。可以多對一就是把一個維度time_stepinput_dim的數據—變爲一個數值。一般神經網絡是把input_dim的數據(1維張量)—變爲一個數值。
注意:如果你想變樣本batchsize的大小輸入,可以將其設爲None,但此時不能直接用fit方法訓練。
return_sequences爲True,是一個LSTM層就會返回[batchsize,time_step,output_dim]的3維張量數據,也就是用在你想堆疊多個LSTM層的時候(如我的代碼),這個參數要設爲True。層函數調用時必須指定的units參數就是out_dim,一般是8,16,32,64,128,256等正整數,其實50 60 20都行。*
在這裏插入圖片描述
其實從應用層面,看到這裏就可以了。
三、如果你還要了解具體原理,就繼續看吧。
在三個門式結構中,數據流ct, ft ,it ,Ot ,ht,都是單元內張量。輸入後會按照這樣方式進行運算。
在這裏插入圖片描述
注意我圖中hidden state(短期記憶ht,藍線)和cell state(長期記憶,黃長線)的信息傳遞,以及最終CLEE輸出其實就是ht(需要
x*t-1參與運算,和歷史的Ct-1等,而Ct-1又和Ct-2等有關)在傳遞到下一個CELL,直到輸出。圖例的乘號*應該表示向量逐點乘法pointwise multiplication。當你把return_sequences設爲True,你就得到了很多ht,ht-1,ht-2,ht-3…;否則只有ht。

LSTM/RNN的變種?

1.雙向LSTM

本質就是堆疊兩層LSTM,但是這兩層LSTM的數據流方向是相反的,這樣可以進一步挖掘時間依賴。儘管似乎違背記憶的概念,用未來推斷過去。

2.柵格LSTM

直接接受柵格數據(圖片等)的升級版LSTM。

3.GRU

就像二哈和狼,我們可以說LSTM和GRU是近親啦。它也是循環神經網絡層,參數更少,只有重置門和更新門。

4.卷積LSTM網絡

卷積操作強化的LSTM,同時具備挖掘空間依賴的能力,不過多介紹

LSTM的代碼實例與API調用?

這些是我寫我論文時候編寫的,你們可以參考(庫和模型部分),基於TENSORFLOW backend 的KERAS框架。

#導入有關庫
import numpy as np
import pandas as pd
import time
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties #解決中文字體無法顯示
import math

import tensorflow as tf
from keras.models import Sequential,Model
from keras.layers import Dense, LSTM,TimeDistributed
import keras.backend as K
from keras.optimizers import Adam
import keras.callbacks
from keras import metrics
from keras.utils import plot_model
from keras.layers.core import Dense, Activation, Dropout
from keras.layers.normalization import BatchNormalization
#標準化、歸一化
from sklearn.preprocessing import StandardScaler
from sklearn.preprocessing import MinMaxScaler
from sklearn import model_selection
#有關參數設置
TIME_STEPS = 20
BATCH_SIZE = 500 #其實沒有用到
INPUT_SIZE = 3  #
OUTPUT_SIZE = 1
CELL_SIZE = 64
LR = 0.001  

#搭建1層的LSTM的RNN網絡,目前已經加深
model = Sequential()
#NOW build a multilwayer LSTM-RNN    
model.add(LSTM(activation='relu',
         batch_input_shape=(None,TIME_STEPS,INPUT_SIZE),
         output_dim=CELL_SIZE,
     return_sequences=True# True: output at all steps. False: output as last step.
          # True: the final state of batch1 is feed into the initial state of batch2
        ))
#return_sequences=True
model.add(Dropout(0.2))
model.add(BatchNormalization())
model.add(LSTM(units=CELL_SIZE,activation='tanh', input_shape=(TIME_STEPS,INPUT_SIZE),return_sequences=True))
model.add(Dropout(0.2))
model.add(LSTM(units=CELL_SIZE,activation='relu', input_shape=(TIME_STEPS,INPUT_SIZE),return_sequences=True))
model.add(Dropout(0.2))
model.add(BatchNormalization())
model.add(LSTM(units=OUTPUT_SIZE,activation='relu', input_shape=(TIME_STEPS,INPUT_SIZE),return_sequences=False))
#stateful=False!!!!!此時batch之間無聯繫要設置statefu參數l=False
# add output layer
model.add((Dense(OUTPUT_SIZE)))  #如果設置多狀態輸出,加TimeDistributed(Dense(OUTPUT_SIZE))
adam = Adam(LR)  #這就是把adam優化器對象實例化,萬物皆可**紅油**(不不不,是對象)
model.compile(optimizer=adam,loss='mae',metrics=['mse'])
sumcost=0
losthis=np.zeros([lstmx_trainrange.shape[0],3])

#繪製結構模型圖
#plot_model(model,to_file='XFXZ'Slstm.png',show_shapes=False,show_layer_names=True)
#進行LSTM模型訓練
losthis=np.zeros([lstmx_trainrange.shape[0],3])

##進行模型訓練,使用model train on batch 方法
for each in range(lstmx_trainrange.shape[0]):   #1     
   X_batch, Y_batch,currentbatchsize = getonebatchdata(current=each,batchsize=500,
                           slicedatax=lstmx_trainrange) #這裏的batchsize其實是變化的,都比500大
   cost = model.train_on_batch(X_batch, Y_batch) #目前每個batch值設置了一次,
   sumcost+=cost[0]
   if each==0:
       averagecost=cost
   else:
        averagecost=sumcost/(each*1)   #求得平均損失          
        pred = model.predict(X_batch, currentbatchsize) #預測比對
   if each % 1 == 0: #連續輸出
       print('now train cost is: ', cost,'train average cost: ',(averagecost))

API參數(官方文檔,可能看起來需要理解挺久,也枯燥)
通用參數
LSTM它是RNN對象的子類,RNN是它的基類。
keras.layers.RNN(cell, return_sequences=False, return_state=False, go_backwards=False, stateful=False, unroll=False)
cell: 一個 RNN 單元實例。RNN 單元是一個具有以下幾項的類:
一個 call(input_at_t, states_at_t) 方法, 它返回 (output_at_t, states_at_t_plus_1)。 單元的調用方法也可以採引入可選參數 constants, 詳見下面的小節「關於給 RNN 傳遞外部常量的說明」。
一個 state_size 屬性。這可以是單個整數(單個狀態), 在這種情況下,它是循環層狀態的大小(應該與單元輸出的大小相同)。 這也可以是整數表示的列表/元組(每個狀態一個大小)。
一個 output_size 屬性。 這可以是單個整數或者是一個 TensorShape, 它表示輸出的尺寸。出於向後兼容的原因,如果此屬性對於當前單元不可用, 則該值將由 state_size 的第一個元素推斷。
cell 也可能是 RNN 單元實例的列表,在這種情況下,RNN 的單元將堆疊在另一個單元上,實現高效的堆疊 RNN。

return_sequences: 布爾值。是返回輸出序列中的最後一個輸出,還是全部序列。

return_state: 布爾值。除了輸出之外是否返回最後一個狀態。
go_backwards: 布爾值 (默認 False)。 如果爲 True,則向後處理輸入序列並返回相反的序列。
stateful: 布爾值 (默認 False)。 如果爲 True,則批次中索引 i 處的每個樣品的最後狀態將用作下一批次中索引 i 樣品的初始狀態。
unroll: 布爾值 (默認 False)。 如果爲 True,則網絡將展開,否則將使用符號循環。 展開可以加速 RNN,但它往往會佔用更多的內存。 展開只適用於短序列。
input_dim: 輸入的維度(整數)。 將此層用作模型中的第一層時,此參數(或者,關鍵字參數 input_shape)是必需的。
input_length: 輸入序列的長度,在恆定時指定。 如果你要在上游連接 Flatten 和 Dense 層, 則需要此參數(如果沒有它,無法計算全連接輸出的尺寸)。 請注意,如果循環神經網絡層不是模型中的第一層, 則需要在第一層的層級指定輸入長度(例如,通過 input_shape 參數)。
輸入尺寸

3D 張量,尺寸爲 (batch_size, timesteps, input_dim)。

輸出尺寸

如果 return_state:返回張量列表。 第一個張量爲輸出。剩餘的張量爲最後的狀態, 每個張量的尺寸爲 (batch_size, units)。
如果 return_sequences:返回 3D 張量, 尺寸爲 (batch_size, timesteps, units)。
否則,返回尺寸爲 (batch_size, units) 的 2D 張量。

特有參數
keras.layers.LSTM(units, activation=‘tanh’, recurrent_activation=‘hard_sigmoid’, use_bias=True, kernel_initializer=‘glorot_uniform’, recurrent_initializer=‘orthogonal’, bias_initializer=‘zeros’, unit_forget_bias=True, kernel_regularizer=None, recurrent_regularizer=None, bias_regularizer=None, activity_regularizer=None, kernel_constraint=None, recurrent_constraint=None, bias_constraint=None, dropout=0.0, recurrent_dropout=0.0, implementation=1, return_sequences=False, return_state=False, go_backwards=False, stateful=False, unroll=False)
特有參數:
units: 正整數,輸出空間的維度。
activation: 要使用的激活函數 (詳見 activations)。 如果傳入 None,則不使用激活函數 (即 線性激活:a(x) = x)。
recurrent_activation: 用於循環時間步的激活函數 (詳見 activations)。 默認:分段線性近似 sigmoid (hard_sigmoid)。 如果傳入 None,則不使用激活函數 (即 線性激活:a(x) = x)。
use_bias: 布爾值,該層是否使用偏置向量。
kernel_initializer: kernel 權值矩陣的初始化器, 用於輸入的線性轉換 (詳見 initializers)。
recurrent_initializer: recurrent_kernel 權值矩陣 的初始化器,用於循環層狀態的線性轉換 (詳見 initializers)。
bias_initializer:偏置向量的初始化器 (詳見initializers).
unit_forget_bias: 布爾值。 如果爲 True,初始化時,將忘記門的偏置加 1。 將其設置爲 True 同時還會強制 bias_initializer=“zeros”。 這個建議來自 Jozefowicz et al.。
kernel_regularizer: 運用到 kernel 權值矩陣的正則化函數 (詳見 regularizer)。
recurrent_regularizer: 運用到 recurrent_kernel 權值矩陣的正則化函數 (詳見 regularizer)。
bias_regularizer: 運用到偏置向量的正則化函數 (詳見 regularizer)。
activity_regularizer: 運用到層輸出(它的激活值)的正則化函數 (詳見 regularizer)。
kernel_constraint: 運用到 kernel 權值矩陣的約束函數 (詳見 constraints)。
recurrent_constraint: 運用到 recurrent_kernel 權值矩陣的約束函數 (詳見 constraints)。
bias_constraint: 運用到偏置向量的約束函數 (詳見 constraints)。
dropout: 在 0 和 1 之間的浮點數。 單元的丟棄比例,用於輸入的線性轉換。
recurrent_dropout: 在 0 和 1 之間的浮點數。 單元的丟棄比例,用於循環層狀態的線性轉換。
implementation: 實現模式,1 或 2。 模式 1 將把它的操作結構化爲更多的小的點積和加法操作, 而模式 2 將把它們分批到更少,更大的操作中。 這些模式在不同的硬件和不同的應用中具有不同的性能配置文件。
return_sequences: 布爾值。是返回輸出序列中的最後一個輸出,還是全部序列。
return_state: 布爾值。除了輸出之外是否返回最後一個狀態。
go_backwards: 布爾值 (默認 False)。 如果爲 True,則向後處理輸入序列並返回相反的序列。
stateful: 布爾值 (默認 False)。 如果爲 True,則批次中索引 i 處的每個樣品的最後狀態 將用作下一批次中索引 i 樣品的初始狀態。
unroll: 布爾值 (默認 False)。 如果爲 True,則網絡將展開,否則將使用符號循環。 展開可以加速 RNN,但它往往會佔用更多的內存。 展開只適用於短序列
引自 https://keras.io/zh/layers/recurrent/

LSTM的使用難點和缺點?

1.參數體量大,與同類的神經網絡,如果處理一樣的數據,網絡深度的相同。LSTM的超參數炒雞多,會隨着隱層神經元數量爆炸性增長。相比之下GRU參數少,但是可能效果略差。

LSTM(3層)

=================================================================
input_3 (InputLayer) (None, 40, 8) 0


lstm_5 (LSTM) (None, 16) 1600


repeat_vector_3 (RepeatVecto (None, 40, 16) 0


=================================================================
Total params: 2,400
Trainable params: 2,400
Non-trainable params: 0
所以是2400/3 ,平均每層=800 個超參數

隱層神經元有16變爲64個後
Layer (type) Output Shape Param #

input_3 (InputLayer) (None, 40, 8) 0


lstm_1 (LSTM) (None, 40, 64) 18688


lstm_2 (LSTM) (None, 16) 5184


repeat_vector_3 (RepeatVecto (None, 40, 16) 0


=================================================================
Total params: 24,672
Trainable params: 24,672
Non-trainable params: 0
所以平均每層=8000參數

2.理解它的張量維度轉換是難點。還有個難點是timedistributed層,不用過多理解,當你要把LSTM(return_sequences=True時)和全連接層直接相連,你就要插入這個層。不然報錯!

LSTM的資料鏈接?

視頻課就看莫凡(我老師朋友的學生,已經畢業去TENCENT)的吧,講得很好。
1.https://morvanzhou.github.io/tutorials/machine-learning/keras/2-5-RNN-LSTM-Regressor/
2.https://keras.io/zh/ 第90頁左右

LSTM的學術用途與進階展望分析?

往往現實中有很多自迴歸/迴歸問題,屬於時間序列分析範疇就可以用LSTM來解決。比如股價預測,場站客流預測,交通流預測,經濟產值預測;圖片分類(比CNN差點)。在車輛控制,交通誘導的深度強化學習領域還有人用它進行車輛智能體的試錯學習的記憶強化,優化訓練過程,在DDPG的critic network和actor network範疇。

敲下黑板,我們在用LSTM的同時,更需要辯證的理解它,適合自己的纔是最好。不能因爲它比ARIMA HMM模型 移動平均法 新 高大上 就用,LSTM是難以解釋的(不過已經有方法了。)

這一塊歡迎同學留言,我就附上一些論文鏈接:
1.https://kns.cnki.net/KCMS/detail/detail.aspx?dbcode=CJFQ&dbname=CJFDLAST2019&filename=DLDY201905024&v=MTY0NDk5ak1xbzlIWUlSOGVYMUx1eFlTN0RoMVQzcVRyV00xRnJDVVI3cWZaZVJyRnlqbFdydklJU0hQZDdHNEg=
2.https://kns.cnki.net/KCMS/detail/detail.aspx?dbcode=CJFQ&dbname=CJFDLAST2019&filename=JSJK201909011&v=MTc5ODBGckNVUjdxZlplUnJGeWpsVzc3S0x6N0JaYkc0SDlqTXBvOUVaWVI4ZVgxTHV4WVM3RGgxVDNxVHJXTTE=
3.https://kns.cnki.net/KCMS/detail/detail.aspx?dbcode=CMFD&dbname=CMFD201902&filename=1019099446.nh&v=MDU1NTExVDNxVHJXTTFGckNVUjdxZlplUnJGeWpsVzczTlZGMjZGN094RjlYSXFaRWJQSVI4ZVgxTHV4WVM3RGg=
4.https://www.sciencedirect.com/science/article/pii/S187705091930969X
5.https://www.sciencedirect.com/science/article/pii/S0968090X1830158X
在這裏插入圖片描述
參考博客鏈接:
https://blog.csdn.net/Geek_of_CSDN/article/details/86559464?ops_request_misc=%7B%22request_id%22%3A%22158242563619724846404799%22%2C%22scm%22%3A%2220140713.130056874…%22%7D&request_id=158242563619724846404799&biz_id=0&utm_source=distribute.pc_search_result.none-task

https://blog.csdn.net/destiny_block/article/details/89153617?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task

https://blog.csdn.net/owenfy/article/details/80022586
版權聲明:本文爲CSDN博主「TJXFXZ」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章