三、深度学习开源框架PyTorch的特性

一、PyTorch的特性

1、与Python完美融合(Pythonic)

PyTorch与Python其他程序包没有任何区别。

2、支持张量计算(tensor computation)

PyTorch的运算单元叫张量(Tensor)。

张量其实就是多维数组:

一阶张量叫一维数组,又叫做向量(vector);

二阶张量叫二维数组,又叫做矩阵(Matrix);

n阶张量即n维数组。

我们将一个张量的每个维度的大小称为张量在这个维度的尺寸(size)。

一个2阶张量a: a = [[1,2,3],[4,5,6]]

一般来说,确定张量的维数可以通过确定其最左边的括号个数,如果有n个括号,那么这个张量就是n阶。

张量的形状:

张量 1 的形状是[]; 表示0行0列。

张量[1,2,3]的形状是[3]; 表示1行3列。

张量[[1,2],[3,4]]的形状是[2,2]; 表示2行2列。

PyTorch中的张量定义和访问方法与Python中的NumPy数组的定义和访问是相同的,因此可以参考NumPy的语法和技巧来操作PyTorch中的张量。

PyTorch中的张量可以在GPU中运算,而NumPy数组却不能,所以它提高了运算速度。

张量的切片:

import torch

x = torch.rand(5,3)
print(x)
print(x[:2,1])

张量的加法:x和y的尺寸需要一模一样。

import torch

x = torch.rand(5,3)
print(x)

y = torch.ones(5,3)
print(y)

z = x+y
print(z)

 二维张量的矩阵乘法:和两个矩阵相乘一样。

mm:matrix multiply

根据矩阵的乘法规则,第一个张量x的第二个维度的尺寸必须和第二个张量y的第一个维度的尺寸相等才能相乘,所以需要先将y转置y.t()后得到尺寸(3,5)才可以和x(5,3)相乘

import torch

x = torch.rand(5,3)
print(x)

y = torch.rand(5,3)
print(y)

q = x.mm(y.t())
print(q)

张量的基本运算还有换位、索引、切片、数学运算、线性运算、随机数等。

张量与NumPy数组之间的直接转换:

from_numpy(a):a是一个NumPy数组,转换为张量;

a.numpy():a是一个张量,转换为NumPy数组。 

randn:创建一个满足正态分布的随机张量或矩阵;

rand:创建一个满足均匀分布的随机张量或矩阵。 

import numpy as np
import torch

x_tensor = torch.randn(2,3) #尺寸为(2,3)的随机张量
y_numpy = np.random.randn(2,3) #尺寸为(2,3)的随机矩阵

x_numpy = x_tensor.numpy() #转换为数组
y_tensor = torch.from_numpy(y_numpy) #转换为张量

 张量与NumPy数组之间的按照类型转换:

torch.FloatTensor(a):a是一个float类型的NumPy数组,将其转换为float类型的张量;

torch.LongTensor(a):a是一个int类型的NumPy数组,将其转换为int类型的张量。

3、动态计算图(dynamic computation graph)

反向传播算法能够精确地计算出神经网络中每一个神经元对于神经网络表现的贡献,即所谓的梯度信息,利用这种技术大大提高了神经网络的训练效率。

现在大多数深度学习框架采用了计算图(computational graph)技术,有了它就不需要为每一种架构的网络定制不同的反向传播算法,而只需要关注如何实现神经网络的前馈运算即可。当前馈运算步骤完成后,深度学习框架就会自动搭建一个计算图,通过这个图,就可以让反向传播算法自动进行。计算图技术大幅提升了构建神经计算系统的效率。

        计算图技术的基本思想是将正向的计算过程步骤记录下来,只要这些运算步骤是可微分(differentialable)的,即可以进行求导运算的,我们就可以沿着计算图的路径对任意变量进行求导,从而自动计算每个变量的梯度。

        动态计算图是整套深度学习技术和框架中的最重要核心,它是数值运算符号运算(微分求导)的一种综合。

        计算图是一种描述和记录张量运算过程的抽象网络,它有两种节点:变量(variable)运算(computation)

静态计算图技术:

        传统的深度学习框架,TensorFlow、Theano。将计算图的构建过程和利用该图进行计算的过程明确分离。优点是静态计算图可以反复利用。

        PyTorch可以动态地构建计算图,同时在计算图上执行计算,执行完计算后还可以接着构建计算图,而不需要将构建计算图和图上的计算过程分离。优点:构建计算图的过程像写python代码一样方便、快捷,也让代码的调试和最终更简便。

自动微分变量:

Autograd variable。PyTorch用此乃实现动态计算图。

PyTorch 1.5以后,自动微分变量与张量合并了,因此,任何一个张量都是自动微分变量。

