自动求导机制

    1. 从后向中排除子图
    2. 自动求导如何编码历史信息
    3. In-place正确性检查

    每个变量都有一个标记:允许从梯度计算中细分排除子图,并可以提高效率。

    requires_grad

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

    例如,如果您想调整预训练的CNN,只要切换冻结模型中的requires_grad标志即可,直到计算到最后一层才会保存中间缓冲区,仿射变换和网络输出都需要使用梯度的权值。

    1. model = torchvision.models.resnet18(pretrained=True)
    2. for param in model.parameters():
    3. param.requires_grad = False
    4. model.fc = nn.Linear(512, 100)
    5. # Optimize only the classifier
    6. optimizer = optim.SGD(model.fc.parameters(), lr=1e-2, momentum=0.9)

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

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

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

    1. 覆盖计算梯度所需的值。这就是为什么变量不支持log_。其梯度公式需要原始输入,而通过计算逆运算可以重新创建它,它在数值上是不稳定的,并且需要额外的工作,这往往会失败使用这些功能的目的。
    2. 每个in-place操作实际上需要实现重写计算图。不合适的版本只需分配新对象,并保留对旧图的引用,而in-place操作则需要将所有输入的creator更改为Function表示此操作。这就比较棘手,特别是如果有许多变量引用相同的存储(例如通过索引或转置创建的),并且如果被修改输入的存储被其他Variable引用,则in-place函数实际上会抛出错误。