pytorch-autograde-计算图

定义requires_grad

如果所有输入有任意子单元有requires_grad,则输出单元则也相应为requires_grad。

import torch

x = torch.randn(5, 5)
y = torch.randn(5, 5)
z = torch.randn((5, 5), requires_grad=True)
a = x + z
print(a.requires_grad)

对应的,则不需要进行梯度更新的则进行freeze。

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)

pytorch autograd 工作模式

Autograd是自动微分系统的反向过程。在概念上,autograd记录了数据需要执行的所有算子,并将其根据顺序放置在一个有向无环图(DAG)上。
可以理解为叶子节点是输入的Tensor,根节点是输出的Tensor。根据tracing图的根到叶子,可以根据链式法则来求解梯度。

从原理来讲,autograd将计算图表示成一种由Function对象组成的图。在前向计算的时候,autograd同时执行算子op对应的计算,并且建立一个表示计算梯度的函数的图。当前向计算完成时,在反向回传过程中评估这个图,并计算梯度。
需要注意的是图结构在每次迭代的时候都重新创建(every iteration),这也正是在PyTorch中,允许用户使用任意的Python控制流语句的原因(for之类的)。可以在每次迭代中改变计算图的整体形状和大小,即所谓的动态图

in-place operations with autograd

in-place operation在pytorch中是指改变一个tensor的值的时候,不经过复制操作,而是直接在原来的内存上改变它的值。可以把它成为原地操作符。
在pytorch中经常加后缀“”来代表原地 in-place operation,比如说.add() 或者.scatter_()。python里面的+=,*=也是in-place operation。

import torch
x=torch.rand(2) #tensor([0.8284, 0.5539])
print(x)
y=torch.rand(2)
x.add_(y)
print(x)        #tensor([1.1610, 1.3789])

计算图

为了更精确地描述反向传播算法,使用更精确的 计算图(computational graph)语言是很有帮助的。将计算抽象为图形的方法有很多,这里,我们使用图中的每一个节点来表示一个变量(可以是标量、向量、矩阵、张量等各种形式)。
为了形式化我们的图形,我们还需引入 算子(operator)这一概念(PyTorch、Tensorflow等框架提供了成百上千种不同的算子,比如卷积、Pooling、GRU、LSTM、RNN等等等等)。算子(operator是指一个或多个变量的简单函数(也可能不那么“简单”)。我们的图形语言伴随着一组被允许的操作。我们可以通过将多个操作复合在一起来描述更为复杂的函数。
这里,假设每个算子只返回单个输出变量。目的是:避免引入对概念理解不重要的许多额外细节。

注意,如果一个变量y是由变量x经过一个**算子(operator)**得到的,那么在计算图中,会建立一条从x到y的有向边。

而每个节点的名称,在一般的框架中,是用op的名称表示(加上一些参数,比如conv的话,会加上kernel size, stride等参数
在这里插入图片描述
PyTorch为代表的动态图和以Tensorflow、Theano为代表的静态图的差别

  • Symbol2Symbol
    代数表达式和计算图都对符号(symbol) 或不具有特定值的变量进行操作。这些代数或者基于图的表达式被称为符号表示(symbolic representation)。
    这个部分很好理解,因为我们对网络的输入每个batch、每个样本的的内容都不一样,为了避免重复的计算(比如重复的求解梯度表达式),所以需要制定出每个算子(operator)的确定的计算逻辑。
    一些反向传播的方法采用计算图和一组用于图的输入的数值,然后返回在这些输入值处的梯度的数值。这种方法称为Symbol2Value——符号到数值的微分方法。也就是PyTorch以及其前身Torch和Caffe所采用的方法。另一种方法是采用计算图和为计算图添加额外的节点(用于计算算子梯度),这些额外的节点提供了我们所需的导数的符号描述,称为Symbol2Symbol。这就是Theano和Tensorflow使用的方法。ensorflow和Theano类似,额外节点提供了所需导数的符号描述。这种方法的主要优点是导数可以使用与原始表达式相同的语言来描述。因为导数只是另外一张计算图(添加到主计算图中),我们可以再次运行反向传播,对导数 再进行求导就能得到更高阶的导数
    基于Symbol2Symbol——符号到符号的方法的描述包含了Symbol2Value符号到数值的方法。符号到数值的方法可以理解为执行了与符号到符号的方法中构建图的过程中完全相同的计算。关键的区别:符号到数值的方法不会显示出计算图。
    下图是符号到符号的方法,即构建出导数的计算图,这里容易看出:
    在这里插入图片描述

在这里插入图片描述

  • Symbol2value
    • PyTorch是动态图

    • 动态图在每次iteration后都需要重建图本身

    • PyTorch的optimizer默认情况会自动对梯度进行accumulate[4],所以对下一次iteration(一个新的batch),需要对optimizer进行清空操作。PyTorch使用方式如下:

      optimizer.zero_grad()
      
              # forward + backward + optimize
              outputs = net(inputs)
              loss = criterion(outputs, labels)
              loss.backward()
              optimizer.step()
      
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值