Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ember.js/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Pytorch-为什么预分配内存会导致;第二次尝试在图表中倒转“;_Pytorch_Backpropagation_Tensor_Autograd_Autodiff - Fatal编程技术网

Pytorch-为什么预分配内存会导致;第二次尝试在图表中倒转“;

Pytorch-为什么预分配内存会导致;第二次尝试在图表中倒转“;,pytorch,backpropagation,tensor,autograd,autodiff,Pytorch,Backpropagation,Tensor,Autograd,Autodiff,假设我有一个简单的单隐层网络,我正在以典型的方式进行训练: for x,y in trainData: optimizer.zero_grad() out = self(x) loss = self.lossfn(out, y) loss.backward() optimizer.step() 这可以按预期工作,但如果我改为预分配并更新输出数组,则会出现错误: out = torch.empty_

假设我有一个简单的单隐层网络,我正在以典型的方式进行训练:

    for x,y in trainData:
        optimizer.zero_grad()
        out = self(x)
        loss = self.lossfn(out, y)
        loss.backward()
        optimizer.step() 
这可以按预期工作,但如果我改为预分配并更新输出数组,则会出现错误:

    out = torch.empty_like(trainData.tensors[1])
    for i,(x,y) in enumerate(trainData):
        optimizer.zero_grad()
        out[i] = self(x)
        loss = self.lossfn(out[i], y)
        loss.backward()
        optimizer.step()  
RuntimeError:第二次尝试向后遍历图形,但是 缓冲区已被释放。在以下情况下指定retain_graph=True 第一次向后呼叫


这里发生了什么,在第二个版本中,Pytorch再次尝试通过图形反向?为什么这在第一个版本中不是一个问题?(请注意,即使我没有
zero\u grad()
),也会发生此错误)

此错误表示程序正试图再次通过一组操作进行反向传播。第一次通过一组操作进行反向传播时,pytorch会删除计算图以释放内存。因此,第二次尝试反向传播时失败,因为图形已被删除

对此的详细解释

简短回答 使用
loss.backward(retain\u graph=True)
。这不会删除计算图

详细答案 在第一个版本中,在每个循环迭代中,每次运行
out=self(x)
时都会生成一个新的计算图

Every loop's graph
out = self(x) -> loss = self.lossfn(out, y)
在第二个版本中,由于
out
是在循环外声明的,因此每个循环中的计算图都有一个父节点在循环外

           - out[i] = self(x) -> loss = self.lossfn(out[i], y) 
out[i] - | - out[i] = self(x) -> loss = self.lossfn(out[i], y) 
           - out[i] = self(x) -> loss = self.lossfn(out[i], y)
因此,这里有一个发生的时间线

  • 第一次迭代运行
  • 将删除计算图,包括父节点
  • 第二次迭代尝试反向传播,但失败,因为它没有找到父节点