近幾天處理了幾天卷積LSTM,操作的數據格式太復雜,驀然回首,突然發現自己不明白LSTM中的輸入格式是什么了,於是寫一篇文章幫助自己回憶一下,也希望能幫助到一起正在機器學習的伙伴。補充一下,在LSTM之后,GRU和LSTM幾乎已經取代了傳統的RNN,因此在稱呼RNN的時候,大多數情況也是在稱呼LSTM,下文中可能會提到RNN,也是在說LSTM
按照Pytorch 給的文檔里格式寫一個LSTM
# author: https://www.cnblogs.com/danielkung/
lstm = torch.nn.LSTM(input_size, # INT,輸入的維度
hidden_size, # INT,隱藏層的維度
num_layers, # INT,LSTM的層數
bias, # BOOL,是否需要wx+b中的b
batch_first, # BOOL,輸入的數據第一維度為batch,與輸出無關
dropout, # BOOL,是否需要dropout
bidirectional) # BOOL,是否雙向RNN,是的話hidden,output都雙倍
intput = torch.randn(seq_len, batch, input_size) # 三個參數需要定義
output, hidden = lstm(input)
Q:在處理了無數次以后,我終於有一次懵圈了,啥是seq_len來着?
A:seq_len就是輸入的sequence_length(序列長度),既然LSTM是處理序列數據的,那么序列就需要一個長度。雖然LSTM處理的序列長度通常是不固定的,但是Pytorch和TensorFlow的集成實現還是固定了input的序列長度,在處理不固定長度的數據(如機器翻譯),通常加入開始和結束符號
來看幾個實際的例子:
1. 輸入長度不固定,輸出長度固定
我想做一個語句的情感分析(positve,negtive),或者給一串數字,預測這串數字的下一個數字是什么(例如某串長度為N,預測第N+1數字是什么)。
在第一個問題中,假設我們拿到了N條數據,每條包含的字數不定,但是可以知道最長的字數為MAX_LEN。首先我們需要進行word embedding,即把每個詞轉變為長度固定的矩陣。假如每個word被轉化為 [1*128] 的矩陣,那我們得到的數據格式就為:
[N, MAX_LEN+2, 128]
此時你也許會問,那長度不夠MAX_LEN的呢?不夠的就被填充到MAX_LEN,並且多的2是開頭和結尾的'sos''eos'。
然后在LSTM中,我們每次取N條中的batch_size條進行訓練,並且input的seq_len就是MAX_LEN+2。代碼:
# author: https://www.cnblogs.com/danielkung/
import torch
input_size = 128 # 輸入的維度,就是我們word_embedding的長度
hidden_size = 64 # 這里我自己定義的,定義的是lstm的hidden也是輸出的維度
num_layers = 1 # 先定義一層的LSTM
lstm = torch.nn.LSTM(input_size, hidden_size, num_layers)
input = getFromDataSet() # 函數沒定義,就是從data中取batch條數據,input的shape:[seq_len, batch_size, input_size]=[MAX_LEN+2, batch, 128]
output, hidden = lstm(input, hidden=None) # Pytorch的LSTM會自己初始化hidden,因此hidden不寫一樣
output1 = output[-1] # 取最后一層的輸出作為最終輸出,因為只有一層LSTM,output[-1]==output[0]
print(output.shape)
# RETURN: [seq_len, batch_size, hidden_size]
這里發現如果是做postive或者negtive分析的話,我們只需要一個數值,甚至只需要一個BOOL,因此還需要把輸出的output結果取最后一份output[-1],然后通過MLP即可,具體分析如圖。
代碼接上面繼續:
fc = nn.Linear(hidden_size, 1)
last_cell = outpu1t[-1] # shape: [batch_size, hidden_size]
# 由圖可見, 此時的last_cell就是LSTM的最后一次的輸出結果。
res = fc(last_cell) # shape: [batch_size, 1]
# 由此就得出了所有所有batch的預測結果。
Q:可能有人要問,輸出了那么多的output,只取最后一個用,這樣准確嗎?不浪費嗎?
A:不准,浪費。但是可以這么處理。在早期的sequence_to_sequence模型中,就是把encoder RNN的最后一個cell的輸出作為context傳給decoder,當然后來還有更好的辦法,如attention mechanism。在這里只展示最簡單的。
2. 輸入長度不固定,輸出長度不固定
如果輸出長度不固定,我們只需要把<1>中輸出中加入'sos''eos',並且去掉最后的全連接層就好了。
3. 特殊情況,seq_len的長度特別大
這類問題通常出現在文本翻譯或者文本處理,以及音頻、視頻處理中。我們需要把seq_len設置為一個適當的值,並且通過迭代,傳遞lstm的hidden_state的方式進行訓練。這對模型的設計,網絡的深度都有一定的要求,博客中就不在展示。
在相關領域已經有很多優秀的論文發表。
author:danielKKK