文档章节

pytorch学习-AUTOGRAD: AUTOMATIC DIFFERENTIATION自动微分

o
 osc_fmg49rzg
发布于 2019/03/20 12:12
字数 1408
阅读 5
收藏 0

精选30+云产品,助力企业轻松上云!>>>

参考:https://pytorch.org/tutorials/beginner/blitz/autograd_tutorial.html#sphx-glr-beginner-blitz-autograd-tutorial-py

AUTOGRAD: AUTOMATIC DIFFERENTIATION

PyTorch中所有神经网络的核心是autograd包。让我们先简单地看一下这个,然后我们来训练我们的第一个神经网络。
autograd包为张量上的所有操作提供自动微分。它是一个按运行定义的框架,这意味着的、该支持是由代码的运行方式定义的,并且每个迭代都可以是不同的。

让我们用更简单的术语和一些例子来看看。

Tensor

torch.Tensor是包的中心类。如果将其属性.requires_grad设置为True,它将开始跟踪其上的所有操作。当你完成计算时,你可以调用 .backward()函数并自动计算所有的梯度。这个张量的梯度将累积为.grad属性。

要阻止张量跟踪历史,可以调用.detach()将其从计算历史中分离出来,并防止跟踪未来的计算。

为了防止跟踪历史(和使用内存),还可以使用torch.no_grad():将代码块封装起来。这在评估模型时特别有用,因为模型可能有requires_grad=True的可训练参数,但我们不需要梯度。

还有一个类对autograd实现非常重要—— 即函数。

张量和函数是相互联系的,并建立一个无环图,它编码了一个完整的计算历史。每个张量都有一个.grad_fn属性,该属性引用一个创建了张量的函数(用户创建的张量除外 —— 它们的grad_fn为None)。

如果你想计算导数,你可以在一个张量上调用 .backward() 。如果张量是一个标量(即它包含一个元素数据),你不需要指定任何参数给 .backward() ,但是如果它有更多的元素,你需要指定一个梯度参数,这是一个匹配形状的张量。

import torch

创建一个tensor x并设置requires_grad=True去追踪其计算;然后进行加法操作得到y, 这时候就能够查看y的.grad_fn属性去得到其计算的说明:

#-*- coding: utf-8 -*-
from __future__ import print_function
import torch

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

y = x + 2
print(y)

print(y.grad_fn)

返回:

(deeplearning) userdeMBP:pytorch user$ python test.py
tensor([[1., 1.],
        [1., 1.]], requires_grad=True)
tensor([[3., 3.],
        [3., 3.]], grad_fn=<AddBackward0>)
<AddBackward0 object at 0x101816358>

上面的最后的返回结果AddBackward0说明了该y是经过加法操作获得的

 

还可以进行更多的操作:

#-*- coding: utf-8 -*-
from __future__ import print_function
import torch

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

y = x + 2

z = y * y * 3
out = z.mean()

print(z)
print(out)

返回:

(deeplearning) userdeMBP:pytorch user$ python test.py
tensor([[27., 27.],
        [27., 27.]], grad_fn=<MulBackward0>)
tensor(27., grad_fn=<MeanBackward1>)

可以看出来z是乘法操作得出的,out是求平均值操作得出的

 

.requires_grad_( ... )函数会改变现存的Tensor的内置requires_grad标签。如果没设置,这个标签默认为False,即不计算梯度

#-*- coding: utf-8 -*-
from __future__ import print_function
import torch

a = torch.randn(2, 2)
a = ((a * 3) / (a - 1))
print(a)
print(a.requires_grad)

a.requires_grad_(True)
print(a)
print(a.requires_grad)

b = (a * a).sum()
print(b)
print(b.grad_fn)

返回:

(deeplearning) userdeMBP:pytorch user$ python test.py
tensor([[20.8490, -1.7316],
        [ 1.4831, -2.8223]])
False
tensor([[20.8490, -1.7316],
        [ 1.4831, -2.8223]], requires_grad=True)
True
tensor(447.8450, grad_fn=<SumBackward0>)
<SumBackward0 object at 0x10c381400>

 

Gradients梯度

因为out中只包含了一个标量,out.backward()和out.backward(torch.tensor(1.))的值是相同的

#-*- coding: utf-8 -*-
from __future__ import print_function
import torch

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

y = x + 2

z = y * y * 3
out = z.mean()

print(out)
out.backward()
print(x.grad) # 得到out相对于x的梯度d(out)/dx

返回:

(deeplearning) userdeMBP:pytorch user$ python test.py
tensor(27., grad_fn=<MeanBackward1>)
tensor([[4.5000, 4.5000],
        [4.5000, 4.5000]])

省略计算步骤

你应该得到值为4.5的矩阵。让我们将out称为Tensor "o"。o的计算公式为o=1/4 izizi=3(xi+2)2 zixi=1=27。因此o对xi求导为 o/xi=3/2(xi+2), 带入xi=1,则得到值4.5.

数学上,如果你有一个向量值函数 y⃗ =f(x),那么 y相对于 x的梯度就是一个Jacobian矩阵:

一般来说,torch.autograd是一个计算vector-Jacobian矩阵乘积的引擎。也就是说,给定任意向量v=(v1v2vm)T,计算vTJ。

如果v是一个标量函数 l=g(y)的梯度,那么v为 v=(∂l/y1∂l/ym)T,根据链式法则,vector-Jacobian矩阵乘积就是l相对与x的梯度:

⚠️vTJ给出一个行向量,通过 JTv该行向量可以被视为列向量

 

