image.png
圆形表示变量,矩阵表示算子。 如表达式:z=wx+b,可写成两个表示式:y=wx,则z=y+b,其中x、w、b为变量,是用户创建的变量,又称为叶子节点

计算图的反向传播

image.png

  • 为计算各叶子节点的梯度,需要把对应的张量参数requires_grad属性设置为True,这样就可自动跟踪其历史记录。y、z是计算得到的变量,非叶子节点,z为根节点。mul和add是算子(或操作或函数)。由这些变量及算子,就构成一个完整的计算过程(或前向传播过程)

image.png

  • Pytorch调用backward(),将自动计算各节点的梯度,这是一个反向传播过程,这个过程可如上图表示。在反向传播过程中,autograd沿着根节点z反向溯源,利用导数链式法则,计算所有叶子节点的梯度,其梯度值将累加到grad属性中。对非叶子节点的计算操作(或function)记录在grad_fn属性中,叶子节点的grad_fn值为None

    动态图vs静态图

    目前深度学习框架主要有声明式编程和命令式编程两种编程方式。

  • 声明式编程,代码先描述要做的事情但不立即执行,对深度学习任务建模,需要事先定义神经网络的结构,然后再执行整个图结构,这一般称为静态图模式。通常来说,静态图模式能够对整体性做编译优化,更有利于性能的提升

  • 命令式编程对应的动态图模式,代码可以立即执行并返回运算的结果,神经网络结构的定义和执行同步,可以任意修改前向传播。而动态图则非常便于用户对程序进行调试。

    Tensor

    在神经网络中,一个重要内容就是进行参数学习,而参数学习离不开求导,Pytorch是如何进行求导的呢.torch.autograd包就是用来自动求导的。
    autograd包为张量上所有的操作提供了自动求导功能,而torch.Tensor和torch.Function为autograd上的两个核心类,他们相互连接并生成一个有向非循环图

  • Tensor是这个包的核心类,如果将其属性.requires_grad(自动获取梯度)设置为True,它将开始追踪(track)在其上的所有操作(这样就可以利用链式法则进行梯度传播了)。

    • 如果不想被继续追踪,可以调用.detach()(汉语是分离)将Tensor从追踪记录中分离出来,这样就可以防止将来的计算被追踪,这样梯度就传不过去了。
    • 此外,还可以用with torch.no_grad()将不想被追踪的操作代码块包裹起来,这种方法在评估模型的时候很常用,因为在评估模型时,我们并不需要计算可训练参数(requires_grad=True)的梯度。
  • 完成计算后,可以调用.backward()来完成所有梯度计算。此Tensor的梯度将累积到.grad属性中。

    注意在y.backward()时,如果y是标量,则不需要为backward()传入任何参数;否则,需要传入一个与y同形的Tensor。

  • Function是另外一个很重要的类。Tensor和Function互相结合就可以构建一个记录有整个计算过程的有向无环图(DAG)。每个Tensor都有一个.

使用torch.nn模块实现模型

  • 首先,导入torch.nn模块。实际上,“nn”是neural networks(神经网络)的缩写。顾名思义,该模块定义了大量神经网络的层
  • nn就是利用autograd来定义模型。nn的核心数据结构是Module,它是一个抽象概念,既可以表示神经网络中的某个层(layer),也可以表示一个包含很多层的神经网络。在实际使用中,最常见的做法是继承nn.Module,撰写自己的网络/层
  • 一个nn.Module实例应该包含一些层以及返回输出的前向传播(forward)方法。

image.png

Mnist手写数字识别

(1)利用Pytorch内置函数mnist下载数据
(2)利用torchvision对数据进行预处理,调用torch.utils建立一个数据迭代器
(3)可视化源数据
(4)利用nn工具箱构建神经网络模型
(5)实例化模型,并定义损失函数及优化器
(6)训练模型
(7)可视化结果

image.png

说明

①transforms.Compose可以把一些转换函数组合在一起;
②Normalize([0.5], [0.5])对张量进行归一化,这里两个0.5分别表示对张量进行归一化的全局平均值和方差。因图像是灰色的只有一个通道,如果有多个通道,需要有多个数字,如三个通道,应该是Normalize([m1,m2,m3], [n1,n2,n3])
③download参数控制是否需要下载,如果./data目录下已有MNIST,可选择False。
④用DataLoader得到生成器,这可节省内存。