torch.nn.lstm參數


 

這里num_layers是同一個time_step的結構堆疊,Lstm堆疊層數與time step無關。Time step表示的是時間序列長度,它是由數據的inputsize決定,你輸的數據時序有多長,那么神經網絡會自動確定,時間序列長度只需要與你輸入的數據時序長度保持一致即可。

lstm=nn.LSTM(input_size,                     hidden_size,                      num_layers)
x                         seq_len,                          batch,                              input_size
h0            num_layers× \times×num_directions,   batch,                             hidden_size
c0            num_layers× \times×num_directions,   batch,                             hidden_size

output                 seq_len,                         batch,                num_directions× \times×hidden_size
hn            num_layers× \times×num_directions,   batch,                             hidden_size
cn            num_layers× \times×num_directions,    batch,                            hidden_size

舉個例子:
對句子進行LSTM操作

假設有100個句子(sequence),每個句子里有7個詞,batch_size=64,embedding_size=300

此時,各個參數為:
input_size=embedding_size=300
batch=batch_size=64
seq_len=7

另外設置hidden_size=100, num_layers=1

import torch
import torch.nn as nn
lstm = nn.LSTM(300, 100, 1)
x = torch.randn(7, 64, 300)
h0 = torch.randn(1, 64, 100)      

c0 = torch.randn(1, 64, 100)

output, (hn, cn)=lstm(x, (h0, c0))

>>
output.shape torch.Size([7, 64, 100])
hn.shape torch.Size([1, 64, 100])
cn.shape torch.Size([1, 64, 100])
--------------------- 
作者:huxuedan01 
來源:CSDN 
原文:https://blog.csdn.net/m0_37586991/article/details/88561746 
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!

二、雙向LSTM模型

1、雙向LSTM的結構

雙向LSTM(Bidirectional Long-Short Term Memorry,Bi-LSTM)不僅能利用到過去的信息,還能捕捉到后續的信息,比如在詞性標注問題中,一個詞的詞性由上下文的詞所決定,那么用雙向LSTM就可以利用好上下文的信息。

雙向LSTM由兩個信息傳遞相反的LSTM循環層構成,其中第一層按時間順序傳遞信息,第二層按時間逆序傳遞信息。

沒有去找雙向LSTM的圖了,就看這個雙向RNN的結構來學習吧,理解了雙向RNN,那么把循環層的記憶細胞換成LSTM就行。

2、雙向LSTM隱狀態的計算

關鍵在於隱狀態如何計算。為了簡單,還是按照雙向RNN的公式進行理解,我們看隱狀態如何計算。可以看到t時刻第一層(順時間循環層)的隱狀態ht(1)取決於前一時刻的隱狀態ht-1(1)和輸入值xt,這一點非常容易理解。

而要注意的是第二層(逆時間循環層)的隱狀態則依然取決於前一時刻的隱狀態和輸入值x,這與堆疊的LSTM不同,堆疊的LSTM其l層的隱狀態不由輸入值x直接輸入得到,而是取決於該層前一時刻的隱狀態和當前時刻下一層的隱狀態。如下的公式就是堆疊的循環網絡層中隱狀態的計算過程。

雙向LSTM和堆疊的LSTM可以結合使用,在順時間循環層我們可以構造堆疊多層的LSTM,同樣,在逆時間循環層可以堆疊多個。

而雙向LSTM的一個循環層中有兩個隱狀態,長期狀態C用於內部傳遞信息,不拋頭露面,而短期狀態h則作為該循環層的輸出,用於其他循環層或全連接層的計算。因此在對得的雙向LSTM的最后一步,會有超過4個隱狀態存在。

 

先上結論:

  1. output保存了最后一層,每個time step的輸出h,如果是雙向LSTM,每個time step的輸出h = [h正向, h逆向] (同一個time step的正向和逆向的h連接起來)。
  2. h_n保存了每一層,最后一個time step的輸出h,如果是雙向LSTM,單獨保存前向和后向的最后一個time step的輸出h。
  3. c_n與h_n一致,只是它保存的是c的值。

