PyTorch学习笔记之自动求导(AutoGrad)

 

1、使用PyTorch 计算梯度数值

         PyTorch 的 Autograd 模块实现了深度学习的算法中的反向传播求导数,在张量(Tensor类)上的所有操作, Autograd 都能为他们自动提供微分,简化了手动计算导数的复杂过程。

在04以前的版本中, Pytorch 使用 Variabe 类来自动计算所有的梯度 Variable 类主要包含三个属性 Variable 所包含的 Tensor;grad:保存 data 对应的梯度,grad 也是个 Variable,而不是 Tensor,它和 data 的形状一样;grad_fn:指向一个 Function 对象,这个 Function 用来反向传播计算输入的梯度;

从 0.4 起, Variable 正式合并入 Tensor 类,通过 Variable 嵌套实现的自动微分功能已经整合进入了 Tensor 类中。虽然为了的兼容性还是可以使用 Variable(tensor)这种方式进行嵌套,但是这个操作其实什么都没做。

以后的代码建议直接使用 Tensor 类进行操作,因为官方文档中已经将 Variable 设置成过期模块。

想通过 Tensor 类本身就支持了使用 autograd 功能,只需要设置 reques_grad=True;

Variable 类中的的 grad 和 grad_fn 属性已经整合进入了 Tensor 类中。

 

2Autograd

  • 在张量创建时,通过设置 requires_grad 标识为 True 来告诉 PyTorch 需要对该张量进行自动求导, PyTorch 会记录该张量的每一步操作历史并自动计算 。

 

  • PyTorch 会自动追踪和记录对与张量的所有操作,当计算完成后调用 .backward() 方法自动计算梯度并且将计算结果保存到 grad 属性中。

 

在张量进行操作后,grad_fn 已经被赋予了一个新的函数,这个函数引用了一个创建了这个 Tensor 类的 Function 对象。 Tensor 和 Function 互相连接生成了一个非循环图,它记录并且编码了完整的计算历史。每个张量都有个 grad 血属性,如果这个张量是用户手动创建的那么这个张量的 grad 是 None 下面我们来调用反向传播函数,计算其梯度。

 

3、简单自动求

       如果 Tensor 类表示的是一个标量(即它包含一个元素的张量),则不需要为 backwad()(指定任何参数,但是如果它有更多的元素,则需要指定一个 gradient 参数,它是形状匹配的张量。以上的 z.backward() 相当于是 z.backward(torch. Tensor(1.)) 的简写。这种参数常出现在图像分类中的单标签分类,输出一个标量代表图像的标签。

 

4、复杂的自动求导

 

  • 我们的返回值不是一个标量,所以需要输入一个大小相同的张量作为参数,这里我们用 ones_like 函数根据 x 生成一个张量;

 

  • 我们可以使用 with torch.no_grad() 上下文管理器临时禁止对已设置 requires_grad = True 的张量进行自动求导。这个方法在测试集计算准确率的时候会经常用到,例如:

 

 使用.no_grad() 进行嵌套后,代码不会跟踪历史记录,也就是说保存这部分记录会减少内存的使用量并且会加快少许的运算速度。

5 Autograd 过程解析

      为了说明 Torch 的自动求导原理,我们来尝试分析一下 PyTorch 的源代码,虽然 Pytorch 的 Tensor和 TensorBase 都是使用 CPP 来实现的,但是可以使用一些 Python 的一些方法查看这些对象在 Python 的属性和状态。 Python 的 dir 返回参数的属性、方法列表。z 是一个 Tensor 变量,看看里面有哪些成员变量。

 

返回很多,我们直接排除掉一些 Python 中特殊方法(以开兴和结束的)和私有方法(以开头的,直接看几个比较主的属性:.is_leaf: 记录是否是叶子节点。通过这个属性来确定这个变量的类型在官方文档中所说的" graphleaves"," leaf variables",都是指像 x,y 这样的手动创建的、而非运算得到的变量,这些变量成为创建变量。像 z 这样的,是通过计算后得到的结果称为结果变量。

一个变量是创建变量还是结果变量是通过 .is_leaf() 来获取的。

 

 x 是手动创建的没有通过计算,所以他被认为是一个叶子节点也就是一个创建变量,而 z 是通过x 与 y 的一系列计算得到的,所以不是叶子结点也就是结果变量为什么我们执行 z. backward(方法会更新 x.grad 和 y.grad 呢?. grad_fn 属性记录的就是这部分的操作,虽然 backward()方法也是CPP 实现的,但是可以通过 Python 来进行简单的探索。

grad_fn: 记录并且编码了完整的计算历史

 

grad_fn 是一个 AddBackward0 这个类也是用 cpp 来写的,但是我们从名字里就能够大概知道,他是加法 (ADD) 的反向传播。

 

next_functions 就是 grad_fn 的精华

 

next_functions 是一个 tuple of tuple of PowBackwardo and int

为什么是 2 个 tuple ?因为我们的操作是 z = x**2+y**3刚才的 addBackward() 是相加,而前面的操作是乘方PowBackward()。 tuple第一个元素就是 x 相关的操作记录

 

当我们执行 z.backward 的时候。这个操作将调用 z 里面的 grad_fn 这个属性,执行求导的操作。

这个操作将遍历 grad_fn 的 next_functions,然后分别取出里面的 Function(Accumulategrad),执行求导操作。这部分是一个递归的过程直到最后美型为叶子节点。

计算出结果以后,将结果保存到他们对应的 Variable 这个变量所引用的对象 ( x 和 y)的gad这个属性里面。

求导结束。所有的叶节点的 grad 变量都得到了相应的更新最终当我们执行完 c.backward()之后,a 和 b 里面的 grad 值就得到了更新。

 

在 PyTorch 的反向图计算中, Accumulategrad 类型代表的就是叶子节点类型,也就是计算图终止节点。

Accumulategrad 类中有一个 . variable 属性指向叶子节点。

 

这个 . variable 的属性就是我们的生成的变量 x

 

6、扩展 Autograd

      如果需要目定义 autograd扩展新的功能,就需要扩展 Function类。因为 Function使用 autograd来计算结果和梯度,并对操作历史进行编码。在 Function类中最主要的方法就是 forward0和 backward他们分别代表了前向专播和反向传。

一个自定义的 Function 需要以下三个方法:

__init__( optional):如果这个操作需要额外的参数则需要定义这个 Function 的构造函数,不需要的话可以忽略。

forward():执行前向传播的计算代码

backward():反向传播时梯度计算的代码。参数的个数和 forward 返回值的个数一样,每个参数代表传回到此操作的梯度。

 

 

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值