基于TorchViz详解计算图(附代码)

简介: 基于TorchViz详解计算图(附代码)

0. 前言

按照国际惯例,首先声明:本文只是我自己学习的理解,虽然参考了他人的宝贵见解,但是内容可能存在不准确的地方。如果发现文中错误,希望批评指正,共同进步。

本文的主旨是基于TorchViz模块详细说明计算图以及叶子节点等相关概念。


创作本文的目的主要有两个:


  1. 计算图这个概念在深度学习中经常被提及,但是对于新手(甚至部分老手)而言,可能很少人能明白计算图究竟是个什么东西,用来干嘛的;


  1. CSDN上关于计算图的介绍文章不少,但基本都是引用TorchViz生成计算图后就完事了,缺乏对计算图的理解。


1. 计算图是什么?

答:计算图是用于表示计算过程的图,例如下面这个:

这个图可以理解为最简单的单层神经元网络,其中:x为训练输入数据,w和b 是要优化的参数,y 为训练输出数据,loss为损失值。


PyTorch官方对计算图(Computational Graph)的介绍是:一个有向开环图(DAG),这个有向开环图记录了①所有的输入数据(张量),②这些数据(张量)的计算过程,③通过这些计算过程生成的新数据(张量)。


在计算图中,“叶子”代表了输入数据(张量),“根”代表了输出数据(张量)。追溯从“根”到“叶子”的过程,通过链式法则可以计算出(损失值对神经元网络模型参数的)偏导。


PyTorch官网原文链接:https://pytorch.org/tutorials/beginner/blitz/autograd_tutorial.html?highlight=grad_fn


2. TorchViz的安装

TorchViz是一个用于可视化 PyTorch计算图的工具库,后面的说明都是使用TorchViz生成的计算图来讲解,所以先介绍下TorchViz的安装。


其方法非常简单。。。使用Conda直接安装TorchViz:首先进入到Pycharm/settings/Python Interpreter,然后点“+”。



再搜torchviz,点“Install Package”



因为TorchViz中引用了GraphViz库中的方法,所以也得把GraphViz安装上。



其实不太想水这一章的内容,但是我实在不理解为什么大家都千篇一律喜欢用pip?

3. 计算图详解

首先我们先生成一个最简单的 h = w × x + b h = w×x + b h=w×x+b的计算图,代码如下:

import torch
from torchviz import make_dot


x = torch.tensor([1],dtype=torch.float32,requires_grad=True)
w = torch.tensor([4],dtype=torch.float32,requires_grad=True)
b = torch.tensor([0.5],dtype=torch.float32,requires_grad=True)

h = w*x + b
graph_forward = make_dot(h)
graph_forward.render(filename='C:\\Users\\Lenovo\\Desktop\\DL\\calc_graph\\graph_forward', view=False, format='pdf')

这里的路径filename一定要写道最终文件的名字,而不是最终文件夹!!!也就是说calc_graph最后一层文件夹,生成的文件是graph_forward.pdf

生成的计算图如下:

其中,蓝底色的3个(1)即是第1章中说明的计算图中的“叶子”,绿底色的(1)是“根”。


这里的“叶子”即为我们经常听说的叶子节点(leaf node)。PyTorch为了节省内存,只会记录叶子节点的相关操作,计算梯度时也只对叶子节点进行计算。


回到 h = w × x + b h = w×x + b h=w×x+b的计算图,如果它代表的是某个深度学习网络模型中的某个隐层的计算过程,那显然我们不用知道对 x x x的偏导,这样我们就可以把它从计算图中剥离出来,把计算资源都给到对参数 w w w和 b b b的计算。把 x x x从计算图中剥离出来的方式也很简单,只要指定requires_grad为False就可以了。


x = torch.tensor([1],dtype=torch.float32,requires_grad=False)

这里再说明另外一个方法——.detach()。有人也会介绍.detach()的作用也是把张量从计算图中剥离出来,甚至有人不明所以会说.detach()和requires_grad=False作用等效。

这里最大的区别就是requires_grad=False会把这个张量直接从计算图中砍掉,这点在下面的计算图中也可以看出来。

而.detach()的作用更类似于“复制”,张量在.detach()操作后在原来的计算图中仍然存在,只是把这个节点的数据复制出来用作别的计算而不会影响原来的计算图。

这样新的计算图就成了这样:

