《动手学深度学习(PyTorch版)》笔记2

Chapter2 Preliminaries

2.1 Automatic Differentiation

让计算机实现微分功能, 有以下四种方式:
- 手工计算出微分, 然后编码进代码
- 数值微分 (numerical differentiation)
- 符号微分 (symbolic differentiation)
- 自动微分(automatic differentiation)
在这里插入图片描述

深度学习框架通过自动微分来加快求导。
实际中,根据设计好的模型,系统会构建一个计算图(computational graph),来跟踪计算是哪些数据通过哪些操作组合起来产生输出。自动微分使系统能够随后反向传播梯度。这里,反向传播(backpropagate)意味着跟踪整个计算图,填充关于每个参数的偏导数。自动微分以链式法则为基础,将一个复杂的数学运算过程分解为一系列简单的基本运算,把公式中一些部分整理出来成为一些新变量,然后用这些新变量整体替换这个公式,而且每一项基本运算都可以通过查表得出来。自动微分有两种形式

- 前向模式 (forward mode)
- 反向模式 (reverse mode)

前向模式是在计算图前向传播的同时计算微分。下面的前向模式微分中, v i ˙ = ∂ v i ∂ x 1 \dot{v_i}=\frac{\partial v_i}{\partial x_1} vi˙=x1vi
在这里插入图片描述

反向模式需要对计算图进行一次正向计算, 得出输出值,再进行反向传播, 其中 v i ˉ = ∂ y j ∂ v i \bar{v_i}=\frac{\partial y_j}{\partial v_i} viˉ=viyj
在这里插入图片描述

前向模式的一次正向传播能够计算出输出值以及导数值, 而反向模式需要先进行正向传播计算出输出值, 然后进行反向传播计算导数值,所以反向模式的内存开销要大一点, 因为它需要保存正向传播中的中间变量值,这些变量值用于反向传播的时候计算导数。当输出的维度大于输入的时候,适宜使用前向模式微分;当输出维度远远小于输入的时候,适宜使用反向模式微分。

从矩阵乘法次数的角度来看,前向模式和反向模式的不同之处在于矩阵相乘的起始之处不同。当输出维度小于输入维度,反向模式的乘法次数要小于前向模式。
在这里插入图片描述

2.1.1 一个简单的例子

假设我们想对函数 y = 2 x ⊤ x y=2\mathbf{x}^{\top}\mathbf{x} y=2xx关于列向量 x \mathbf{x} x求导。首先,我们创建变量x并为其分配一个初始值。

import torch
x = torch.arange(4.0)
x

结果:

tensor([0., 1., 2., 3.])

在我们计算 y y y关于 x \mathbf{x} x的梯度之前,需要一个地方来存储梯度。重要的是,我们不会在每次对一个参数求导时都分配新的内存。因为我们经常会成千上万次地更新相同的参数,每次都分配新的内存可能很快就会将内存耗尽。注意,一个标量函数关于向量 x \mathbf{x} x的梯度是向量,并且与 x \mathbf{x} x具有相同的形状。

x.requires_grad_(True)  # 等价于x=torch.arange(4.0,requires_grad=True)
x.grad  # 
y = 2 * torch.dot(x, x)
y

结果:

tensor(28., grad_fn=<MulBackward0>)

x \mathbf{x} x是一个长度为4的向量,计算 x \mathbf{x} x x \mathbf{x} x的点积,得到了我们赋值给y的标量输出。
接下来,通过调用反向传播函数来自动计算y关于x每个分量的梯度,并打印这些梯度。

y.backward()
x.grad

结果:

tensor([ 0.,  4.,  8., 12.])

函数 y = 2 x ⊤ x y=2\mathbf{x}^{\top}\mathbf{x} y=2xx关于 x \mathbf{x} x的梯度应为 4 x 4\mathbf{x} 4x,显然计算结果正确。
现在计算 x \mathbf{x} x的另一个函数。

# 在默认情况下,PyTorch会累积梯度,我们需要清除之前的值
x.grad.zero_() #将张量x的梯度清零
y = x.sum()
y.backward()
x.grad

结果:

tensor([1., 1., 1., 1.])

2.1.2 非标量变量的反向传播

y不是标量时,向量 y \mathbf{y} y关于向量 x \mathbf{x} x的导数的最自然解释是一个矩阵。
对于高阶和高维的y x \mathbf{x} x,求导的结果可以是一个高阶张量。

然而,虽然这些更奇特的对象确实出现在高级机器学习中,但当调用向量的反向计算时,我们通常会试图计算一批训练样本中每个组成部分的损失函数的导数。这里我们的目的不是计算微分矩阵,而是单独计算批量中每个样本的偏导数之和。

# 对非标量调用backward需要传入一个gradient参数,该参数指定微分函数关于self的梯度。
# 本例只想求偏导数的和,所以传递一个1的梯度是合适的
x.grad.zero_()
y = x * x
y.sum().backward()#等价于y.backward(torch.ones(len(x)))
x.grad

结果:

tensor([0., 2., 4., 6.])

