日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人工智能 > pytorch >内容正文

pytorch

[深度学习] Pytorch中RNN/LSTM 模型小结

發布時間:2023/12/15 pytorch 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [深度学习] Pytorch中RNN/LSTM 模型小结 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

一 Liner

二 RNN

三 LSTM

四 LSTM 代碼例子


概念介紹可以參考:[深度學習]理解RNN, GRU, LSTM 網絡

Pytorch中所有模型分為構造參數和輸入和輸出構造參數兩種類型。

  • ?模型構造參數主要限定了網絡的結構,如對循環網絡,則包括輸入維度、隱層\輸出維度、層數;對卷積網絡,無論卷積層還是池化層,都不關心輸入維度,其構造方法只涉及卷積核大小\步長等。這里的參數決定了模型持久化后的大小.
  • ?輸入和輸出的構造參數一般和模型訓練相關,都需指定batch大小,seq大小(循環網絡)\chanel大小(卷積網絡),以及輸入\輸出維度,如果是RNN還需涉及h0和c0的初始化等。這里的參數決定了模型訓練效果。

?

一 Liner

  • Liner(x_dim,y_dim)
    – 輸入x,程序輸入(batch,x)
    – 輸出y, 程序輸出(batch,y)
import torch import torch.nn as nn from torch.autograd import Variable as V line = nn.Linear(2, 4) # 輸入2維,輸出4維 print(line) print(line.weight) # 參數是隨機初始化的,維度為out_dim * in_dim

?

x = V(torch.randn(5,2)) # batch為5,即一次輸入10個x print(x) line(x) # 輸出為batch*4

?

二 RNN

對于不同的網絡層,輸入的維度雖然不同,但是通常輸入的第一個維度都是batch_size,比如torch.nn.Linear的輸入(batch_size,in_features),torch.nn.Conv2d的輸入(batch_size,??,)。而RNN的輸入卻是(seq_len, batch_size, input_size),batch_size位于第二維度!雖然你可以將batch_size和序列長度seq_len對換位置,此時只需要把batch_first設置為True。但是默認情況下RNN輸入為啥不是batch first?原因同上,因為cuDNN中RNN的API就是batch_size在第二維度!進一步,為啥cuDNN要這么做呢?

因為batch first意味著模型的輸入(一個Tensor)在內存中存儲時,先存儲第一個sequence,再存儲第二個... 而如果是seq_len first,模型的輸入在內存中,先存儲所有序列的第一個單元,然后是第二個單元... 兩種區別如下圖所示:

seq_len first意味著不同序列中同一個時刻對應的輸入單元在內存中是毗鄰的,這樣才能做到真正的batch計算。

CNN中和RNNbatchSize的默認位置是不同的。

  • CNN中:batchsize的位置是position 0.
  • RNN中:batchsize的位置是position 1.

?

首先介紹一下什么是rnn,rnn特別擅長處理序列類型的數據,因為他是一個循環的結構

一個序列的數據依次進入網絡A,網絡A循環的往后傳遞。

這里輸入X一般是一個sequence, 如[我 愛 上海 小籠包]

