為了解決傳統RNN無法長時依賴問題,RNN的兩個變體LSTM和GRU被引入。
LSTM
Long Short Term Memory,稱為長短期記憶網絡,意思就是長的短時記憶,其解決的仍然是短時記憶問題,這種短時記憶比較長,能一定程度上解決長時依賴。
上圖為LSTM的抽象結構,LSTM由3個門來控制,分別是輸入門、遺忘門和輸出門。輸入門控制網絡的輸入,遺忘門控制著記憶單元,輸出門控制著網絡的輸出。最為重要的就是遺忘門,可以決定哪些記憶被保留,由于遺忘門的作用,使得LSTM具有長時記憶的功能。對于給定的任務,遺忘門能夠自主學習保留多少之前的記憶,網絡能夠自主學習。
具體看LSTM單元的內部結構:
在每篇文章中,作者都會使用和標準LSTM稍微不同的版本,針對特定的任務,特定的網絡結構往往表現更好。
GRU
上述的過程的線性變換沒有使用偏置。隱藏狀態參數不再是標準RNN的4倍,而是3倍,也就是GRU的參數要比LSTM的參數量要少,但是性能差不多。
Pytorch
在Pytorch中使用nn.LSTM()可調用,參數和RNN的參數相同。具體介紹LSTM的輸入和輸出:
輸入: input, (h_0, c_0)
input:輸入數據with維度(seq_len,batch,input_size)
h_0:維度為(num_layers*num_directions,batch,hidden_size),在batch中的
初始的隱藏狀態.
c_0:初始的單元狀態,維度與h_0相同
輸出:output, (h_n, c_n)
output:維度為(seq_len, batch, num_directions * hidden_size)。
h_n:最后時刻的輸出隱藏狀態,維度為 (num_layers * num_directions, batch, hidden_size)
c_n:最后時刻的輸出單元狀態,維度與h_n相同。
LSTM的變量:
以MNIST分類為例實現LSTM分類
MNIST圖片大小為28×28,可以將每張圖片看做是長為28的序列,序列中每個元素的特征維度為28。將最后輸出的隱藏狀態 作為抽象的隱藏特征輸入到全連接層進行分類。最后輸出的
導入頭文件:
1
2
3
4
5
|
import torch import torch.nn as nn import torch.optim as optim import torchvision from torchvision import transforms |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
class Rnn(nn.Module): def __init__( self , in_dim, hidden_dim, n_layer, n_classes): super (Rnn, self ).__init__() self .n_layer = n_layer self .hidden_dim = hidden_dim self .lstm = nn.LSTM(in_dim, hidden_dim, n_layer, batch_first = True ) self .classifier = nn.Linear(hidden_dim, n_classes) def forward( self , x): out, (h_n, c_n) = self .lstm(x) # 此時可以從out中獲得最終輸出的狀態h # x = out[:, -1, :] x = h_n[ - 1 , :, :] x = self .classifier(x) return x |
訓練和測試代碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
|
transform = transforms.Compose([ transforms.ToTensor(), transforms.Normalize([ 0.5 ], [ 0.5 ]), ]) trainset = torchvision.datasets.MNIST(root = './data' , train = True , download = True , transform = transform) trainloader = torch.utils.data.DataLoader(trainset, batch_size = 128 , shuffle = True ) testset = torchvision.datasets.MNIST(root = './data' , train = False , download = True , transform = transform) testloader = torch.utils.data.DataLoader(testset, batch_size = 100 , shuffle = False ) net = Rnn( 28 , 10 , 2 , 10 ) net = net.to( 'cpu' ) criterion = nn.CrossEntropyLoss() optimizer = optim.SGD(net.parameters(), lr = 0.1 , momentum = 0.9 ) # Training def train(epoch): print ( '\nEpoch: %d' % epoch) net.train() train_loss = 0 correct = 0 total = 0 for batch_idx, (inputs, targets) in enumerate (trainloader): inputs, targets = inputs.to( 'cpu' ), targets.to( 'cpu' ) optimizer.zero_grad() outputs = net(torch.squeeze(inputs, 1 )) loss = criterion(outputs, targets) loss.backward() optimizer.step() train_loss + = loss.item() _, predicted = outputs. max ( 1 ) total + = targets.size( 0 ) correct + = predicted.eq(targets). sum ().item() print (batch_idx, len (trainloader), 'Loss: %.3f | Acc: %.3f%% (%d/%d)' % (train_loss / (batch_idx + 1 ), 100. * correct / total, correct, total)) def test(epoch): global best_acc net. eval () test_loss = 0 correct = 0 total = 0 with torch.no_grad(): for batch_idx, (inputs, targets) in enumerate (testloader): inputs, targets = inputs.to( 'cpu' ), targets.to( 'cpu' ) outputs = net(torch.squeeze(inputs, 1 )) loss = criterion(outputs, targets) test_loss + = loss.item() _, predicted = outputs. max ( 1 ) total + = targets.size( 0 ) correct + = predicted.eq(targets). sum ().item() print (batch_idx, len (testloader), 'Loss: %.3f | Acc: %.3f%% (%d/%d)' % (test_loss / (batch_idx + 1 ), 100. * correct / total, correct, total)) for epoch in range ( 200 ): train(epoch) test(epoch) |
以上這篇Pytorch實現LSTM和GRU示例就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支持服務器之家。
原文鏈接:https://blog.csdn.net/winycg/article/details/88937583