vector-Jacobian矩阵乘积的这种特性使得将外部梯度输入具有非标量输出的模型变得非常方便。
现在让我们看一个vector-Jacobian矩阵乘积的例子:

#-*- coding: utf-8 -*-
from __future__ import print_function
import torch

x = torch.randn(3, requires_grad=True)
print(x)
y = x * 2
print(y)
while y.data.norm() < 1000: #归一化
    y = y * 2

print(y)

返回:

(deeplearning) userdeMBP:pytorch user$ python test.py
tensor([0.6542, 0.1118, 0.1979], requires_grad=True)
tensor([1.3084, 0.2236, 0.3958], grad_fn=<MulBackward0>)
tensor([1339.8406,  229.0077,  405.2867], grad_fn=<MulBackward0>)

在这种情况下,y不再是标量。 torch.autograd不能直接计算出整个Jacobian矩阵,但是如果我们只想要vector-Jacobian矩阵乘积,只需将向量作为参数向后传递:

#-*- coding: utf-8 -*-
from __future__ import print_function
import torch

x = torch.randn(3, requires_grad=True)
print(x)
y = x * 2
print(y)
while y.data.norm() < 1000: #归一化
    y = y * 2
    
v = torch.tensor([0.1, 1.0, 0.0001], dtype=torch.float)
y.backward(v)

print(x.grad)

返回:

(deeplearning) userdeMBP:pytorch user$ python test.py
tensor([-0.7163,  1.6850, -0.0286], requires_grad=True)
tensor([-1.4325,  3.3700, -0.0572], grad_fn=<MulBackward0>)
tensor([1.0240e+02, 1.0240e+03, 1.0240e-01])

 

你可以通过使用with torch.no_grad():来封装代码块去阻止带有.requires_grad=True配置的Tensors的autograd去追踪历史:

#-*- coding: utf-8 -*-
from __future__ import print_function
import torch

x = torch.randn(3, requires_grad=True)

print(x.requires_grad)
print((x ** 2).requires_grad)

with torch.no_grad():
    print((x ** 2).requires_grad)

返回:

(deeplearning) userdeMBP:pytorch user$ python test.py
True
True
False

 

有关autograd和Function的文档可见https://pytorch.org/docs/autograd

 

o
粉丝 0
博文 500
码字总数 0
作品 0
私信 提问
加载中
请先登录后再评论。
PyTorch 60 分钟入门教程

PyTorch 60 分钟入门教程:PyTorch 深度学习官方入门中文教程 http://pytorchchina.com/2018/06/25/what-is-pytorch/ PyTorch 60 分钟入门教程:自动微分 http://pytorchchina.com/2018/12/...

不知道自己是谁
2018/12/25
0
0
pytorch系统性学习之入门介绍 - 知乎

https://zhuanlan.zhihu.com/p/105094423 pytorch 环境安装及配置 基础的cuda 啥的就不详细描述了,建议用docker、建议用docker、建议用docker,把搞环境的时间花在跑代码上不香吗? 本文主要...

osc_8rbrmk98
03/19
13
0
pytorch系统性学习之入门介绍 - 知乎

pytorch 环境安装及配置 基础的cuda 啥的就不详细描述了,建议用docker、建议用docker、建议用docker,把搞环境的时间花在跑代码上不香吗? 本文主要是来自于pytorch 官网,会稍微改下部分内...

小石头的码疯窝
02/05
0
0
pytorch系统性学习之入门介绍 - 知乎

https://zhuanlan.zhihu.com/p/105094423 pytorch 环境安装及配置 基础的cuda 啥的就不详细描述了,建议用docker、建议用docker、建议用docker,把搞环境的时间花在跑代码上不香吗? 本文主要...

osc_fy59vgpb
03/19
42
0
教程 | PyTorch经验指南:技巧与陷阱

  选自GitHub   作者:Kaixhin   机器之心编译      PyTorch 的构建者表明,PyTorch 的哲学是解决当务之急,也就是说即时构建和运行计算图。目前,PyTorch 也已经借助这种即时运行...

机器之心
2018/07/30
0
0

没有更多内容

加载失败,请刷新页面

加载更多

linux下java环境搭建

1、jdk下载: 官方地址:https://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html 如下图所示,我这边选择的是红框中的版本 2、压缩包上传至服务器 将下载的压缩包上传...

wc_飞豆
33分钟前
17
0
面试题:Java对象不再使用时,为什么要赋值为null?

前言 许多Java开发者都曾听说过“不使用的对象应手动赋值为null“这句话,而且好多开发者一直信奉着这句话;问其原因,大都是回答“有利于GC更早回收内存,减少内存占用”,但再往深入问就回...

码农突围
35分钟前
22
0
设计模式(5) 原型模式

原型模式 原型模式的适用场景 浅拷贝 深拷贝 用Initialize方法修改初始化状态 原型模式与之前学习的各种工厂方法、单例模式、建造者模式最大、最直观的区别在于,它是从一个既有的对象“克隆...

zhixin9001
35分钟前
7
0
获取免费的pycharm激活码网站

http://www.lookdiv.com/

云烟成雨forever
35分钟前
27
0
用Helm部署Kubernetes应用,支持多环境部署与版本回滚

1 前言 Helm是优秀的基于Kubernetes的包管理器。利用Helm,可以快速安装常用的Kubernetes应用,可以针对同一个应用快速部署多套环境,还可以实现运维人员与开发人员的职责分离。现在让我们安...

南瓜慢说
37分钟前
12
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部