在语言建模中,为啥我必须在每个新的训练时期之前初始化隐藏权重? (火炬)

Posted

技术标签:

【中文标题】在语言建模中,为啥我必须在每个新的训练时期之前初始化隐藏权重? (火炬)【英文标题】:In language modeling, why do I have to init_hidden weights before every new epoch of training? (pytorch)在语言建模中,为什么我必须在每个新的训练时期之前初始化隐藏权重? (火炬) 【发布时间】:2019-08-16 11:05:44 【问题描述】:

我对pytorch语言建模中的以下代码有疑问:

print("Training and generating...")
    for epoch in range(1, config.num_epochs + 1): 
        total_loss = 0.0
        model.train()  
        hidden = model.init_hidden(config.batch_size)  

        for ibatch, i in enumerate(range(0, train_len - 1, seq_len)):
            data, targets = get_batch(train_data, i, seq_len)          
            hidden = repackage_hidden(hidden)
            model.zero_grad()

            output, hidden = model(data, hidden)
            loss = criterion(output.view(-1, config.vocab_size), targets)
            loss.backward()  

请检查第 5 行。

而init_hidden函数如下:

def init_hidden(self, bsz):
    weight = next(self.parameters()).data
    if self.rnn_type == 'LSTM':  # lstm:(h0, c0)
        return (Variable(weight.new(self.n_layers, bsz, self.hi_dim).zero_()),
                Variable(weight.new(self.n_layers, bsz, self.hi_dim).zero_()))
    else:  # gru & rnn:h0
        return Variable(weight.new(self.n_layers, bsz, self.hi_dim).zero_())

我的问题是:

为什么我们需要在每个 epoch 都进行 init_hidden?不应该是模型继承了上个epoch的隐藏参数,继续训练。

【问题讨论】:

【参考方案1】:

答案在于 init_hidden。不是隐藏层权重,而是RNN/LSTM中的初始隐藏状态,在公式中为h0。对于每个 epoch,我们应该重新初始化一个新的初学者隐藏状态,这是因为在测试期间,我们的模型将没有关于测试语句的信息,并且初始隐藏状态为零。

【讨论】:

【参考方案2】:

隐藏状态存储 RNN 的内部状态,该状态来自对当前序列中先前标记的预测,这允许 RNN 理解上下文。隐藏状态由前一个令牌的输出决定。

当您预测任何序列的第一个标记时,如果您要保留前一个序列的隐藏状态,您的模型将表现得好像新序列是旧序列的延续,这会产生更差的结果。而不是为第一个令牌初始化一个空的隐藏状态,然后将其填充模型状态并用于第二个令牌。

这样想:如果有人让你对一个句子进行分类,然后给你美国宪法(不相关的信息),或者有人给你一些关于这个句子的背景背景,然后让你对这个句子进行分类。

【讨论】:

【参考方案3】:

将隐藏状态视为输出,在反向传播期间不会更新。 因此,对于每个新的时期,而不是每个新批次(每次迭代),我们都会重新初始化 hidden_​​state 向量,以便单独计算每个序列的 hidden_​​state 向量。

【讨论】:

以上是关于在语言建模中,为啥我必须在每个新的训练时期之前初始化隐藏权重? (火炬)的主要内容,如果未能解决你的问题,请参考以下文章

PyTorch:为啥在训练时期循环内部或外部调用验证准确性会发生变化?

Pytorch - 跳过计算每个时期的预训练模型的特征

TensorFlow进阶---变量的创建初始化

如何在训练期间在每个时期修改损失函数内的变量?

Keras 中的 TensorBoard 回调不尊重适合的初始时期?

为啥 NSObject 必须在其 .class-property 可读之前进行初始化