PyTorch基础入门七:PyTorch搭建循环神经网络(RNN)

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的一些扩展,是可以深入研究的,这将是一件非常有趣的事情。

猜你喜欢

转载自blog.csdn.net/out_of_memory_error/article/details/81456501