Pytorch - RuntimeError:尝试第二次向后退,但缓冲区已被释放

Posted

技术标签:

【中文标题】Pytorch - RuntimeError:尝试第二次向后退,但缓冲区已被释放【英文标题】:Pytorch - RuntimeError: Trying to backward through the graph a second time, but the buffers have already been freed 【发布时间】:2018-06-24 18:55:46 【问题描述】:

我一直遇到这个错误:

RuntimeError: 试图第二次向后遍历图形,但缓冲区已被释放。第一次向后调用时指定retain_graph=True。

我在 Pytorch 论坛中搜索过,但仍然无法找出我在自定义损失函数中做错了什么。我的模型是 nn.GRU,这是我的自定义损失函数:

def _loss(outputs, session, items):  # `items` is a dict() contains embedding of all items
    def f(output, target):
        pos = torch.from_numpy(np.array([items[target["click"]]])).float()
        neg = torch.from_numpy(np.array([items[idx] for idx in target["suggest_list"] if idx != target["click"]])).float()
        if USE_CUDA:
            pos, neg = pos.cuda(), neg.cuda()
        pos, neg = Variable(pos), Variable(neg)

        pos = F.cosine_similarity(output, pos)
        if neg.size()[0] == 0:
            return torch.mean(F.logsigmoid(pos))
        neg = F.cosine_similarity(output.expand_as(neg), neg)

        return torch.mean(F.logsigmoid(pos - neg))

    loss = map(f, outputs, session)
return -torch.mean(torch.cat(loss))

培训代码:

    # zero the parameter gradients
    model.zero_grad()

    # forward + backward + optimize
    outputs, hidden = model(inputs, hidden)
    loss = _loss(outputs, session, items)
    acc_loss += loss.data[0]

    loss.backward()
    # Add parameters' gradients to their values, multiplied by learning rate
    for p in model.parameters():
        p.data.add_(-learning_rate, p.grad.data)

【问题讨论】:

【参考方案1】:

问题出在我的训练循环中:它没有在批次之间分离或重新打包隐藏状态?如果是这样,那么loss.backward() 正在尝试一直反向传播到时间的开始,这适用于第一批但不适用于第二批,因为第一批的图已被丢弃。

有两种可能的解决方案。

1) 在批次之间分离/重新打包隐藏状态。有(在 至少)三种方法来做到这一点(我选择了这个解决方案):

 hidden.detach_()
 hidden = hidden.detach()

2) 将 loss.backward() 替换为 loss.backward(retain_graph=True),但要知道每个连续批次将比前一个批次花费更多时间,因为它必须一直反向传播到第一批次的开始。

Example

【讨论】:

LSTMs 上的 PyTorch tutorial 暗示了以下几行 model.hidden = model.init_hidden() 您需要清除 LSTM 的隐藏状态,将其从最后一个实例的历史记录中分离出来。 变量现已弃用 (pytorch.org/docs/stable/autograd.html#variable-deprecated)。 关于方案一:为什么要分离两次? detach_() 是不是不需要 hidden = hidden.detach() 的就地操作? 是的。他一定是指其中一个。 pytorch-1x+方式实现示例链接为here

以上是关于Pytorch - RuntimeError:尝试第二次向后退,但缓冲区已被释放的主要内容,如果未能解决你的问题,请参考以下文章

Pytorch,`back` RuntimeError:尝试第二次向后遍历图形,但缓冲区已经被释放

RuntimeError:cuDNN 错误:CUDNN_STATUS_NOT_INITIALIZED 使用 pytorch

RuntimeError:梯度计算所需的变量之一已被就地操作修改:PyTorch 错误

Pytorch RNN 错误:RuntimeError:输入必须有 3 个维度得到 1

PyTorch - RuntimeError: [enforce fail at inline_container.cc:209]。找不到文件:存档/data.pkl

pytorch RuntimeError: 标量类型 Double 的预期对象,但得到标量类型 Float