2.1.3 分离计算

有时,我们希望将某些计算移动到记录的计算图之外。例如,假设y是作为x的函数计算的,而z则是作为yx的函数计算的。想象一下,我们想计算z关于x的梯度,但由于某种原因,希望将y视为一个常数,并且只考虑到xy被计算后发挥的作用。这里可以分离y来返回一个新变量u,该变量与y具有相同的值,但丢弃计算图中如何计算y的任何信息。换句话说,梯度不会向后流经ux。因此,下面的反向传播函数计算z=u*x关于x的偏导数,同时将u作为常数处理,而不是z=x*x*x关于x的偏导数。

x.grad.zero_()
y = x * x
u = y.detach()
z = u * x
z.sum().backward()
x.grad == u

结果:

tensor([True, True, True, True])

由于记录了y的计算结果,我们可以随后在y上调用反向传播,
得到y=x*x关于的x的导数,即2*x

x.grad.zero_()
y.sum().backward()
x.grad == 2 * x

结果:

tensor([True, True, True, True])

2.1.4 Python控制流的梯度计算

使用自动微分的一个好处是:
即使构建函数的计算图需要通过Python控制流(例如,条件、循环或任意函数调用),我们仍然可以计算得到的变量的梯度。
在下面的代码中,while循环的迭代次数和if语句的结果都取决于输入a的值。

def f(a):b = a * 2while b.norm() < 1000:b = b * 2if b.sum() > 0:c = belse:c = 100 * breturn ca = torch.randn(size=(), requires_grad=True)
d = f(a)
d.backward()
a.grad == d / a

我们现在可以分析上面定义的f函数。
请注意,它在其输入a中是分段线性的。
换言之,对于任何a,存在某个常量标量k,使得f(a)=k*a,其中k的值取决于输入a,因此可以用d/a验证梯度是否正确。

结果:

    tensor(True)

2.1.5 小结

  • 深度学习框架可以自动计算导数:我们首先将梯度附加到想要对其计算偏导数的变量上,然后记录目标值的计算,执行它的反向传播函数,并访问得到的梯度。

2.1.6 参考文献

  • 一文看懂AD原理
  • AD的正反向模式
  • AD的常用实现方案
  • 反向OO实现自动微分(Pytroch核心机制)
  • Automatic differentiation in machine learning: a survey

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/644280.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java web mvc-03-JFinal

拓展阅读 Spring Web MVC-00-重学 mvc mvc-01-Model-View-Controller 概览 web mvc-03-JFinal web mvc-04-Apache Wicket web mvc-05-JSF JavaServer Faces web mvc-06-play framework intro web mvc-07-Vaadin web mvc-08-Grails JFinal JFinal 是基于 Java 语言的极…

Shell脚本③条件语句、if命令和case命令

目录 一.条件语句 1.test测试条件表达式 2.整数数值比较 &#xff08;1&#xff09;比较两个整数大小 &#xff08;2&#xff09;查看系统剩余内存是否低于1024M 3.逻辑测试 4.三元运算符 二.if命令 1.单分支结构 2.双分支结构 3.多分支结构 三.case语句 四.脚本 …

代码随想录算法训练营第十三天|层序遍历10,226.翻转二叉树,101.对称二叉树

系列文章目录 代码随想录算法训练营第一天|数组理论基础&#xff0c;704. 二分查找&#xff0c;27. 移除元素 代码随想录算法训练营第二天|977.有序数组的平方 &#xff0c;209.长度最小的子数组 &#xff0c;59.螺旋矩阵II 代码随想录算法训练营第三天|链表理论基础&#xff…

项目成本估算基准的常见步骤

项目成本估算基准是指在项目启动阶段确定的用于衡量和控制项目成本的基准。 基准成本是项目成本估算的依据&#xff0c;也是后续成本控制和决策的依据。它为管理层提供项目预算投资方案等关键投资依据&#xff0c;决定资源的分配情况&#xff0c;有助于优化资源使用效率&#x…

【Linux】文件周边001之系统文件IO

&#x1f440;樊梓慕&#xff1a;个人主页 &#x1f3a5;个人专栏&#xff1a;《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》《实训项目》《C》《Linux》《算法》 &#x1f31d;每一个不曾起舞的日子&#xff0c;都是对生命的辜负 目录 前言 1.C语言文件IO 1.1…

2024 V加爆好友的4个方法

2024加好友&#x1f449;加爆V信的4个方法

SUSE Linux 15 SP5 安装图解

风险告知 本人及本篇博文不为任何人及任何行为的任何风险承担责任&#xff0c;图解仅供参考&#xff0c;请悉知&#xff01;本次安装图解是在一个全新的演示环境下进行的&#xff0c;演示环境中没有任何有价值的数据&#xff0c;但这并不代表摆在你面前的环境也是如此。生产环境…

如何自己制作一个属于自己的小程序?

在这个数字化时代&#xff0c;小程序已经成为了我们生活中不可或缺的一部分。它们方便快捷&#xff0c;无需下载安装&#xff0c;扫一扫就能使用。如果你想拥有一个属于自己的小程序&#xff0c;不论是为了个人兴趣&#xff0c;还是商业用途&#xff0c;都可以通过编程或者使用…

