1、pytorch创建RNN模型和训练模型的代码
import torch
from torch import nn
from torch.autograd import Variable
#定义RNN模型
class RNN(nn.Module):
def __init__(self):
super(RNN, self).__init__()
self.rnn = nn.RNN(
input_size=1,
hidden_size=32,
num_layers=2,
batch_first=True,
)
self.linear = nn.Linear(32, 1)
def forward(self, x, h_n):
r_out, h_n = self.rnn(x, h_n)
outs = []
for step in range(r_out.size(1)):
outs.append(self.linear(r_out[:, step, :]))
return torch.stack(outs, dim=1), h_n
#创建模型
net = RNN()
#========以下是训练过程===========
#获取样本和标签(此处为numpy格式,shape=(batch_size, time_step, feature))
sample = ……
label = ……
#将样本和标签转化为Variable
x = Variable(torch.Tensor(sample).type(torch.FloatTensor))
y = Variable(torch.Tensor(label).type(torch.FloatTensor))
#优化器(举例)
optimizer = torch.optim.Adam(net.parameters(), lr=0.02)
#损失函数(举例)
loss_func = nn.MSELoss()
#初次传入RNN的隐藏层状态
h_n = None
#训练100轮
for i in range(100):
#将样本和隐藏层状态输入到模型中,得到模型输出值和更新后的隐藏层状态
prediction, h_n = net(x, h_n)
h_n = h_n.data
#计算损失值
loss = loss_func(prediction, y)
#输出损失值
print('round ' + str(i) + ' ' +str(loss))
optimizer.zero_grad()
loss.backward()
optimizer.step()
#每训练100轮保存1次模型
if (i+1)%100 == 0:
torch.save(net, 'net.pkl')
2、代码的分析:
__inti__:__init__方法定义了网络中的各个组成部分。以上代码定义了slef.rnn和self.linear两个部分,rnn是循环网络,linear是线性变换层。RNN参数介绍如下:
RNN的参数 | ||
参数 | 解释 | 默认值 |
input_size | 输入x的特征数量。 | |
hidden_size | 隐藏层状态h的特征数量。 | |
num_layers | 循环层(recurrent layers)数量。例子:参数值为2表示将两个RNN堆叠(stacking)在一起,第1个RNN的输出作为第2个RNN的输入,第2个RNN输出最终结果。 |
1 |
nonlinearity | 使用的非线性函数,'tanh'或是'relu'. | 'tanh' |
bias | 如果是False,那么RNN层就不会使用偏置权重 b_ih 和 b_hh。 | True |
batch_first | 如果True的,那么输入和输出的Tensor的shape为[batch_size, time_step, feature]。 | False |
dropout | 如果值非零,那么除了最后一层外,其它层的输出都引入Dropout层。 | 0 |
bidirectional | 如果True,代表这是一个双向RNN。 | False |
(参考自:https://pytorch.org/docs/stable/nn.html#recurrent-layers)
forward:forward方法定义了模型的输入输出和数据在模型中的流动方向。数据流动过程如下:
(1)模型输入参数【x】和【h_n】被输入到Rnn中,Rnn结果将返回2个Tensor:计算的结果【r_out】和新的隐藏层状态【h_n】
(2)for循环将Rnn的输出【r_out】按照step的顺序输入到Linear层中,每个step的Linear输出将追加到类型为tensor的列表【outs】中
(3)将【outs】(通过torch.stack方法)中的内容堆叠到一个Tensor中,与新的隐藏层状态【h_n】一起作为forward的返回值被返回。
简单来说,以上例子定义出来如下模型:
torch.nn.Rnn输入输出值格式说明:
因为在创建Rnn时,batch_first参数被设置为true,所以Forward方法中Rnn的输入值【x】和输出值【r_out】的shape为[batch_size, time_step, feature]。这两个Tensor的第1维是训练的批次batch,第2维是rnn的输入序列,第3维是每次输入Rnn或Rnn输出的特征向量。举个例子:
x = [ [ [1, 3, 5], [2, 4, 6], [9, 8, 3], [3, 0, 2], [7, 9 1] ], [ [4, 2, 8], [2, 1, 2], [8, 4, 2], [3, 5, 6], [1, 8 7] ] ]
故x = [ [……], [……] ]表示意味这这个batch有2个序列;[ [1, 3, 5], [2, 4, 6], [9, 8, 3], [3, 0, 2], [7, 9 1] ]表示一个序列有5次输入(x0、x1、x2、x3、x4、x5);[1, 3, 5]表示一次输入有3个值。因此,x.shape = (2, 5, 3),同理,r_out.shape = (2, 5, 3)。