Pytorch實現(xiàn)LSTM和GRU示例
為了解決傳統(tǒng)RNN無法長時依賴問題,RNN的兩個變體LSTM和GRU被引入。
LSTM
Long Short Term Memory,稱為長短期記憶網(wǎng)絡(luò),意思就是長的短時記憶,其解決的仍然是短時記憶問題,這種短時記憶比較長,能一定程度上解決長時依賴。

上圖為LSTM的抽象結(jié)構(gòu),LSTM由3個門來控制,分別是輸入門、遺忘門和輸出門。輸入門控制網(wǎng)絡(luò)的輸入,遺忘門控制著記憶單元,輸出門控制著網(wǎng)絡(luò)的輸出。最為重要的就是遺忘門,可以決定哪些記憶被保留,由于遺忘門的作用,使得LSTM具有長時記憶的功能。對于給定的任務(wù),遺忘門能夠自主學(xué)習(xí)保留多少之前的記憶,網(wǎng)絡(luò)能夠自主學(xué)習(xí)。
具體看LSTM單元的內(nèi)部結(jié)構(gòu):




在每篇文章中,作者都會使用和標準LSTM稍微不同的版本,針對特定的任務(wù),特定的網(wǎng)絡(luò)結(jié)構(gòu)往往表現(xiàn)更好。
GRU

上述的過程的線性變換沒有使用偏置。隱藏狀態(tài)參數(shù)不再是標準RNN的4倍,而是3倍,也就是GRU的參數(shù)要比LSTM的參數(shù)量要少,但是性能差不多。
Pytorch
在Pytorch中使用nn.LSTM()可調(diào)用,參數(shù)和RNN的參數(shù)相同。具體介紹LSTM的輸入和輸出:
輸入: input, (h_0, c_0)
input:輸入數(shù)據(jù)with維度(seq_len,batch,input_size)
h_0:維度為(num_layers*num_directions,batch,hidden_size),在batch中的
初始的隱藏狀態(tài).
c_0:初始的單元狀態(tài),維度與h_0相同
輸出:output, (h_n, c_n)
output:維度為(seq_len, batch, num_directions * hidden_size)。
h_n:最后時刻的輸出隱藏狀態(tài),維度為 (num_layers * num_directions, batch, hidden_size)
c_n:最后時刻的輸出單元狀態(tài),維度與h_n相同。
LSTM的變量:

以MNIST分類為例實現(xiàn)LSTM分類
MNIST圖片大小為28×28,可以將每張圖片看做是長為28的序列,序列中每個元素的特征維度為28。將最后輸出的隱藏狀態(tài)
作為抽象的隱藏特征輸入到全連接層進行分類。最后輸出的
導(dǎo)入頭文件:
import torch import torch.nn as nn import torch.optim as optim import torchvision from torchvision import transforms
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中獲得最終輸出的狀態(tài)h
# x = out[:, -1, :]
x = h_n[-1, :, :]
x = self.classifier(x)
return x
訓(xùn)練和測試代碼:
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實現(xiàn)LSTM和GRU示例就是小編分享給大家的全部內(nèi)容了,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Pytorch 如何訓(xùn)練網(wǎng)絡(luò)時調(diào)整學(xué)習(xí)率
這篇文章主要介紹了Pytorch 如何訓(xùn)練網(wǎng)絡(luò)時調(diào)整學(xué)習(xí)率的操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-05-05
python網(wǎng)絡(luò)編程學(xué)習(xí)筆記(四):域名系統(tǒng)
當我們在上網(wǎng)的時候,通常輸入的是網(wǎng)址,其實這就是一個域名,而我們計算機網(wǎng)絡(luò)上的計算機彼此之間只能用IP地址才能相互識別2014-06-06
Python操作MySQL數(shù)據(jù)庫的示例代碼
這篇文章主要介紹了Python操作MySQL數(shù)據(jù)庫的方法,文中示例代碼非常詳細,幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下2020-07-07
Python利用itchat庫向好友或者公眾號發(fā)消息的實例
今天小編就為大家分享一篇Python利用itchat庫向好友或者公眾號發(fā)消息的實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-02-02
python爬取百度貼吧前1000頁內(nèi)容(requests庫面向?qū)ο笏枷雽崿F(xiàn))
這篇文章主要介紹了python爬取百度貼吧前1000頁內(nèi)容(requests庫面向?qū)ο笏枷雽崿F(xiàn)),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2019-08-08

