当您有多个网络输出时,这是一项非常有用的功能。这是一个完整的示例:假设您要构建一个随机卷积网络,可以提出以下两个问题:输入图像是否包含猫,图像是否包含汽车?
一种实现方法是让网络共享卷积层,但随后具有两个并行分类层(原谅我糟糕的ASCII图,但这应该是三个卷积层,然后是三个完全连接的层,其中一层用于猫还有一个用于汽车):
-- FC - FC - FC - cat?
Conv - Conv - Conv -|
-- FC - FC - FC - car?
给定一张我们想要在两个分支上都运行的图片,在训练网络时,我们可以通过几种方式来实现。首先(这可能是最好的事情,说明示例有多糟糕),我们仅在两个评估中计算损失并求和,然后反向传播。
但是,还有另一种情况-我们想要按顺序执行此操作。首先,我们要通过一个分支进行反向传播,然后再通过另一个分支进行反向传播(我之前有这个用例,因此它并没有完全组成)。在那种情况下,在一个图上运行.backward()
也会破坏卷积层中的任何梯度信息,并且第二个分支的卷积计算(因为这些是与另一个分支共享的唯一卷积计算)将不再包含图!这意味着,当我们尝试向后分支第二个分支时,Pytorch将抛出错误,因为它找不到将输入连接到输出的图形!在这些情况下,我们可以通过简单地将图形保留在第一个向后传递上来解决问题。该图将不被使用,而仅由不需要保留它的第一个向后传递使用。
编辑:如果在所有向后传递中都保留该图,则附加到输出变量的隐式图定义将永远不会被释放。这里也可能有一个用例,但是我想不到。因此,通常,您应确保不保留图形信息,以确保最后一次向后传递可释放内存。
至于多次向后传递所发生的情况:如您所料,pytorch通过就地添加梯度(将其添加到变量的/ parameters .grad
属性中)来累积梯度。这可能非常有用,因为这意味着循环遍历一个批处理并一次处理一次,最后累积渐变,将执行与进行完整批处理更新相同的优化步骤(该步骤只会将所有渐变汇总为好)。尽管完全批处理的更新可以更多地并行化,因此通常是更可取的,但是在某些情况下,批处理计算要么非常,非常难以实现,要么根本不可能。但是,使用这种累积量,我们仍然可以依靠批处理带来的一些稳定特性。 (如果不提高性能)
0
我正在阅读神经传递pytorch教程 ,并对
retain_variable
的使用感到困惑(不推荐使用,现在称为retain_graph
)。代码示例显示:从文档中
因此,通过设置
retain_graph= True
,我们不会在向后传递时释放为该图分配的内存。保留此内存的好处是什么,为什么我们需要它?