【學習筆記】RNN演算法的pytorch實現
阿新 • • 發佈:2022-04-18
一些新理解
之前我有個疑惑,RNN的網路視窗,換句話說不也算是一個卷積核嘛?那所有的網路模型其實不都是一個東西嗎?今天又聽了一遍RNN,發現自己大錯特錯,還是沒有學明白阿。因為RNN的視窗所包含的那一系列帶有時間序列的資料,他們再視窗內是相互影響的,這也正是RNN的核心,而不是像卷積那樣直接選個最大值,RNN會引入新的引數以保證每個時刻的值都能參與進去,影響最終結果。而且這裡的視窗大小,實質上是指你迴圈網路的層數
構造RNN
- 方式一:做自己的RNN cell,自己寫處理序列的迴圈
- 方式二:直接使用RNN
RNN cell
cell = torch.nn.RNNCell(input_size=input_size, hidden_size=hidden_size)
input_size
這個是你輸入的維度,hidden_size
這個是你隱藏層的維度,只有你有了這兩個值,你才能把權重和偏置的維度都確定下來
所以呼叫的時候不僅要給當前時刻的輸入,再加上當前的hidden
hidden = cell(inpput, hidden)
比如input是x1,hidden是h0,經過cell後就算出了h1,這裡有一個點很關鍵,就是這個input的維度和hidden的維度
input的維度包括batch和input_size,由於我們是批量輸入x,所以應該是輸入nx,因此batch是n,input_size就是x,而隱層的batch應該就是x乘以隱層的維度,輸出維度也是相同
舉例,程式碼和解釋註釋如下
import torch batch_size = 1 # 資料量 seq_len = 3 # 序列的個數與 input_size = 4 # 輸入資料的維度 hidden_size = 2 # 隱層維度 cell = torch.nn.RNNCell(input_size=input_size, hidden_size=hidden_size) # 確定cell維度 dataset = torch.rand(seq_len, batch_size, input_size) # 隨便設定下資料集 hidden = torch.zeros(batch_size, hidden_size) #隨便設定下隱層資料權重 for idx, input in enumerate(dataset): print('='*20, idx, '='*20) print('input size:', input.shape) hidden = cell(input, hidden) //RNN計算 print('outputs size:', hidden.shape) print(hidden)
直接使用RNN
cell = torch.nn.RNN(input_size=input_size,hidden_szie=hidden_size, num_layers=num_layers) ##num_layers代表RNN層數
out, hidden = cell(inputs, hidden) # inputs就是輸入序列,hn給到out,所有的h序列給到hidden
這裡輸入維度要求有序列長度,batch,input_size,而隱層維度則多了一個numplayers,因為要考慮網路的層數
而輸出的維度變成seqlen,batch和hidden_size,
程式碼如下
import torch
batch_size = 1
seq_len = 3
input_size = 4
hidden_size = 2
num_layers = 1
cell = torch.nn.RNN(input_size=input_size, hidden_size=hidden_size, num_layers=num_layers)
inputs = torch.randn(seq_len, batch_size, input_size)
hidden = torch.zeros(num_layers, batch_size, hidden_size)
out, hidden = cell(inputs, hidden)
print('output size:', out.shape)
print('output:', out)
print('Hidden size:', hidden.shape)
print('hidden:', hidden)
這裡就不同寫迴圈了
其他引數batch_first:如果設定為Ture,就代表要把序列長度和樣本數量維度進行交換
然後視訊又介紹瞭如何使用詞嵌入,寫法如下
import torch
input_size = 4
hidden_size = 8
batch_size = 1
seq_len = 5
embedding_size = 3
num_class = 4
num_layers = 2
idx2char = ['e', 'h', 'l', 'o']
x_data = [1, 0, 2, 2, 3]
y_data = [0, 0, 0, 0, 2]
inputs = torch.LongTensor(x_data).view(batch_size, seq_len)
labels = torch.LongTensor(y_data)
class Model(torch.nn.Module):
def __init__(self):
super(Model, self).__init__()
self.emb = torch.nn.Embedding(input_size, embedding_size)
self.rnn = torch.nn.RNN(input_size=embedding_size, hidden_size=hidden_size, num_layers=num_layers, batch_first=True)
self.fc = torch.nn.Linear(hidden_size, num_class)
def forward(self, x):
hidden = torch.zeros(num_layers, x.size(0), hidden_size)
x = self.emb(x)
x, _ = self.rnn(x, hidden)
x = self.fc(x)
return x.view(-1, num_class)
net = Model()
criterion = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(net.parameters(), lr=0.1)
for epoch in range(15):
optimizer.zero_grad()
outputs = net(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
_, idx = outputs.max(dim=1)
idx = idx.data.numpy()
print('predicted :',''.join([idx2char[x] for x in idx]), end='')
print(',EPOCH[%d/100] loss=%.4f'% (epoch+1, loss.item()))