Pytorch:搭建RNN方法和过程分析

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] ] ]

  • [……]代表一个batch
  • [……]表示一个序列
  • [……]表示一个输入或输出

故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)。

你可能感兴趣的:(机器学习)