1. 程式人生 > 程式設計 >Pytorch實現LSTM和GRU示例

Pytorch實現LSTM和GRU示例

為了解決傳統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,hidden_size),在batch中的

初始的隱藏狀態.

c_0:初始的單元狀態,維度與h_0相同

輸出:output,(h_n,c_n)

output:維度為(seq_len,num_directions * hidden_size)。

h_n:最後時刻的輸出隱藏狀態,維度為 (num_layers * num_directions,hidden_size)

c_n:最後時刻的輸出單元狀態,維度與h_n相同。

LSTM的變數:

以MNIST分類為例實現LSTM分類

MNIST圖片大小為28×28,可以將每張圖片看做是長為28的序列,序列中每個元素的特徵維度為28。將最後輸出的隱藏狀態 作為抽象的隱藏特徵輸入到全連線層進行分類。最後輸出的

匯入標頭檔案:

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,batch_first=True)
    self.classifier = nn.Linear(hidden_dim,n_classes)

  def forward(self,x):
    out,c_n) = self.lstm(x)
    # 此時可以從out中獲得最終輸出的狀態h
    # x = out[:,-1,:]
    x = h_n[-1,:,:]
    x = self.classifier(x)
    return x

訓練和測試程式碼:

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,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,targets) in enumerate(testloader):
      inputs,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),total))




for epoch in range(200):
  train(epoch)
  test(epoch)

以上這篇Pytorch實現LSTM和GRU示例就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支援我們。