• 传统RNN的内部结构图:

    5.4 构建RNN模型 - 图1


    • 结构解释图:

    5.4 构建RNN模型 - 图2


    • 内部结构分析: * 我们把目光集中在中间的方块部分, 它的输入有两部分, 分别是h(t-1)以及x(t), 代表上一时间步的隐层输出, 以及此时间步的输入, 它们进入RNN结构体后, 会”融合”到一起, 这种融合我们根据结构解释可知, 是将二者进行拼接, 形成新的张量[x(t), h(t-1)], 之后这个新的张量将通过一个全连接层(线性层), 该层>使用tanh作为激活函数, 最终得到该时间步的输出h(t), 它将作为下一个时间步的>输入和x(t+1)一起进入结构体. 以此类推.

    • 内部结构过程演示:

    5.4 构建RNN模型 - 图3


    • 根据结构分析得出内部计算公式:

    5.4 构建RNN模型 - 图4


    • 激活函数tanh的作用: * 用于帮助调节流经网络的值, tanh函数将值压缩在-1和1之间.

    5.4 构建RNN模型 - 图5


    • 构建RNN模型的代码分析:
      1. class RNN(nn.Module):
      2. def __init__(self, input_size, hidden_size, output_size):
      3. """初始化函数中有三个参数,分别是输入张量最后一维的尺寸大小,
      4. 隐层张量最后一维的尺寸大小, 输出张量最后一维的尺寸大小"""
      5. super(RNN, self).__init__()
      6. # 传入隐含层尺寸大小
      7. self.hidden_size = hidden_size
      8. # 构建从输入到隐含层的线性变化, 这个线性层的输入尺寸是input_size + hidden_size
      9. # 这是因为在循环网络中, 每次输入都有两部分组成,分别是此时刻的输入和上一时刻产生的输出.
      10. # 这个线性层的输出尺寸是hidden_size
      11. self.i2h = nn.Linear(input_size + hidden_size, hidden_size)
      12. # 构建从输入到输出层的线性变化, 这个线性层的输入尺寸还是input_size + hidden_size
      13. # 这个线性层的输出尺寸是output_size.
      14. self.i2o = nn.Linear(input_size + hidden_size, output_size)
      15. # 最后需要对输出做softmax处理, 获得结果.
      16. self.softmax = nn.LogSoftmax(dim=-1)
      17. def forward(self, input, hidden):
      18. """在forward函数中, 参数分别是规定尺寸的输入张量, 以及规定尺寸的初始化隐层张量"""
      19. # 首先使用torch.cat将input与hidden进行张量拼接
      20. combined = torch.cat((input, hidden), 1)
      21. # 通过输入层到隐层变换获得hidden张量
      22. hidden = self.i2h(combined)
      23. # 通过输入到输出层变换获得output张量
      24. output = self.i2o(combined)
      25. # 对输出进行softmax处理
      26. output = self.softmax(output)
      27. # 返回输出张量和最后的隐层结果
      28. return output, hidden
      29. def initHidden(self):
      30. """隐层初始化函数"""
      31. # 将隐层初始化成为一个1xhidden_size的全0张量
      32. return torch.zeros(1, self.hidden_size)

    • torch.cat演示:
    1. >>> x = torch.randn(2, 3)
    2. >>> x
    3. tensor([[ 0.6580, -1.0969, -0.4614],
    4. [-0.1034, -0.5790, 0.1497]])
    5. >>> torch.cat((x, x, x), 0)
    6. tensor([[ 0.6580, -1.0969, -0.4614],
    7. [-0.1034, -0.5790, 0.1497],
    8. [ 0.6580, -1.0969, -0.4614],
    9. [-0.1034, -0.5790, 0.1497],
    10. [ 0.6580, -1.0969, -0.4614],
    11. [-0.1034, -0.5790, 0.1497]])
    12. >>> torch.cat((x, x, x), 1)
    13. ensor([[ 0.6580, -1.0969, -0.4614, 0.6580, -1.0969, -0.4614, 0.6580,-1.0969, -0.4614],
    14. [-0.1034, -0.5790, 0.1497, -0.1034, -0.5790, 0.1497, -0.1034,-0.5790, 0.1497]])

    • 代码位置: /data/doctor_offline/review_model/RNN_MODEL.py

    • 实例化参数:
      input_size = 768
      hidden_size = 128
      n_categories = 2
      

    • 输入参数:
      input = torch.rand(1, input_size)
      hidden = torch.rand(1, hidden_size)
      

    • 调用:

      from RNN_MODEL import RNN
      rnn = RNN(input_size, hidden_size, n_categories)
      outputs, hidden = rnn(input, hidden)
      print("outputs:", outputs)
      print("hidden:", hidden)
      
    • 输出效果:

      outputs: tensor([[-0.7858, -0.6084]], grad_fn=<LogSoftmaxBackward>)
      hidden: tensor([[-4.8444e-01, -5.9609e-02,  1.7870e-01, 
                     -1.6553e-01,  ... , 5.6711e-01]], grad_fn=<AddmmBackward>))
      

    • 小节总结:
      • 学习了RNN模型的内部结构及计算公式.
      • 学习并实现了RNN模型的类: class RNN(nn.Module).