《动手学深度学习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 torch

x = 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 * 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.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 c

a = torch.randn(size=(), requires_grad=True)
d = f(a)
d.backward()

a.grad == d / a
# tensor(True)

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

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

相关推荐
软件算法开发3 小时前
基于LSTM深度学习的网络流量测量算法matlab仿真
深度学习·matlab·lstm·网络流量测量
先做个垃圾出来………3 小时前
PyTorch 模型文件介绍
人工智能·pytorch·python
幂简集成4 小时前
通义灵码 AI 程序员低代码 API 课程实战教程
android·人工智能·深度学习·神经网络·低代码·rxjava
Learn Beyond Limits5 小时前
Error metrics for skewed datasets|倾斜数据集的误差指标
大数据·人工智能·python·深度学习·机器学习·ai·吴恩达
我不是小upper5 小时前
一文详解深度学习中神经网络的各层结构与功能!
人工智能·pytorch·深度学习
Niuguangshuo5 小时前
深度学习:Dropout 技术
人工智能·深度学习
LLM精进之路5 小时前
美团发布 | LongCat-Flash最全解读,硬刚GPT-4.1、Kimi!
人工智能·深度学习·机器学习·语言模型·transformer
DreamLife☼5 小时前
工业领域 ACP 协议全解析:从入门到实战案例
网络·安全·ai·工业·行为·acp·管控
DatGuy6 小时前
Week 15: 深度学习补遗:集成学习初步
人工智能·深度学习·集成学习