本章代码:https://github.com/zhangxiann/PyTorch_Practice/blob/master/lesson1/computational_graph.py

计算图

深度学习就是对张量进行一系列的操作,随着操作种类和数量的增多,会出现各种值得思考的问题。比如多个操作之间是否可以并行,如何协同底层的不同设备,如何避免冗余的操作,以实现最高效的计算效率,同时避免一些 bug。因此产生了计算图 (Computational Graph)。

计算图是用来描述运算的有向无环图,有两个主要元素:节点 (Node) 和边 (Edge)。节点表示数据,如向量、矩阵、张量。边表示运算,如加减乘除卷积等。

用计算图表示:$y=(x+w)*(w+1)$,如下所示:

可以看作, $y=a \times b$ ,其中 $a=x+w$,$b=w+1$。

计算图与梯度求导

这里求 $y$ 对 $w$ 的导数。根复合函数的求导法则,可以得到如下过程。

$\begin{aligned} \frac{\partial y}{\partial w} &=\frac{\partial y}{\partial a} \frac{\partial a}{\partial w}+\frac{\partial y}{\partial b} \frac{\partial b}{\partial w} \ &=b * 1+a * 1 \ &=b+a \ &=(w+1)+(x+w) \ &=2 * w+x+1 \ &=2 * 1+2+1=5\end{aligned}$

体现到计算图中,就是根节点 $y$ 到叶子节点 $w$ 有两条路径 y -> a -> wy ->b -> w。根节点依次对每条路径的孩子节点求导,一直到叶子节点w,最后把每条路径的导数相加即可。

代码如下:

import torch
w = torch.tensor([1.], requires_grad=True)
x = torch.tensor([2.], requires_grad=True)
# y=(x+w)*(w+1)
a = torch.add(w, x) # retain_grad()
b = torch.add(w, 1)
y = torch.mul(a, b)
# y 求导
y.backward()
# 打印 w 的梯度,就是 y 对 w 的导数
print(w.grad)

结果为tensor([5.])

我们回顾前面说过的 Tensor 中有一个属性is_leaf标记是否为叶子节点。

在上面的例子中,$x$ 和 $w$ 是叶子节点,其他所有节点都依赖于叶子节点。叶子节点的概念主要是为了节省内存,在计算图中的一轮反向传播结束之后,非叶子节点的梯度是会被释放的。

代码示例:

# 查看叶子结点
print("is_leaf:\n", w.is_leaf, x.is_leaf, a.is_leaf, b.is_leaf, y.is_leaf) # 查看梯度
print("gradient:\n", w.grad, x.grad, a.grad, b.grad, y.grad)

结果为:

is_leaf:
True True False False False
gradient:
tensor([5.]) tensor([2.]) None None None

非叶子节点的梯度为空,如果在反向传播结束之后仍然需要保留非叶子节点的梯度,可以对节点使用retain_grad()方法。

而 Tensor 中的 grad_fn 属性记录的是创建该张量时所用的方法 (函数)。而在反向传播求导梯度时需要用到该属性。

示例代码:

# 查看梯度
print("w.grad_fn = ", w.grad_fn)
print("x.grad_fn = ", x.grad_fn)
print("a.grad_fn = ", a.grad_fn)
print("b.grad_fn = ", b.grad_fn)
print("y.grad_fn = ", y.grad_fn)

结果为

w.grad_fn =  None
x.grad_fn = None
a.grad_fn = <AddBackward0 object at 0x000001D8DDD20588>
b.grad_fn = <AddBackward0 object at 0x000001D8DDD20588>
y.grad_fn = <MulBackward0 object at 0x000001D8DDD20588>

PyTorch 的动态图机制

PyTorch 采用的是动态图机制 (Dynamic Computational Graph),而 Tensorflow 采用的是静态图机制 (Static Computational Graph)。

动态图是运算和搭建同时进行,也就是可以先计算前面的节点的值,再根据这些值搭建后面的计算图。优点是灵活,易调节,易调试。PyTorch 里的很多写法跟其他 Python 库的代码的使用方法是完全一致的,没有任何额外的学习成本。

静态图是先搭建图,然后再输入数据进行运算。优点是高效,因为静态计算是通过先定义后运行的方式,之后再次运行的时候就不再需要重新构建计算图,所以速度会比动态图更快。但是不灵活。TensorFlow 每次运行的时候图都是一样的,是不能够改变的,所以不能直接使用 Python 的 while 循环语句,需要使用辅助函数 tf.while_loop 写成 TensorFlow 内部的形式。

参考资料

如果你觉得这篇文章对你有帮助,不妨点个赞,让我有更多动力写出好文章。

我的文章会首发在公众号上,欢迎扫码关注我的公众号张贤同学

