PyTorch基礎入門七:PyTorch搭建迴圈神經網路(RNN)
阿新 • • 發佈:2019-01-30
1)任務介紹
今天,我們通過PyTorch搭建一個用於處理序列的RNN。
當我們以sin值作為輸入,其對應的cos作為輸出的時候,你會發現,即使輸入值sin相同,其輸出結果也可以是不同的,這樣的話,以前學過的FC, CNN就難以處理,因為你的輸出結果不僅僅依賴於輸出,而且還依賴於之前的程式結果。所以說,RNN在這裡就派上了用場。
2)程式碼實現
上程式碼之前,還是先了解一下RNN的引數吧:
torch.nn.RNN()
引數 | 含義 |
input_size | 輸入 x 的特徵數量 |
hidden_size | 隱狀態 h 中的特徵數量 |
num_layers | RNN 的層數 |
nonlinearity | 指定非線性函式使用 [‘tanh’|’relu’]. 預設: ‘tanh’ |
bias | 如果是 False , 那麼 RNN 層就不會使用偏置權重 b_ih 和 b_hh, 預設: True |
batch_first | 如果 True, 那麼輸入 Tensor 的 shape 應該是 (batch, seq, feature),並且輸出也是一樣 |
dropout | 如果值非零, 那麼除了最後一層外, 其它層的輸出都會套上一個 dropout 層 |
bidirectional | 如果 True , 將會變成一個雙向 RNN, 預設為 False |
首先,我們定義出RNN模型
import torch from torch import nn class Rnn(nn.Module): def __init__(self, INPUT_SIZE): super(Rnn, self).__init__() self.rnn = nn.RNN( input_size=INPUT_SIZE, hidden_size=32, num_layers=1, batch_first=True ) self.out = nn.Linear(32, 1) def forward(self, x, h_state): r_out, h_state = self.rnn(x, h_state) outs = [] for time in range(r_out.size(1)): outs.append(self.out(r_out[:, time, :])) return torch.stack(outs, dim=1), h_state
選擇模型進行訓練:
import numpy as np
import matplotlib.pyplot as plt
import torch
from torch import nn
import rnn
# 定義一些超引數
TIME_STEP = 10
INPUT_SIZE = 1
LR = 0.02
# # 創造一些資料
# steps = np.linspace(0, np.pi*2, 100, dtype=np.float)
# x_np = np.sin(steps)
# y_np = np.cos(steps)
# #
# # “看”資料
# plt.plot(steps, y_np, 'r-', label='target(cos)')
# plt.plot(steps, x_np, 'b-', label='input(sin)')
# plt.legend(loc='best')
# plt.show()
# 選擇模型
model = rnn.Rnn(INPUT_SIZE)
print(model)
# 定義優化器和損失函式
loss_func = nn.MSELoss()
optimizer = torch.optim.Adam(model.parameters(), lr=LR)
h_state = None # 第一次的時候,暫存為0
for step in range(300):
start, end = step * np.pi, (step+1)*np.pi
steps = np.linspace(start, end, TIME_STEP, dtype=np.float32)
x_np = np.sin(steps)
y_np = np.cos(steps)
x = torch.from_numpy(x_np[np.newaxis, :, np.newaxis])
y = torch.from_numpy(y_np[np.newaxis, :, np.newaxis])
prediction, h_state = model(x, h_state)
h_state = h_state.data
loss = loss_func(prediction, y)
optimizer.zero_grad()
loss.backward()
optimizer.step()
然後,畫圖看看最後擬合的結果
plt.plot(steps, y_np.flatten(), 'r-')
plt.plot(steps, prediction.data.numpy().flatten(), 'b-')
plt.show()
其擬合效果如下圖:
可以看到,真實的結果和擬合的效果已經十分接近了。
3)結語
神經網路學到RNN的時候,才慢慢感覺到神經網路的真正強大之處。因為RNN引入了”時間“這個特徵,我們的訓練結果不再受限於輸入,而是取決於”隨著時間的輸入序列“。正是由於這樣的原因,它可以廣泛的應用到自然語言處理,語言識別,甚至是AI作曲中來。
RNN確實相比於其他的神經網路顯得更為複雜和抽象,但是學到這裡的時候是非常興奮的,今天的博文只是借鑑了別人的程式碼,簡單地展示了一些RNN在處理序列上的優勢,關於RNN的一些擴充套件,是可以深入研究的,這將是一件非常有趣的事情。