AUTOGRAD: AUTOMATIC DIFFERENTIATION(自动分化)

来源于这里

autograd包是PyTorch中所有神经网络的核心。首先我们先简单地了解下它,然后我们将训练我们的第一个神经网络。

autograd包为Tensors上的所有操作提供自动分化。它是一个逐步执行的框架,这意味着你的反向传播(backprop)函数是由你的代码运行方式定义的,而且每个迭代器可以是不同的。接下来通过一些例子用更简单的术语来了解autograd

Tensor

torch.tensorautograd包的核心。如果你将它的属性.requires_grad设置为True,那么它将开始追踪其上的所有操作。当完成你的计算之后,你可以调用.backward()是所有的梯度自动计算完成。这个张量的梯度会被累积到.grad属性中。

要停止张量追踪记录,你可以使用.detach()将它熊计算记录中分离出来,并防止将来的计算被追踪。

为了阻止追踪记录(和使用内存),你可以使用with torch.no_grad()打包代码块。这在评估模型的时候非常有用,因为当模型的requires_grad=True时,可能具有可训练的参数,但我们并不需要这些梯度。

另外还有一个对自动推倒非常重要的类 --- Function

TensorFunction相互关联、构建出一个无环图,它编码了一个完整的计算历史记录。每个tensor都有一个.grad_fn属性,该属性引用自一个创建张量(用户创建的张量除外,它们的.grad_fn是空)的函数。

如果你想计算导数,你可以调用张量上的backward()。如果张量是一个标量(比如它只有一个数据元素),那么你不需要给backward()传递任何特殊的参数;但是如果它拥有多个元素,你需要指定一个特殊的梯度参数,它是一个与形状匹配的张量。

创建一个张量,并设置requires_grad=True来追踪计算。

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

输出

tensor([[1., 1.],
[1., 1.]], requires_grad=True)

进行一次张量操作:

y = x + 2
print(y)

输出:

tensor([[3., 3.],
[3., 3.]], grad_fn=<AddBackward0>)

y是作为一个操作的结果被创建的,所以它有grad_fn属性:

print(y.grad_fn)

输出:

<AddBackward0 object at 0x121669470>

y进行更多操作:

z = y * y * 3
out = z.mean()
print(z,out)
tensor([[27., 27.],
[27., 27.]], grad_fn=<MulBackward0>) tensor(27., grad_fn=<MeanBackward0>)

。requires_grad_(...)可以改变已存在张量的requires_grad属性。如果为给定,该输入标识默认为False

a = torch.randn(2,2)
a = ((a * 3) / (a - 1))
print(a.requires_grad)
a.requires_grad_(True)
print(a.requires_grad)
b = (a * a).sum()
print(b.grad_fn)

输出:

False
True
<SumBackward0 object at 0x121726588>

Gradients(梯度)

现在进行反向传播。因为out只包含一个标量,out.backward()等价于out.backward(torch.tensor(1.))

out.backward()

打印梯度 d(out)/dx:

print(x.grad)

输出:

tensor([[4.5000, 4.5000],
[4.5000, 4.5000]])

如上,得到了一个4.5填充的2x2的矩阵。我们将out张量命名为\(\omicron\)。我们知道\(\omicron = \frac{1}{4}\sum_iz_i,z_i = 3(x_i+2)^2\),而且\(z_i|_{x_i=1} = 27\),那么,\(\frac{\sigma_\omicron}{\sigma_{x_i}} = \frac{3}{2}(x_i + 2)\),因此\(\frac{\sigma_\omicron}{\sigma_{x_i}}|_{x_i=1} = \frac{9}{2} = 4.5\)。

在数学上,如果你有一个向量值函数\(\vec{y} = f(\vec{x})\),那么遵循\(\vec{x}\)的\(\vec{y}\)的梯度是一个Jacobian矩阵:

\[ J = \begin{pmatrix}
\frac{\sigma_{y_1}}{\sigma_{x_1}} \quad \cdots \quad \frac{\sigma_{y_1}}{\sigma_{x_n}} \\
\vdots \quad \ddots \quad \vdots \\
\frac{\sigma_{y_m}}{\sigma_{x_1}} \quad \cdots \quad \frac{\sigma_{y_m}}{\sigma_{x_n}}
\end{pmatrix}\]