[PyTorch 学习笔记] 1.4 计算图与动态图机制的更多相关文章

  1. [PyTorch 学习笔记] 2.2 图片预处理 transforms 模块机制

    PyTorch 的数据增强 我们在安装PyTorch时,还安装了torchvision,这是一个计算机视觉工具包.有 3 个主要的模块: torchvision.transforms: 里面包括常用的 ...

  2. [PyTorch 学习笔记] 1.1 PyTorch 简介与安装

    PyTorch 的诞生 2017 年 1 月,FAIR(Facebook AI Research)发布了 PyTorch.PyTorch 是在 Torch 基础上用 python 语言重新打造的一款深 ...

  3. WPF学习笔记-用Expression Design制作矢量图然后导出为XAML

    WPF学习笔记-用Expression Design制作矢量图然后导出为XAML 第一次用Windows live writer写东西,感觉不错,哈哈~~ 1.在白纸上完全凭感觉,想象来画图难度很大, ...

  4. Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第九章:贴图

    原文:Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第九章:贴图 代码工程地址: https://github.com/j ...

  5. 莫烦pytorch学习笔记(二)——variable

    .简介 torch.autograd.Variable是Autograd的核心类,它封装了Tensor,并整合了反向传播的相关实现 Variable和tensor的区别和联系 Variable是篮子, ...

  6. [PyTorch 学习笔记] 5.2 Hook 函数与 CAM 算法

    本章代码: https://github.com/zhangxiann/PyTorch_Practice/blob/master/lesson5/hook_fmap_vis.py https://gi ...

  7. Nodejs学习笔记(三)——一张图看懂Nodejs建站

    前言:一条线,竖着放,如果做不到精进至深,那就旋转90°,至少也图个幅度宽广. 通俗解释上面的胡言乱语:还没学会爬,就学起走了?! 继上篇<Nodejs学习笔记(二)——Eclipse中运行调试 ...

  8. Spring学习(二)—— java的动态代理机制

    在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,依赖注入就不用多说了,而对于Spring的核心AOP来说,我们不但要知道怎么通过AOP来满足的 ...

  9. PyTorch学习笔记之计算图

    1. **args, **kwargs的区别 def build_vocab(self, *args, **kwargs): counter = Counter() sources = [] for ...

随机推荐

  1. jQuery中常用网页效果应用

    一.常用网页效果应用 1.表单应用 表单由表单标签.表单域和表单按钮组成. 1.1单行文本框应用 例:获取和失去焦点改变样式 首先,在网页中创建一个表单,HTML代码如下 <form actio ...

  2. ASP.NET WebAPI2复杂请求跨域设置

    ASP.Net Core的跨域设置比较简单  官方都整合了 具体的参见微软官方文档: https://docs.microsoft.com/zh-cn/aspnet/core/security/cor ...

  3. The option-critic architecture

    Abstract 时间抽象是强化学习中扩大学习和规划的关键.虽然计划与时间扩展的行动是众所周知的,但从数据中自主地创建这样的抽象仍然具有挑战性.我们在option框架内解决这个问题[Sutton,Pr ...

  4. Laragon修改配置快速创建其他框架的项目

    配置方式 依葫芦画瓢,如添加thinkPHP: # Thinkphp Thinkphp 3.2=composer create-project topthink/thinkphp %s Thinkph ...

  5. socket网络

    Socket 是进程间通信的一种方式,它与其他进程间通信的一个主要不同是:它能实现不同主机间的进程间通信,我们网络上各种各样的服务大多都是基于 Socket 来完成通信的,例如我们每天浏览网页.QQ ...

  6. Bug--Tomcat Error start child

    添加Quartz之后报错 下面的Cause by: More than one fragment with the name [spring_web] was found. This is not l ...

  7. JDK动态代理和 CGLIB 代理

    JDK动态代理和 CGLIB 代理 JDK动态代理:其代理对象必须是某个接口的实现,它是通过在运行期期间创建一个接口的实现类来完成对目标对象的代理. 代码示例 接口 public interface ...

  8. PHP password_verify() 函数

    password_verify() 函数用于验证密码是否和散列值匹配. PHP 版本要求: PHP 5 >= 5.5.0, PHP 7高佣联盟 www.cgewang.com 语法 bool p ...

  9. PHP preg_replace() 函数

    preg_replace 函数执行一个正则表达式的搜索和替换.高佣联盟 www.cgewang.com 语法 mixed preg_replace ( mixed $pattern , mixed $ ...

  10. 51nod 1584 加权约数和 约数和函数小trick 莫比乌斯反演

    LINK:加权约数和 我曾经一度认为莫比乌斯反演都是板子题. 做过这道题我认输了 不是什么东西都是板子. 一个trick 设\(s(x)\)为x的约数和函数. 有 \(s(i\cdot j)=\sum ...