下面單獨分析三個輸出:

  1. output是一個三維的張量,第一維表示序列長度,第二維表示一批的樣本數(batch),第三維是 hidden_size(隱藏層大小) * num_directions ,這里是我遇到的第一個不理解的地方,hidden_sizes由我們自己定義,num_directions這是個什么鬼?翻看源碼才明白,先貼出代碼,從代碼中可以發現num_directions根據是“否為雙向”取值為1或2。因此,我們可以知道,output第三個維度的尺寸根據是否為雙向而變化,如果不是雙向,第三個維度等於我們定義的隱藏層大小;如果是雙向的,第三個維度的大小等於2倍的隱藏層大小。為什么使用2倍的隱藏層大小?因為它把每個time step的前向和后向的輸出連接起來了,后面會有一個實驗,方便我們記憶。

 

 

2. h_n是一個三維的張量,第一維是num_layers*num_directions,num_layers是我們定義的神經網絡的層數,num_directions在上面介紹過,取值為1或2,表示是否為雙向LSTM。第二維表示一批的樣本數量(batch)。第三維表示隱藏層的大小。第一個維度是h_n難理解的地方。首先我們定義當前的LSTM為單向LSTM,則第一維的大小是num_layers,該維度表示第n層最后一個time step的輸出。如果是雙向LSTM,則第一維的大小是2 * num_layers,此時,該維度依舊表示每一層最后一個time step的輸出,同時前向和后向的運算時最后一個time step的輸出用了一個該維度。

  • 舉個例子,我們定義一個num_layers=3的雙向LSTM,h_n第一個維度的大小就等於 6 (2*3),h_n[0]表示第一層前向傳播最后一個time
    step的輸出,h_n[1]表示第一層后向傳播最后一個time step的輸出,h_n[2]表示第二層前向傳播最后一個time step的輸出,h_n[3]表示第二層后向傳播最后一個time step的輸出,h_n[4]和h_n[5]分別表示第三層前向和后向傳播時最后一個time step的輸出。

3. c_n與h_n的結構一樣,就不重復贅述了。

給出一個樣例圖(畫工太差,如有錯誤請指正),對比前面的例子自己分析下

最后上一段代碼結束戰斗

import torch
import torch.nn as nn

定義一個兩層雙向的LSTM,input size為10,hidden size為20。

隨機生成一個輸入樣本,sequence length為5,batch size為3,input size與定義的網絡一致,為10。

手動初始化h0和c0,兩個結構一致(num_layers * 2, batch, hidden_size) = (4, 3, 20)。

如果不初始化,PyTorch默認初始化為全零的張量。

bilstm = nn.LSTM(input_size=10, hidden_size=20, num_layers=2, bidirectional=True)
input = torch.randn(5, 3, 10)
h0 = torch.randn(4, 3, 20)
c0 = torch.randn(4, 3, 20)
output, (hn, cn) = bilstm(input, (h0, c0))

查看output,hn,cn的維度

print('output shape: ', output.shape)
print('hn shape: ', hn.shape)
print('cn shape: ', cn.shape)
輸出:
output shape:  torch.Size([5, 3, 40])
hn shape:  torch.Size([4, 3, 20])
cn shape:  torch.Size([4, 3, 20])

根據一開始結論,我們來驗證下。

1.前向傳播時,output中最后一個time step的前20個與hn最后一層前向傳播的輸出應該一致。

output[4, 0, :20] == hn[2, 0]
輸出:
tensor([ 1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
         1,  1,  1,  1,  1,  1], dtype=torch.uint8)

2.后向傳播時,output中最后一個time step的后20個與hn最后一層后向傳播的輸出應該一致。

output[0, 0, 20:] == hn[3, 0]
輸出:
tensor([ 1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
         1,  1,  1,  1,  1,  1], dtype=torch.uint8)
 
       


免責聲明!

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



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