對于最簡單的 RNN,我們可以使用下面兩種方式去調用,分別是 torch.nn.RNNCell() 和 torch.nn.RNN(),這兩種方式的區別在于 RNNCell() 只能接受序列中單步的輸入,且必須傳入隱藏狀態,而 RNN() 可以接受一個序列的輸入,默認會傳入全 0 的隱藏狀態,也可以自己申明隱藏狀態傳入。
?

  • 輸入大小是三維tensor[seq_len,batch_size,input_dim]
    • input_dim是輸入的維度,比如是128
    • batch_size是一次往RNN輸入句子的數目,比如是5。
    • seq_len是一個句子的最大長度,比如15
      所以千萬注意,RNN輸入的是序列,一次把批次的所有句子都輸入了,得到的ouptut和hidden都是這個批次的所有的輸出和隱藏狀態,維度也是三維。
      **可以理解為現在一共有batch_size個獨立的RNN組件,RNN的輸入維度是input_dim,總共輸入seq_len個時間步,則每個時間步輸入到這個整個RNN模塊的維度是[batch_size,input_dim]

    ?

    # 構造RNN網絡,x的維度5,隱層的維度10,網絡的層數2 rnn_seq = nn.RNN(5, 10,2) # 構造一個輸入序列,長為 6,batch 是 3, 特征是 5 x = V(torch.randn(6, 3, 5)) #out,ht = rnn_seq(x, h0) # h0可以指定或者不指定 out,ht = rnn_seq(x) # q1:這里out、ht的size是多少呢? out:6*3*10, ht:2*3*10

    問題1:這里out、ht的size是多少呢?
    回答:out:6 * 3 * 10, ht: 2 * 3 * 10,out的輸出維度[seq_len,batch_size,output_dim],ht的維度[num_layers * num_directions, batch, hidden_size],如果是單向單層的RNN那么一個句子只有一個hidden。
    問題2:out[-1]和ht[-1]是否相等?
    回答:相等,隱藏單元就是輸出的最后一個單元,可以想象,每個的輸出其實就是那個時間步的隱藏單元

    ?

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

    三 LSTM

    ?

    這就是LSTM的模型結構,也是一個向后傳遞的鏈式模型,而現在廣泛使用的RNN其實就是LSTM,序列中每個數據傳入LSTM可以得到兩個輸出,而這兩個輸出和序列中下一個數據一起又作為傳入LSTM的輸入,然后不斷地循環向后,直到序列結束。

    注意共4個非線性變化。其中三個sigmoid變化分別對應的三個門:遺忘門f、輸入門(當前狀態)i、輸出門o。這三個門的取值為[0,1],可以看做選擇系數可以很好的控制信息的傳導。

    ?

    LSTM參數

    • input_size 表示的是輸入的數據維數
    • hidden_size 表示的是輸出維數
    • num_layers 表示堆疊幾層的LSTM,默認是1
    • bias True 或者 False,決定是否使用bias, False則b_h=0. 默認為True
    • batch_first True 或者 False,因為nn.lstm()接受的數據輸入是(序列長度,batch,輸入維數),這和我們cnn輸入的方式不太一致,所以使用batch_first,我們可以將輸入變成(batch,序列長度,輸入維數)
    • dropout 表示除了最后一層之外都引入一個dropout,
    • bidirectional 表示雙向LSTM,也就是序列從左往右算一次,從右往左又算一次,這樣就可以兩倍的輸出

    ?

    LSTM數據格式:

    • num_layers: 我們構建的循環網絡有幾層lstm

    • num_directions: 當bidirectional=True時,num_directions=2;當bidirectional=False時,num_directions=1

    LSTM? Input 數據格式

    ? LSTM輸入的X數據格式尺寸為(seq_len, batch, input_size),此外h0和c0尺寸如下

    • h0(num_layers * num_directions, ?batch_size, ?hidden_size)

    • c0(num_layers * num_directions, ?batch_size, ?hidden_size)

    LSTM? Output 數據格式

    ? LSTM輸出數據格式尺寸為(seq_len, batch, hidden_size * num_directions);輸出的hn和cn尺寸如下

    • hn(num_layers * num_directions, ?batch_size, ?hidden_size)

    • cn(num_layers * num_directions, ?batch_size, ?hidden_size)

    LSTM的輸出多了一個memory單元

    # 輸入維度 50,隱層100維,兩層 lstm_seq = nn.LSTM(50, 100, num_layers=2) # 輸入序列seq= 10,batch =3,輸入維度=50 lstm_input = torch.randn(10, 3, 50) out, (h, c) = lstm_seq(lstm_input) # 使用默認的全 0 隱藏狀態

    問題1:out和(h,c)的size各是多少?
    回答:out:(10 * 3 * 100),(h,c):都是(2 * 3 * 100)
    問題2:out[-1,:,:]和h[-1,:,:]相等嗎?
    回答: 相等


    四 LSTM 代碼例子

    ?

    Example 1

    # 輸入維度 50,隱層100維,兩層 lstm_seq = nn.LSTM(50, 100, num_layers=2) # 查看網絡的權重,ih和hh,共2層,所以有四個要學習的參數 print(lstm_seq.weight_hh_l0.size()) print(lstm_seq.weight_ih_l0.size()) print(lstm_seq.weight_hh_l1.size()) print(lstm_seq.weight_ih_l1.size()) # q1: 輸出的size是多少?#torch.Size([400, 100]) #torch.Size([400, 50]) #torch.Size([400, 100]) #torch.Size([400, 100])

    ?

    # 輸入序列seq= 10,batch =3,輸入維度=50 lstm_input = V(torch.randn(10, 3, 50)) out, (h, c) = lstm_seq(lstm_input) # 使用默認的全 0 隱藏狀態 # q1:out和(h,c)的size各是多少?out:(10*3*100),(h,c):都是(2*3*100) print(out.shape, h.shape, c.shape)#torch.Size([10, 3, 100]) torch.Size([2, 3, 100]) torch.Size([2, 3, 100])

    Example 2

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

    from torch.autograd import Variable lstm = nn.LSTM(10, 30, batch_first=True) print(lstm.weight_hh_l0.size()) print(lstm.weight_ih_l0.size()) print(lstm.bias_hh_l0.size()) print(lstm.bias_ih_l0.size())#torch.Size([120, 30]) #torch.Size([120, 10]) #torch.Size([120]) #torch.Size([120])

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

    我們定義一個輸入

    x = Variable(torch.randn((50, 100, 10))) h0 = Variable(torch.randn(1, 50, 30)) c0 = Variable(torch.randn(1, 50 ,30))
    • x的三個數字分別表示batch_size為50,序列長度為100,每個數據維數為10
    • h0的第二個參數表示batch_size為50,輸出維數為30,第一個參數取決于網絡層數和是否是雙向的,如果雙向需要乘2,如果是多層,就需要乘以網絡層數
    • c0的三個參數和h0是一致的
    out, (h_out, c_out) = lstm(x, (h0, c0))

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

    這就是我們如何在pytorch上使用RNN的基本操作了,了解完最基本的參數我們才能夠使用其來做應用。


    Example 3

    使用單向LSTM進行MNIST分類

    import torch from torch import nn from torch.autograd import Variable import torchvision.datasets as datasets import torchvision.transforms as transforms import numpy as np import matplotlib.pyplot as plt# 超參數 EPOCH = 1 BATCH_SIZE = 64 TIME_STEP = 28 # rnn time step / image height INPUT_SIZE = 28 # rnn input size / image width LR = 0.01 DOWNLOWD_MNIST = False # 如果沒有下載好MNIST數據,設置為True# 下載數據 # 訓練數據 train_data = datasets.MNIST(root='./mnist', train=True, transform=transforms.ToTensor(), download=DOWNLOWD_MNIST) train_loader = torch.utils.data.DataLoader(dataset=train_data, batch_size=BATCH_SIZE, shuffle=True)# 測試數據 test_data = datasets.MNIST(root='./mnist', train=False, transform=transforms.ToTensor()) test_x = Variable(test_data.test_data).type(torch.FloatTensor)[:2000] / 255. test_y = np.squeeze(test_data.test_labels.numpy())[:2000]class RNN(nn.Module):def __init__(self):super(RNN, self).__init__()self.rnn = nn.LSTM(input_size=INPUT_SIZE,hidden_size=64,num_layers=2, # hidden_layer的數目batch_first=True, # 輸入數據的維度一般是(batch, time_step, input),該屬性表征batch是否放在第一個維度)self.out = nn.Linear(64, 10)def forward(self, x):# rnn 運行的結果出了每層的輸出之外,還有該層要傳入下一層進行輔助分析的hidden state,# lstm 的hidden state相比于 RNN,其分成了主線h_n,分線h_cr_out, (h_n, h_c) = self.rnn(x, None) # x shape ( batch, step, input_size), None 之前的hidden state(沒有則填None)out = self.out(r_out[:, -1, :]) # 選取最后一個時刻的output,進行最終的類別判斷return outrnn = RNN() # print(rnn)# 優化器 optimizer = torch.optim.Adam(rnn.parameters(), lr=LR) # 誤差函數 loss_func = nn.CrossEntropyLoss() for epoch in range(EPOCH):for step, (x, y) in enumerate(train_loader):b_x = Variable(x.view(-1, 28, 28)) # reshape x to (batch, time_step, input_size)b_y = Variable(y)output = rnn(b_x)loss = loss_func(output, b_y)optimizer.zero_grad()loss.backward()optimizer.step()if step % 50 == 0:test_output = rnn(test_x)pred_y = np.squeeze(torch.max(test_output, 1)[1].data.numpy())accuracy = float((pred_y == test_y).astype(int).sum()) / float(test_y.size)print('Epoch: ', epoch, ' | train loss: %.4f' % loss.data.numpy(), ' | test accuracy: %.2f' % accuracy )

    ?

    # 輸出前10個測試數據的測試值 test_output = rnn(test_x[: 10].view(-1, 28, 28)) pred_y = np.squeeze(torch.max(test_output, 1)[1].data.numpy()) print(pred_y, 'prediction number') print(test_y[:10], 'real number')

    ?

    由上面代碼可以看到輸出為:output,(h_n,c_n)=self.rnn(x)

    ?

    ?

    ?

    更多的RNN的應用可以看這個資源

    ?

    總結

    以上是生活随笔為你收集整理的[深度学习] Pytorch中RNN/LSTM 模型小结的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。