其中左上角的蓝框代表权重w x 已经被砍掉),(1)代表1维向量且只有1个元素,右边蓝框代表偏差b ,下边绿框代表“根”h ,箭头方向代表正向传播方向。


反向传播是从“根”通过链式法则回溯到“叶子”的过程,这里从“根”往上回溯,经历了如下操作过程(灰色框):


  • AddBackward0:加法过程,代表 h = w × x + b h = w×x + b h=w×x+b中的“+”;
  • MulBackward0:乘法过程,代表 h = w × x + b h = w×x + b h=w×x+b中的“×”;
  • AccumulateGrad:梯度积累,在Pytorch中,权重梯度的计算是累加的,这是为了提升训练效率,在每个batch中梯度都进行累加,不同batch间进行梯度清零,这也就是为什么训练的时候要用.zero_grad()的原因;

在 <操作>Backward<层数>中,常见的<操作>有以下几种:

Add代表加法;

Sub代表减法;

Mul代表乘法;

Mm代表矩阵乘法;

Div代表除法;

T代表矩阵转置;

Pow代表乘方;

Squeeze, Unsqueeze, Relu, Sigmoid就代表原本的含义;

<层数>为从"根"到"叶子"的操作层数,本示例中只有1层,所以Backward后面都为0。这里需要注意<层数>是从"根"到"叶子"从下往上数的,所以离"根"越近<层数>越小。

这样我们就把计算图说明白了,无论多复杂的模型,原理都是一样的,只不过是输入输出,操作的复杂度不同而已。


最后需要说明的一点是:计算图在PyTorch中是动态的,在每次调用.backward()之后都会生成一个新的计算图,这样就可以允许在每次学习迭代中调整计算图。


相关文章
|
算法 容器
图压实算法
## 一、定义 将一个原本较为稀疏的图布局,进行压实操作,从而提高画布空间利用率,便于用户理解。 ## 二、适用场景 1. 图面积最小化:即移除多余的空间,将稀疏图变为紧密图。 1. 布局编译:从符号布局生成蒙版布局,电路板。 1. 重新设计:自动清除违反设计规则的情况。 1. 重新缩放:将蒙版级别的布局从一种技术转换到另一种。 在实际场景中,通常用于电路板的排版中。
230 0
|
27天前
|
机器学习/深度学习
R语言使用 LOWESS技术图分析逻辑回归中的函数形式
R语言使用 LOWESS技术图分析逻辑回归中的函数形式
|
10月前
|
机器学习/深度学习 人工智能 架构师
AI框架跟计算图什么关系?PyTorch如何表达计算图?
目前主流的深度学习框架都选择使用计算图来抽象神经网络计算表达,通过通用的数据结构(张量)来理解、表达和执行神经网络模型,通过计算图可以把 AI 系统化的问题形象地表示出来。 本节将会以AI概念落地的时候,遇到的一些问题与挑战,因此引出了计算图的概念来对神经网络模型进行统一抽象。接着展开什么是计算,计算图的基本构成来深入了解诶计算图。最后简单地学习PyTorch如何表达计算图。
115 0
|
11月前
|
机器学习/深度学习
图(Graph)--经典图特征工程:链接分析
本文记录了关于学习图链接分析方法的个人笔记,以供参考学习
109 0
|
11月前
|
Java
离散数学_十章-图 ( 3 ):由旧图构造新图
离散数学_十章-图 ( 3 ):由旧图构造新图
56 0
|
11月前
|
机器学习/深度学习
离散数学_十章-图 ( 4 ):图的表示和图的同构
离散数学_十章-图 ( 4 ):图的表示和图的同构
188 0
|
11月前
|
算法 数据中心
离散数学_十章-图 ( 1 ):图的相关定义
离散数学_十章-图 ( 1 ):图的相关定义
89 0
|
11月前
|
机器学习/深度学习
离散数学_十章-图 ( 2 ):图的术语和几种特殊的图(二)
离散数学_十章-图 ( 2 ):图的术语和几种特殊的图(二)
1181 0
|
11月前
离散数学_十章-图 ( 2 ):图的术语和几种特殊的图(一)
离散数学_十章-图 ( 2 ):图的术语和几种特殊的图(一)
61 0
|
11月前
|
机器学习/深度学习 Python
图(Graph)--经典图特征工程:节点分析
本文分享了关于学习参考多变博客文献后总结的 经典图特征工程 分析方法,以供参考学习
330 0