当前位置: 首页 > 面试题库 >

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

殳凯捷
2023-03-14
问题内容

我一直遇到这个错误:

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_html" target="_blank">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)

问题答案:

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

有两种可能的解决方案。

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

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

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



 类似资料:
  • 环形缓冲区接口 结构体 struct   rt_ringbuffer   环形缓冲区控制块 更多...   枚举 函数 void  rt_ringbuffer_init (struct rt_ringbuffer *rb, rt_uint8_t *pool, rt_int16_t size)   初始化环形缓冲区   void  rt_ringbuffer_reset (struct rt_rin

  • 我正试图驱逐我的持久性实体管理器中的二级缓存。看起来我可以使用javax.persistence.Cache接口中定义的以下函数: 为了得到Cache对象,我可以使用javax.persistence.EntityManagerFactory接口中定义的以下函数: 我连接我的EntityManagerFactory是这样的: 使用以下applicationContext配置文件: 当我对对象调用g

  • 环形块状缓冲区接口 结构体 struct   rt_rbb_blk   rbb 中的块 更多...   struct   rt_rbb_blk_queue   块队列。这些块在队列中,其 buffer 地址是连续的 更多...   struct   rt_rbb   环形块状缓冲区,简称 rbb 更多...   枚举 函数 void  rt_rbb_init (rt_rbb_t rbb, rt_u

  • 问题内容: 我有一个流时间序列,我有兴趣保留最后4个元素,这意味着我希望能够弹出第一个元素并将其添加到末尾。本质上我需要一个环形缓冲区。 哪个Java集合最适合此用途?向量? 问题答案: 考虑CircularFifoBuffer Apache的Common.Collections。与Queue不同,你不必维护基础集合的有限大小,只要达到极限就可以包装它。 由于以下属性,CircularFifoBu

  • 环形缓冲区在处理异步IO时非常实用。它们可以在一端接收随机长度和区间的数据,在另一端以相同长度和区间提供密致的数据块。它们是Queue数据结构的变体,但是它针对于字节块而不是一系列指针。这个练习中我打算向你展示RingBuffer的代码,并且之后你需要对它执行完整的单元测试。 #ifndef _lcthw_RingBuffer_h #define _lcthw_RingBuffer_h #inc

  • 本文向大家介绍浏览和冲浪之间的区别,包括了浏览和冲浪之间的区别的使用技巧和注意事项,需要的朋友参考一下 浏览 浏览是指没有任何事先目的或目标的网站访问。用户通常浏览互联网时,会注意到他/她需要的信息。 冲浪 冲浪是指使用搜索引擎搜索特定信息。冲浪通常比浏览耗时,因为用户倾向于在Web上搜索和定位所需的信息。 以下是浏览和冲浪之间的重要区别。 序号 键 浏览 冲浪 1 使用完成 使用网络浏览器进行浏