【问题标题】:PyTorch: Trying to backward through the graph a second time, but the buffers have already been freed. Specify retain_graph=TruePyTorch:尝试第二次向后遍历图形,但缓冲区已被释放。指定retain_graph=True
【发布时间】:2020-10-06 06:39:58
【问题描述】:

这是我在处理一些合成数据时收到的错误消息。我有点困惑,因为尽管我按照建议去做,但错误仍然存​​在。这可能与我没有指定批次的事实有关吗?使用 PyTorch Dataset 会缓解这个问题吗?

这是我的代码(我是 PyTorch 的新手,现在才开始学习)——它应该是可重现的:

数据创建:

x, y = np.meshgrid(np.random.randn(100) , np.random.randn(100))    
z = 2 * x + 3 * y + 1.5 * x * y - x ** 2 - y**2
X = x.ravel().reshape(-1, 1)
Y = y.ravel().reshape(-1, 1)    
Z = z.ravel().reshape(-1, 1)    
U = np.concatenate([X, Y], axis = 1)    
U = torch.tensor(U, requires_grad=True)    
Z = torch.tensor(Z, requires_grad=True)    
V = []

for i in range(U.shape[0]):        
    u = U[i, :]  
    u1 = u.view(-1, 1) @ u.view(1, -1)    
    u1 = u1.triu()    
    ones = torch.ones_like(u1)    
    mask = ones.triu()    
    mask = (mask == 1)    
    u2 = torch.masked_select(u1, mask)    
    u3 = torch.cat([u, u2])    
    u3 = u3.view(1, -1)    
    V.append(u3)

V = torch.cat(V, dim = 0)

训练模型

from torch import nn    
from torch import optim    
net = nn.Sequential(nn.Linear(V.shape[1], 1))    
criterion = nn.MSELoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)

for epoch in range(50):  # loop over the dataset multiple times    
    running_loss = 0.0        
    i = 0
    for inputs , labels in zip(V, Z):
        # get the inputs; data is a list of [inputs, labels]

        # zero the parameter gradients
        optimizer.zero_grad()

        # forward + backward + optimize
        outputs = net(inputs)
        loss = criterion(outputs, labels)

        loss.backward(retain_graph = True)

        optimizer.step()

        # print statistics
        running_loss += loss.item()

        i += 1

        if i % 2000 == 1999:    # print every 2000 mini-batches
            print('[%d, %5d] loss: %.3f' %
                  (epoch + 1, i + 1, running_loss / 2000))
            running_loss = 0.0

print('Finished Training')

错误信息:

---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
<ipython-input-143-2454f4bb70a5> in <module>
     25 
     26 
---> 27         loss.backward(retain_graph = True)
     28 
     29         optimizer.step()

~\Anaconda3\envs\torch\lib\site-packages\torch\tensor.py in backward(self, gradient, retain_graph, create_graph)
    193                 products. Defaults to ``False``.
    194         """
--> 195         torch.autograd.backward(self, gradient, retain_graph, create_graph)
    196 
    197     def register_hook(self, hook):

~\Anaconda3\envs\torch\lib\site-packages\torch\autograd\__init__.py in backward(tensors, grad_tensors, retain_graph, create_graph, grad_variables)
     97     Variable._execution_engine.run_backward(
     98         tensors, grad_tensors, retain_graph, create_graph,
---> 99         allow_unreachable=True)  # allow_unreachable flag
    100 
    101 

RuntimeError: Trying to backward through the graph a second time, but the buffers have already been freed. Specify retain_graph=True when calling backward the first time.

您能解释一下错误并修复代码吗?

【问题讨论】:

    标签: python neural-network pytorch backpropagation


    【解决方案1】:

    大概是在设置retain_graph=True 之后,您没有再次重新运行数据创建代码,就像在 IPython REPL 中一样。它可以解决这个问题,但几乎在所有情况下,设置 retain_graph=True 都不是合适的解决方案。

    您的问题是,您已将requires_grad=True 设置为U,这意味着在数据创建中涉及U 的所有内容都将记录在计算图中以及何时调用loss.backward() ,梯度将通过所有这些传播到U。第一次之后,所有梯度的缓冲区都将被释放,第二次后退将失败。

    UZ 都不应该有 requires_grad=True,因为它们没有被优化/学习。只有学习到的参数(给优化器的参数)应该有requires_grad=True,而且通常你也不必手动设置它,因为nn.Parameter 会自动处理。

    您还应确保从 NumPy 数据创建的张量具有 torch.float (float32) 类型,因为 NumPy 的 float 数组通常是 float64,与 float32 相比,这大多是不必要的,而且速度较慢,尤其是在 GPU 上。

    U = torch.tensor(U, dtype=torch.float)
    
    Z = torch.tensor(Z, dtype=torch.float)
    

    并从反向调用中删除retain_graph=True

    loss.backward()
    

    【讨论】:

      猜你喜欢
      • 2020-07-15
      • 1970-01-01
      • 2018-06-24
      • 2021-03-11
      • 2021-11-18
      • 2020-11-07
      • 2021-11-19
      • 1970-01-01
      • 2023-02-26
      相关资源
      最近更新 更多