通常来讲,torch.autograd是一个计算vector-Jacobian结果的引擎。也就是说,给定任意的\(v = (v_1 \quad v_2 \quad \cdots \quad v_m)^T\),计算\(v^T \cdot J\)的结果。如果\(v\)恰好是标量函数\(l = g(\vec{y})\)的梯度,那么\(v = (\frac{\sigma_l}{\sigma_{y_1}} \quad \cdots \quad \frac{\sigma_l}{\sigma_{y_n}})\),然后根据链接规则,vector-Jacobain的结果就是遵循\(\vec{x}\)的\(l\)的梯度:

\[J^T \cdot v = \begin{pmatrix}
\frac{\sigma_{y_1}}{\sigma_{x_1}} \quad \cdots \quad \frac{\sigma_{y_m}}{\sigma_{x_1}} \\
\vdots \quad \ddots \quad \vdots \\
\frac{\sigma_{y_1}}{\sigma_{x_n}} \quad \cdots \quad \frac{\sigma_{y_m}}{\sigma_{x_n}}
\end{pmatrix} \begin{pmatrix}
\frac{\sigma_l}{\sigma_{y_1}} \\
\vdots \\
\frac{\sigma_l}{\sigma_{y_m}}
\end{pmatrix} = \begin{pmatrix}
\frac{\sigma_l}{\sigma_{x_1}} \\
\vdots \\
\frac{\sigma_l}{\sigma_{x_n}}
\end{pmatrix}\]

注意 \(v^T \cdot J\)给出了一个可以看做是从\(J^T \cdot v\)获取的列向量的行向量。

vector-Jacobain结果的特性使得在一个非标量输出的模型中反馈外部梯度非常方便。

现在我们来看一个vector-Jacobain结果的例子:

x = torch.rands(3,requires_grad=True)
y = x * 2 while y.data.norm() < 1000:
y = y * 2 print(y)

输出:

tensor([805.7939, -90.6879, 624.5883], grad_fn=<MulBackward0>)

现在这种情况下,y不再是一个标量。torch.autograd不能直接计算完整的Jacobain矩阵,但如果我们只想要vector-Jacobain结果,那么只需将向量作为参数传递给backward即可。

v = torch.tensor([0.1,1.0,0.0001],dtype=torch.float)
y.backward(v) print(x.grad)

输出:

tensor([2.5600e+01, 2.5600e+02, 2.5600e-02])

你也可以通过使用with torch.no_grad()打包代码块的方式在.requires_grad=True的张量上停止追踪历史记录的自动推倒。

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

输出:

True
True
False

进阶阅读

更详细的autogradFunction文档在这里

