10分鐘快速入門PyTorch (5)

前面一節(jié)我們講了cnn以及如何使用pytorch實現(xiàn)簡單的多層卷積神經(jīng)網(wǎng)絡(luò),下面我們將進入rnn,對于rnn我也涉及不多,歡迎各位高手提出寶貴的意見。

關(guān)于rnn將分成三個部分,第一個部分先介紹rnn的基本結(jié)構(gòu)以及在pytorch里面api的各個參數(shù)所表示的含義,下一個部分將介紹rnn如何在MNIST數(shù)據(jù)集上做分類,最后一個部分涉及一點點自然語言處理的東西。

RNN

首先介紹一下什么是rnn,rnn特別擅長處理序列類型的數(shù)據(jù),因為他是一個循環(huán)的結(jié)構(gòu)

1

一個序列的數(shù)據(jù)依次進入網(wǎng)絡(luò)A,網(wǎng)絡(luò)A循環(huán)的往后傳遞。

這就是RNN的基本結(jié)構(gòu)類型。而最早的RNN模型,序列依次進入網(wǎng)絡(luò)中,之前進入序列的數(shù)據(jù)會保存信息而對后面的數(shù)據(jù)產(chǎn)生影響,所以RNN有著記憶的特性,而同時越前面的數(shù)據(jù)進入序列的時間越早,所以對后面的數(shù)據(jù)的影響也就越弱,簡而言之就是一個數(shù)據(jù)會更大程度受到其臨近數(shù)據(jù)的影響。但是我們很有可能需要更長時間之前的信息,而這個能力傳統(tǒng)的RNN特別弱,于是有了LSTM這個變體。

LSTM

2

這就是LSTM的模型結(jié)構(gòu),也是一個向后傳遞的鏈式模型,而現(xiàn)在廣泛使用的RNN其實就是LSTM,序列中每個數(shù)據(jù)傳入LSTM可以得到兩個輸出,而這兩個輸出和序列中下一個數(shù)據(jù)一起又作為傳入LSTM的輸入,然后不斷地循環(huán)向后,直到序列結(jié)束。

下面結(jié)合pytorch一步一步來看數(shù)據(jù)傳入LSTM是怎么運算的

首先需要定義好LSTM網(wǎng)絡(luò),需要nn.LSTM(),首先介紹一下這個函數(shù)里面的參數(shù)

input_size 表示的是輸入的數(shù)據(jù)維數(shù)

hidden_size 表示的是輸出維數(shù)

num_layers 表示堆疊幾層的LSTM,默認是1

bias True 或者 False,決定是否使用bias

batch_first True 或者 False,因為nn.lstm()接受的數(shù)據(jù)輸入是(序列長度,batch,輸入維數(shù)),這和我們cnn輸入的方式不太一致,所以使用batch_first,我們可以將輸入變成(batch,序列長度,輸入維數(shù))

dropout 表示除了最后一層之外都引入一個dropout

bidirectional 表示雙向LSTM,也就是序列從左往右算一次,從右往左又算一次,這樣就可以兩倍的輸出

3

第一步首先是將傳入的數(shù)據(jù)$x_t$和前面輸出的$h_{t-1}$,$x_t$是輸入的維數(shù),比如是K,$h_{t-1}$是網(wǎng)絡(luò)的輸出維數(shù),比如M,因為輸出的維度是M,權(quán)重w的維數(shù)就是(M, M)和(M, K),b的維數(shù)就是(M, 1)和(M, 1),最后經(jīng)過sigmoid激活函數(shù),得到的f的維數(shù)是(M, 1)。

對于第一個數(shù)據(jù),需要定義初始的h_0和c_0,所以nn.lstm()的輸入Inputs:input, (h_0, c_0),表示輸入的數(shù)據(jù)以及h_0和c_0,這個可以自己定義,如果不定義,默認就是0

4

第二步也是差不多的操作,只不多是另外兩個權(quán)重加上不同的激活函數(shù),一個使用的是sigmoid,一個使用的是tanh,得到的輸出$i_t$和$\tilde{C}_t$都是(M, 1)。

5

接著這個乘法是矩陣每個位置對應(yīng)相乘,然后將兩個矩陣加起來,得到的輸出$C_t$是(M, 1)。

6

最后一步得到的$o_t$也是(M, 1),然后$C_t$經(jīng)過激活函數(shù)tanh,再和$o_t$每個位置相乘,得到的輸出$h_t$也是(M, 1)。

最后得到的輸出就是$h_t$和$C_t$,維數(shù)分別都是(M, 1),而輸入$x_t$維數(shù)都是(K, 1)。

lstm = nn.LSTM(10, 30, batch_first=True)

可以通過這樣定義一個一層的LSTM輸入是10,輸出是30

lstm.weight_hh_l0.size()
lstm.weight_ih_l0.size()
lstm.bias_hh_l0.size()
lstm.bias__ih_l0.size()

可以分別得到權(quán)重的維數(shù),注意之前我們定義的4個weights被整合到了一起,比如這個lstm,輸入是10維,輸出是30維,相對應(yīng)的weight就是30x10,這樣的權(quán)重有4個,然后pytorch將這4個組合在了一起,方便表示,也就是lstm.weight_ih_l0,所以它的維數(shù)就是120x10

我們定義一個輸入

x = Variable(torch.randn((50, 100, 10)))
h0 = Variable(torch.randn(1, 50, 30))
c0 = Variable(torch.randn(1, 50 ,30))

x的三個數(shù)字分別表示batch_size為50,序列長度為100,每個數(shù)據(jù)維數(shù)為10

h0的第二個參數(shù)表示batch_size為50,輸出維數(shù)為30,第一個參數(shù)取決于網(wǎng)絡(luò)層數(shù)和是否是雙向的,如果雙向需要乘2,如果是多層,就需要乘以網(wǎng)絡(luò)層數(shù)

c0的三個參數(shù)和h0是一致的

out, (h_out, c_out) = lstm(x, (h0, c0))

這樣就可以得到網(wǎng)絡(luò)的輸出了,和上面講的一致,另外如果不傳入h0和c0,默認的會傳入相同維數(shù)的0矩陣

這就是我們?nèi)绾卧趐ytorch上使用RNN的基本操作了,了解完最基本的參數(shù)我們才能夠使用其來做應(yīng)用。

本文參考的資料來自如下博客

更多的RNN的應(yīng)用可以看這個資源


本文代碼已經(jīng)上傳到了github

歡迎查看我的知乎專欄,深度煉丹

歡迎訪問我的博客

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容