在采用自动微分变量后,无论一个计算过程多么复杂,系统都会自动构造一个计算图来记录所有的运算过程。构建好动态计算图之后,就可以利用.backward()函数自动执行反向传播算法,从而计算出每一个自动微分变量的梯度信息。

3个重要属性:

data:伴随自动微分变量的张量,专门存储计算结果。平时可以将自动微分变量当成普通的张量来使用,这样,PyTorch就会将计算的结果张量存储到自动微分变量的data分量里。

grad_fn:通过访问自动微分变量的grad_fn来获得计算图中的上一个节点,从而知道是哪个运算导致现在这个自动微分变量的出现。每个节点的grad_fn其实就是计算图中的箭头,可以利用grad_fn来回溯每一个箭头,从而重构整个计算图。

grad:当执行反向传播算法时,需要计算动态计算图中的每一个变量节点的梯度值(gradient,该变量需要调整的增量),只需要调用.backward()函数,就能计算所有变量的梯度值,并将叶节点的导数值存储在.grad中。

动态计算图实例:

requires_grad=True是为了保证它可以在执行反向传播算法的过程中获得梯度信息。

import torch
x = torch.ones(2,2,requires_grad=True)
print(x)

普通的张量就是自动微分变量,因此,可以像对张量一样对自动微分变量进行各类运算。

import torch
x = torch.ones(2,2,requires_grad=True)
print(x)
y = x + 2
print(y)
print(y.data) #查看y中存储的数值
print(y.grad_fn) #查看y的grad_fn

运算结果中的AddBackward0表示加上一个常数的运算。

import torch
x = torch.ones(2,2,requires_grad=True)
# print(x)
y = x + 2
z = y * y
print(z.grad_fn)

 上面代码中*表示自动微分变量或张量之间的按元素乘法,即两个张量在对应位置上进行数值相乘,它与矩阵运算mm完全不一样。

运算结果中的MulBackward0表示是乘法运算。

计算图每增加一次运算,就将相邻两个运算节点连接在一起。

import torch
x = torch.ones(2,2,requires_grad=True)
y = x + 2
z = y * y
t = torch.mean(z)
print(t)

torch.mean()表示求平均。上面的z相当于是一个矩阵,它的平均值等于矩阵里的每个元素求和再除以元素个数。

总结:

  • 通过自动微分变量,PyTorch可以将运算过程全部通过.grad_fn属性记录下来,构成一个计算图;
  • 自动微分变量的运算结果存储在data中;
  • 每进行一步运算,PyTorch就将一个新的运算节点添加到动态计算图中,并与上一步的计算节点相连接。

 梯度计算:

我们在上面的计算图上加上反向传播算法,它指的是沿着计算图从下往上计算每个变量节点梯度信息的过程。

求梯度:就是高等数学中的求导运算,梯度信息就是导数数值。

t.backward():执行这条语句,会自动进行求导计算,并在计算图上执行反向传播算法。

PyTorch规定,只有计算图上的叶节点才可以通过.backward()获取梯度信息。下面的z和y不是叶节点,没有梯度信息。

如何区分哪些是叶子节点:叶子结点的张量是自变量?(自己的理解)

import torch
x = torch.ones(2,2,requires_grad=True)
y = x + 2
z = y * y
t = torch.mean(z)
t.backward() #求导计算,即反向传播算法
print(z.grad) #查看节点z的梯度
print(y.grad) #查看节点y的梯度
print(x.grad) #查看节点x的梯度

梯度或者导数的计算都可以自动化地进行,无论函数的依赖关系多么复杂,无论神经网络有多深,都可以用.backward()函数来完成梯度的自动计算。

 如果一个张量在计算图中出现了多次,那么在对此张量计算梯度时,会为该张量的每一个节点计算梯度信息,然后再把它们的梯度信息相加,作为该张量的最终的梯度信息。

梯度清空:

       每次训练后都需要使用.zero_grad()函数来清空各个参数的梯度。如果不清空的话,backward()函数会累加梯度,可能导致模型无法收敛。而每进行一次训练后,都会立即将梯度反传,因此不需要神经网络累加梯度。

二、PyTorch的规定

1、不能直接对自动微分变量(张量)进行数值更新,只能对它的data属性进行更新。

2、如果某个函数后面加上了“_”,就表明要用这个函数的计算结果更新当前的变量。如:a.data.add_(7)的作用是将a.data的数值更新为a.data加上7。 

三、PyTorch的总结

        PyTorch可以利用自动微分变量(也即张量),将一般的计算过程全部转换为动态计算图。

        一个完整的深度学习算法就可以搭建一个动态计算图,也即是广义的神经网络,之后再利用PyTorch中的backward()函数进行自动求导,然后再利用复杂的动态计算图进行梯度信息的反向传播,从而计算出每个叶节点对应的自动微分变量的梯度信息。有了该梯度信息后,就可以利用梯度下降算法来更新参数,这就是广义的训练或者学习过程。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值