[PyTorch入门之60分钟入门闪击战]之自动推倒的更多相关文章

  1. [PyTorch入门之60分钟入门闪击战]之入门

    深度学习60分钟入门 来源于这里. 本文目标: 在高层次上理解PyTorch的Tensor库和神经网络 训练一个小型的图形分类神经网络 本文示例运行在ipython中. 什么是PyTorch PyTo ...

  2. [PyTorch入门之60分钟入门闪击战]之训练分类器

    训练分类器 目前为止,你已经知道如何定义神经网络.计算损失和更新网络的权重.现在你可能在想,那数据呢? What about data? 通常,当你需要处理图像.文本.音频或者视频数据时,你可以使用标 ...

  3. [PyTorch入门之60分钟入门闪击战]之神经网络

    神经网络 来源于这里. 神经网络可以使用torch.nn包构建. 现在你对autograd已经有了初步的了解,nn依赖于autograd定义模型并区分它们.一个nn.Module包含了层(layers ...

  4. PyTorch 60 分钟入门教程

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

  5. 【PyTorch深度学习60分钟快速入门 】Part4:训练一个分类器

      太棒啦!到目前为止,你已经了解了如何定义神经网络.计算损失,以及更新网络权重.不过,现在你可能会思考以下几个方面: 0x01 数据集 通常,当你需要处理图像.文本.音频或视频数据时,你可以使用标准 ...

  6. 【PyTorch深度学习60分钟快速入门 】Part0:系列介绍

      说明:本系列教程翻译自PyTorch官方教程<Deep Learning with PyTorch: A 60 Minute Blitz>,基于PyTorch 0.3.0.post4 ...

  7. 【PyTorch深度学习60分钟快速入门 】Part5:数据并行化

      在本节中,我们将学习如何利用DataParallel使用多个GPU. 在PyTorch中使用多个GPU非常容易,你可以使用下面代码将模型放在GPU上: model.gpu() 然后,你可以将所有张 ...

  8. 【PyTorch深度学习60分钟快速入门 】Part2:Autograd自动化微分

      在PyTorch中,集中于所有神经网络的是autograd包.首先,我们简要地看一下此工具包,然后我们将训练第一个神经网络. autograd包为张量的所有操作提供了自动微分.它是一个运行式定义的 ...

  9. 【PyTorch深度学习60分钟快速入门 】Part1:PyTorch是什么?

      0x00 PyTorch是什么? PyTorch是一个基于Python的科学计算工具包,它主要面向两种场景: 用于替代NumPy,可以使用GPU的计算力 一种深度学习研究平台,可以提供最大的灵活性 ...

随机推荐

  1. Python 学习笔记:根据输入年月区间,返回期间所有的月份

    目的: 给定一个年月区间,比如:2019.01 至 2019.05,要求返回一个包含期间所有的月份的列表,比如:['2019.01', '2019.02', '2019.03', '2019.04', ...

  2. 致 Python 初学者们!

    ​ 前言 在 Python 进阶的过程中,相信很多同学应该大致上学习了很多 Python 的基础知识,也正在努力成长.在此期间,一定遇到了很多的困惑,对未来的学习方向感到迷茫.我非常理解你们所面临的处 ...

  3. linux下tab作用的描述?

    [Tab] 接在一串指令的第一个字的后面,则为命令补全;     实例怎么描述?什么叫一串指令的第一个字?[Tab] 接在一串指令的第二个字以后时,则为『文件补齐』   实例怎么描述?什么叫一串指令的 ...

  4. Android 5.0 5.1 webview 闪退问题

    自定义webview /** * 处理Android 5.0 5.1 webview 闪退 */ class MyWebView : WebView { companion object{ priva ...

  5. Matlab高级教程_第二篇:Matlab相见恨晚的模块_02_并行运算-2

    1 MATLAB并行计算-从个人桌面到远程集群和云(陈伟/魏奋)视频摘录笔记 https://cn.mathworks.com/videos/parallel-computing-with-matla ...

  6. NOIP2000提高组T1 进制转换

    https://www.luogu.org/problem/P1017 题目描述 我们可以用这样的方式来表示一个十进制数: 将每个阿拉伯数字乘以一个以该数字所处位置的值减1为指数,以10为底数的幂之和 ...

  7. 线程中start与run方法的主要区别

    区别一:                在于当程序调用start方法一个新线程将会被创建,并且在run方法中的代码将会在新线程上运行,                然而在你直接调用run方法的时候, ...

  8. window下mysql安装步骤

    1. 官网下载mysql zip包 2. 解压后再D:\database\mysql\mysql-5.7.26-winx64下添加my.ini文件,文件内容如下: [mysql]# 设置mysql客户 ...

  9. 动态指定log4net日志文件名称

    如果是希望日志文件按常见的日期格式动态命名,没什么好说的,直接修改app.config <param name="DatePattern" value="yyyyM ...

  10. StartDT AI Lab | 视觉智能引擎+数据决策引擎——打造商业“智能沙盘”

    众所周知,线上商家可以通过淘宝平台的大量前端“埋点”轻松获取商品的加购率.收藏率.转化率.成交额等大量基础信息,甚至商家能够在更精细的层面,获取商品关键字变化或者上新/爆款带来的流量变化数据,更甚者商 ...