【论文阅读|2024 WACV 多目标跟踪Deep-EloU】

论文阅读|2024 WACV 多目标跟踪Deep-EloU 摘要1 引言&#xff08;Introduction&#xff09;2 相关工作&#xff08;Related Work&#xff09;2.1 基于卡尔曼滤波器的多目标跟踪算法&#xff08;Multi-Object Tracking using Kalman Filter&#xff09;2.2 基于定位的多目标跟踪…

一篇博客读懂排序

目录 一、常见的排序 二、冒泡排序 2.1基本思想&#xff1a; 2.2代码&#xff1a; 三、插入排序 3.1基本思想&#xff1a; 3.2思路讲解&#xff1a; 3.3代码&#xff1a; 3.4时间复杂度&#xff1a; 四、希尔排序 4.1基本思路&#xff1a; 4.2思路讲解&#xff1a;…

微信小程序如何获取当前日期时间

Hello大家好&#xff01;我是咕噜铁蛋&#xff0c;获取当前日期时间是小程序中经常会用到的一个功能。因此&#xff0c;在本文中&#xff0c;我通过科技手段给大家收集整理了下&#xff0c;今天我将向大家介绍如何在微信小程序中获取当前日期时间的方法&#xff0c;并分享一些实…

Overleaf(LaTeX文档在线编写平台)使用学习记录

一、LaTeX简概[1] LaTeX&#xff0c;是一种基于TEX的排版系统&#xff0c;是一种可以处理排版和渲染的标记语言。由美国计算机科学家莱斯利兰伯特在20世纪80年代初期开发&#xff0c;利用这种格式系统的处理&#xff0c;即使用户没有排版和程序设计的知识也可以充分发挥由TEX所…

离零售业智能体时代的真正开启还有多远?

AIGC&#xff08;生成式人工智能&#xff09;当道的2023年&#xff0c;将LLM&#xff08;大语言模型&#xff09;的各类生成式能力发挥到淋漓尽致、精彩纷呈的程度。各行各业一边在观望大语言模型不断扩宽的商业运用可能&#xff0c;一边在继续探寻能够不断拓宽企业往纵深发展的…

Mybatis----缓存

MyBatis是一个流行的Java持久化框架&#xff0c;它提供了一个灵活的缓存机制来提高查询性能。 MyBatis的缓存机制主要分为一级缓存和二级缓存。 一级缓存是指在同一个SqlSession中&#xff0c;查询结果会被缓存起来&#xff0c;当再次执行同样的查询时&#xff0c;直接从缓存中…

基于SSM的企业文档管理系统

末尾获取源码作者介绍&#xff1a;大家好&#xff0c;我是何时&#xff0c;本人4年开发经验&#xff0c;专注定制项目开发 更多项目&#xff1a;CSDN主页YAML 我欲乘风归去 又恐琼楼玉宇 高处不胜寒 -苏轼 一、项目简介 现代经济快节奏发展以及不断完善升级的信息化技术&…

深度了解TCP/IP模型

网络通信是现代社会不可或缺的一部分&#xff0c;而TCP/IP模型作为网络通信的基石&#xff0c;扮演着至关重要的角色。本文将深入探讨TCP/IP模型的概念、结构及其在网络通信中的作用&#xff0c;为读者提供全面的了解。 一.TCP/IP模型简介 TCP/IP模型是一个网络通信协议体系&a…

机器学习 | 掌握Matplotlib的可视化图表操作

Matplotlib是python的一个数据可视化库&#xff0c;用于创建静态、动态和交互式图表。它可以制作多种类型的图表&#xff0c;如折线图、散点图、柱状图、饼图、直方图、3D 图形等。以渐进、交互式方式实现数据可视化。当然博主也不能面面俱到的讲解到所有内容&#xff0c;详情请…

【极数系列】Flink 初相识(01)

# 【极数系列】Flink 初相识&#xff08;01&#xff09; 引言 Flink官网&#xff1a;https://flink.apache.org/ Flink版本&#xff1a;https://flink.apache.org/blog/ Flink文档&#xff1a;https://ci.apache.org/projects/flink/flink-docs-release-1.12/ Flink代码库…

轻松互换文件夹名,高效批量改名!高手工具助您一臂之力!

在日常工作中&#xff0c;我们经常需要处理大量的文件夹&#xff0c;有时候需要将文件夹名称互换或进行批量改名。这时&#xff0c;一款高效、实用的高手工具就能派上用场。它不仅能帮助您轻松实现文件夹名互换&#xff0c;还能快速批量改名&#xff0c;让您的工作更加高效、轻…

Unity - 角色控制

Test_05 角色控制 创建一个3D对象作为角色&#xff0c;添加 “CharacterController” 组件来控制角色移动&#xff0c;绑定脚本"PlayerControl"。 PlayerControl public class PlayerControl : MonoBehaviour {private CharacterController player;void Start(){p…