RNN(Recurrent Neural Network)是一类用于处理序列数据的神经网络,最常见的是时间序列、文字序列。
基础神经网络(常规CNN)与RNN
我们从基础的神经网络中知道,神经网络包含输入层、隐层、输出层,通过激活函数控制输出,层与层之间通过权值连接。激活函数是事先确定好的,那么神经网络模型通过训练“学“到的东西就蕴含在“权值“中。
基础的神经网络只在层与层之间建立了权值(U,V)连接,如下图所示:
RNN最大的不同之处就是在神经元之间也建立的权值(U,V,W)连接。如图:
图中x代表输入,h代表隐藏层,o代表输出,y代表样本给出的确定值,L代表损失函数,U,V,W代表权值。
RNN的结构变体
RNN的训练方法——BPTT
BPTT(back-propagation through time)算法是常用的训练RNN的方法,其实本质还是BP算法,只不过RNN处理时间序列数据,所以要基于时间反向传播,故叫随时间反向传播。BPTT的中心思想和BP算法相同,沿着需要优化的参数的负梯度方向不断寻找更优的点直至收敛。
公式推导请参考:https://blog.csdn.net/zhaojc1995/article/details/80572098
参考:【1】https://blog.csdn.net/zhaojc1995/article/details/80572098
【3】https://baijiahao.baidu.com/s?id=1622177190450583829&wfr=spider&for=pc
RNN实验
pytorch中的RNN,torch.nn.RNN():
参数 | 含义 | 注意 |
input_size | 输入 x 的特征维度数量 | 是特征维度,不是序列长度 |
hidden_size | 隐状态 h 中的特征数量 | hidden层节点数目 |
num_layers | RNN层数 | hidden层数目,决定网络深度,不是宽度 |
nonlinearity | 指定非线性函数使用 [‘tanh’|’relu’]. 默认: ‘tanh’ | |
bias | 如果是 False , 那么 RNN 层就不会使用偏置权重 b_ih 和 b_hh, 默认: True | |
batch_first | 如果 True, 输入 Tensor 的 shape 为 (batch, seq, feature),输出一样 | 默认是False, 输入Tensor的shape 为 (seq, batch, feature),输出一样 |
dropout | 如果值非零, 那么除了最后一层外, 其它层的输出都会套上一个 dropout 层 | |
bidirectional | 如果 True , 将会变成一个双向 RNN, 默认为 False |
实验演示代码
正弦预测余弦
import torch from torch import nn import numpy as np 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=2, 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 # 定义一些超参 TIME_STEP = 10 INPUT_SIZE = 2 LR = 0.02 # “看”数据 # 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(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(torch.cat((x,x), 2), h_state) h_state = h_state.data loss = loss_func(prediction, y) optimizer.zero_grad() loss.backward() optimizer.step() print("x:") print(x) print("y:") print(y) print("predict:") print(prediction)