pytorch如何计算导数_[Pytorch中文文档] 自动求导机制 - pytorch中文网

自动求导机制

本说明将概述Autograd如何工作并记录操作。没有必要全部了解,但建议您熟悉它,因为它将帮助您编写更高效,更清洁的程序,并可帮助您进行调试。

从后向中排除子图:

每个变量都有两个标志:requires_grad和volatile。它们都允许从梯度计算中细分排除子图,并可以提高效率。

requires_grad

如果一个变量定义requires_grad,那么他所有的操作也可以使用requires_grad,相反,只有所有输入都不需要梯度,才不会输出梯度。如果其中所有的变量都不需要梯度,在子图中从不执行向后计算。

x = Variable(torch.randn(5, 5))

y = Variable(torch.randn(5, 5))

z = Variable(torch.randn(5, 5), requires_grad=True)

a = x + y

a.requires_grad

# False

b = a + z

b.requires_grad

# True

当您想要冻结部分模型时,这个标志特别有用;除非您事先知道不会使用到某些参数的梯度。例如,如果要对预先训练的CNN进行优化,只要切换冻结模型中的requires_grad标志就足够了,直到计算到最后一层才会保存中间缓冲区,其中仿射的变换和网络的输出都需要使用梯度的权值

model = torchvision.models.resnet18(pretrained=True)

for param in model.parameters():

param.requires_grad = False

# Replace the last fully-connected layer

# Parameters of newly constructed modules have requires_grad=True by default

model.fc = nn.Linear(512, 100)

# Optimize only the classifier

optimizer = optim.SGD(model.fc.parameters(), lr=1e-2, momentum=0.9)

volatile

纯粹的inference模式下推荐使用volatile,当你你不调用.backward()的时候。它比其他所有的自动求导的设置更有效——它将使用绝对最小的内存来评估模型。volatile代表require_grad is False。

volatile不同于require_grad的传递。如果一个变量定义了volatile的操作,那么它的输出也将是volatile。Volatility比non-requiring gradient更容易传递——只需要定义一个volatile的输入即可输出volatile;同样,所以变量都不定义梯度才不会输出梯度。使用volatile标志着您不需要更改模型参数的任何设置,用于推理(inference)。创建一个volatile的输入就够了,这将确保不会保存中间状态。

regular_input = Variable(torch.randn(5, 5))

volatile_input = Variable(torch.randn(5, 5), volatile=True)

model = torchvision.models.resnet18(pretrained=True)

model(regular_input).requires_grad

# True

model(volatile_input).requires_grad

# False

model(volatile_input).volatile

# True

model(volatile_input).creator is None

# True

自动求导如何编码历史信息:

每个变量都有一个.creator属性,它指向把它作为输出的函数。这是一个由Function对象作为节点组成的有向无环图(DAG)的入口点,它们之间的引用就是图的边。每次执行一个操作时,一个表示它的新Function就被实例化,它的forward()方法被调用,并且它输出的Variable的创建者被设置为这个Function。然后,通过跟踪从任何变量到叶节点的路径,可以重建创建数据的操作序列,并自动计算梯度。

需要注意的一点是,整个图在每次迭代时都是从头开始重新创建的,这就允许使用任意的Python控制流语句,这样可以在每次迭代时改变图的整体形状和大小。在启动训练之前不必对所有可能的路径进行编码—— what you run is what you differentiate.

Variable上的In-place操作:

支持自动归档中的就地操作是一件很困难的事情,我们在大多数情况下都不鼓励使用它们。Autograd的积极缓冲区释放和重用使其非常高效,并且在现场操作实际上会降低内存使用量的情况下,极少数场合很少。除非您在内存压力很大的情况下运行,否则您可能永远不需要使用它们。

限制现场操作适用性的两个主要原因:

覆盖计算梯度所需的值。这就是为什么变量不支持log_。其梯度公式需要原始输入,而通过计算逆运算可以重新创建它,它在数值上是不稳定的,并且需要额外的工作,这往往会失败使用这些功能的目的。

每个in-place操作实际上需要实现重写计算图。不合适的版本只需分配新对象,并保留对旧图的引用,而in-place操作则需要将所有输入的creator更改为Function表示此操作。这就比较棘手,特别是如果有许多变量引用相同的存储(例如通过索引或转置创建的),并且如果被修改输入的存储被其他Variable引用,则in-place函数实际上会抛出错误。

In-place正确性检查:

每个变量保留有版本计数器version counter,当在任何操作中被使用时,它都会递增。当函数保存任何用于后向的tensor时,还会保存其包含变量的版本计数器version counter。一旦访问,self.saved_tensors它被会被检查,如果它大于保存的值,则会引起错误。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值