当前位置: 首页 > backend >正文

《动手学深度学习v2》学习笔记 | 2.4 微积分 2.5 自动微分

写在前面

本文为《动手学深度学习v2》的学习笔记。本着自己学习、分享他人的态度,分享学习笔记,希望能对大家有所帮助。


本文为同步更新版本,文章格式可能存在问题,建议阅读以下版本:

《动手学深度学习v2》学习笔记-合集https://mp.weixin.qq.com/mp/appmsgalbum?__biz=MzkwMjM0MzA5MA==&action=getalbum&album_id=3180615146931748866#wechat_redirect

目录

  • 2.4 微积分

    • 2.4.1 导数和微分

    • 2.4.2 偏导数

    • 2.4.3 梯度

    • 2.4.4 链式法则

  • 2.5 自动微分

    • 2.5.1 一个简单的例子

    • 2.5.2 非标量变量的反向传播

    • 2.5.3 分离计算

    • 2.5.4 Python控制流的梯度计算

2.4 微积分

参考资料:
视频:https://www.bilibili.com/video/BV1eZ4y1w7PY
教材:https://zh.d2l.ai/chapter_preliminaries/calculus.html#sec-calculus

标量导数:

图片

向量导数:

图片

图片

矩阵导数:

图片

2.4.1 导数和微分

假设我们有一个函数 ,其输入和输出都是标量。如果  的导数存在,这个极限被定义为

如果  存在,则称  在  处是可微(differentiable)的。

对于导数的表示,以下是等价的:

2.4.2 偏导数

设  是一个具有  个变量的函数。 关于第  个参数  的偏导数(partial derivative)为:

为了计算 ,我们可以简单地将  看作常数,并计算  关于  的导数。对于偏导数的表示,以下是等价的:

2.4.3 梯度

我们可以连结一个多元函数对其所有变量的偏导数,以得到该函数的梯度(gradient)向量。 具体而言,设函数  的输入是一个  维向量 ,并且输出是一个标量。函数  相对于  的梯度是一个包含  个偏导数的向量:

其中  通常在没有歧义时被  取代。

2.4.4 链式法则

链式法则可以被用来微分复合函数。

让我们先考虑单变量函数。假设函数  和  都是可微的,根据链式法则:

现在考虑一个更一般的场景,即函数具有任意数量的变量的情况。假设可微分函数  有变量 ,其中每个可微分函数  都有变量 。注意, 是 , 的函数。对于任意 ,链式法则给出:

2.5 自动微分

参考资料:
视频:https://www.bilibili.com/video/BV1KA411N7Px
教材:https://zh.d2l.ai/chapter_preliminaries/autograd.html#sec-autograd

向量链式法则:

图片

计算图:

图片

自动求导:

图片

2.5.1 一个简单的例子

假设我们想对函数  关于列向量  求导

首先,我们创建变量x并为其分配一个初始值。

import torchx = torch.arange(4.0)
x
# tensor([0., 1., 2., 3.])

在我们计算  关于  的梯度之前,需要一个地方来存储梯度。

x.requires_grad_(True)  # 等价于 x=torch.arange(4.0,requires_grad=True)
x.grad  # 默认值是 None

现在计算 ,x是一个长度为4的向量,计算xx的点积,得到了我们赋值给y的标量输出。

y = 2 * torch.dot(x, x)
y
# tensor(28., grad_fn=<MulBackward0>)

通过调用反向传播函数 backward() 来自动计算y关于x每个分量的梯度

y.backward()
x.grad
# tensor([ 0.,  4.,  8., 12.])

函数  关于  的梯度应为 。让我们快速验证这个梯度是否计算正确。

x.grad == 4 * x
# tensor([True, True, True, True])

现在计算x的另一个函数。

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

2.5.2 非标量变量的反向传播

深度学习中,我们的目的不是计算微分矩阵,而是单独计算批量中每个样本的偏导数之和。

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

2.5.3 分离计算

将某些计算移动到记录的计算图之外

x.grad.zero_()
y = x * x
u = y.detach()
z = u * xz.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.5.4 Python控制流的梯度计算

即使构建函数的计算图需要通过Python控制流(例如,条件、循环或任意函数调用),我们仍然可以计算得到的变量的梯度

deff(a):b = a * 2
while b.norm() < 1000:b = b * 2
if b.sum() > 0:c = b
else:c = 100 * b
return ca = torch.randn(size=(), requires_grad=True)
d = f(a)
d.backward()a.grad == d / a
# tensor(True)

--------------- 结束 ---------------

注:本文为个人学习笔记,仅供大家参考学习,不得用于任何商业目的。如有侵权,请联系作者删除。

http://www.xdnf.cn/news/20246.html

相关文章:

  • 深度学习——PyTorch保存模型与调用模型
  • JUC之并发编程
  • MyBatis入门到精通:CRUD实战指南
  • 使用UniApp实现下拉框和表格组件页面
  • Android Kotlin 动态注册 Broadcast 的完整封装方案
  • uv教程 虚拟环境
  • kotlin - 2个Fragment实现左右显示,左边列表,右边详情,平板横、竖屏切换
  • 【LeetCode 每日一题】2348. 全 0 子数组的数目
  • 开源OpenHarmony润开鸿HH-SCDAYU800A开发板开箱体验
  • AI热点周报(8.31~9.6): Qwen3‑Max‑Preview上线、GLM-4.5提供一键迁移、Gemini for Home,AI风向何在?
  • C++进阶——继承(2)
  • 基于STM32的交通灯设计—紧急模式、可调时间
  • 如何理解`(line_status = parse_line()) == LINE_OK`?
  • @Autowired注解(二)
  • 【CAN通信】AUTOSAR架构下TC3xx芯片是如何将一帧CAN报文接收上来的
  • Xsens解码人形机器人训练的语言
  • 如何通过AI进行数据资产梳理
  • 43这周打卡——生成手势图像 (可控制生成)
  • 球坐标系下调和函数的构造:多项式边界条件的求解方法
  • linux Nginx服务配置介绍,和配置流程
  • 快手Keye-VL 1.5开源128K上下文+0.1秒级视频定位+跨模态推理,引领视频理解新标杆
  • 错误是ModuleNotFoundError: No module named ‘pip‘解决“找不到 pip”
  • vsan default storage policy 具体是什么策略?
  • HTB GoodGames
  • centos下gdb调试python的core文件
  • 串口通信的学习
  • 日内5%,总回撤10%:EagleTrader风控规则里,隐藏着什么核心考点?
  • 使用API接口获取淘宝商品详情数据需要注意哪些风险?
  • MySQL数据库精研之旅第十六期:深度拆解事务核心(上)
  • python + Flask模块学习 1 基础用法