Rinne's Blog

Back

循环层#

在循环神经网络中,通过引入与上一个时刻相关的隐状态变量 Ht1H_{t-1} 来描述当前时刻之前的序列,从而实现了保存神经网络的历史信息。具体来说,当前时刻的隐状态是由输入与上一时刻的隐状态共同参与计算得出:

Ht=ϕ(XtWxh+Ht1Whh+bh)H_t = \phi (X_t W_{xh} + H_{t-1} W_{hh} + b_h)

对于该时刻的输出,可由当前时刻的隐状态计算得出:

Ot=HtWhq+bqO_t = H_t W_{hq} + b_q

基于循环计算的隐状态神经网络就叫循环神经网络 (Recurrent Neural Network) ,在循环神经网络中执行计算的层就叫循环层单循环层的RNN

困惑度#

我们可以通过一个序列中所有的 nn 个词元的交叉熵损失的平均值来衡量预测的好坏:

1nt=1nlogP(xtxt1,...,x1)\frac{1}{n} \sum_{t=1}^n -log P(x_t|x_{t-1}, ..., x_1)

在自然语言处理领域,通常使用困惑度这一概念来评估语言模型的好坏,其为上式的指数:

exp(1nt=1nlogP(xtxt1,...,x1))exp(- \frac{1}{n} \sum_{t=1}^n log P(x_t|x_{t-1}, ..., x_1))

简言之,困惑度的可理解为下一个词元的实际选择数的调和平均数

循环神经网络的实现#

基于pytorch的模型的定义:

class RNNModel(nn.Block):
    """循环神经网络模型"""
    def __init__(self, rnn_layer, vocab_size, **kwargs):
        super(RNNModel, self).__init__(**kwargs)
        self.rnn = rnn_layer
        self.vocab_size = vocab_size
        self.dense = nn.Dense(vocab_size)

    def forward(self, inputs, state):
        X = npx.one_hot(inputs.T, self.vocab_size)
        Y, state = self.rnn(X, state)
        # 全连接层首先将Y的形状改为(时间步数*批量大小,隐藏单元数)
        # 它的输出形状是(时间步数*批量大小,词表大小)
        output = self.dense(Y.reshape(-1, Y.shape[-1]))
        return output, state

    def begin_state(self, *args, **kwargs):
        return self.rnn.begin_state(*args, **kwargs)

num_hiddens = 256
rnn_layer = rnn.RNN(num_hiddens)
rnn_layer.initialize()

net = RNNModel(rnn_layer, len(vocab))
python

参考资料#

  1. 动手学深度学习
  2. 李飞飞·斯坦福CS231n计算机视觉课程
©
循环神经网络
https://astro-pure.js.org/blog/learning/deep-learning/rnn-intro
Author Rinne
Published at 2025年9月24日
Comment seems to stuck. Try to refresh?✨