社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  机器学习算法

动手学习深度学习 | 2 预备知识-2.5 自动微分

GIS研发 • 8 月前 • 276 次点击  
2.5.1 一个简单的例子
2.5.2 非标量变量的反向传播
2.5.3 分离计算
2.5.4 Python控制流的梯度计算

https://www.bilibili.com/video/BV1CueXzdEmy?vd_source=2d1af2a9b2aa8124af12180f29fb55f6&spm_id_from=333.788.player.switch&p=17

补充:

1. 标量的反向传播
import numpy as np import torch 
# f(x) = a*x**2 + b*x + c的导数
# 创建需要求导的张量,requires_grad=True表示需要计算梯度x = torch.tensor(0.0, requires_grad=True)  # x需要被求导
# 创建常数张量(不需要求导,默认requires_grad=False)a = torch.tensor(1.0)b = torch.tensor(-2.0)c = torch.tensor(1.0)
# 定义函数 y = ax² + bx + cy = a*torch.pow(x,2) + b*x + c 
# 反向传播,计算梯度y.backward()
# 获取x的梯度值(即dy/dx在x=0处的值)dy_dx = x.gradprint(dy_dx)

数学原理

函数 f(x) = x² - 2x + 1 的导数是:

  • f'(x) = 2x - 2

当 x = 0 时:

  • f'(0) = 2×0 - 2 = -2

因此输出 tensor(-2.) 正确。

PyTorch自动求导机制

  1. 计算图构建:PyTorch会动态构建一个计算图,记录所有运算

  2. requires_grad=True:标记需要计算梯度的张量

  3. backward():自动计算所有requires_grad张量的梯度

  4. x.grad:存储计算得到的梯度值


2. 非标量的反向传播

import numpy as np import torch 
# f(x) = a*x**2 + b*x + c
x = torch.tensor([[0.0,0.0],[1.0,2.0]],requires_grad = True) # x需要被求导a = torch.tensor(1.0)b = torch.tensor(-2.0)c = torch.tensor(1.0)y = a*torch.pow(x,2) + b*x + c 
gradient = torch.tensor([[1.0,1.0],[1.0,1.0]])
print("x:\n",x)print("y:\n",y)y.backward(gradient = gradient)x_grad = x.gradprint("x_grad:\n",x_grad)

输出:x: tensor([[0., 0.],         [1., 2.]], requires_grad=True)y: tensor([[1., 1.],        [0., 1.]], grad_fn=)x_grad: tensor([[-2., -2.],        [ 0.,  2.]])

1.计算过程

x = [[0, 0],     [1, 2]]

2. 函数 f(x) = x² - 2x + 1 的计算

对每个元素应用函数:

  • f(0) = 0² - 2×0 + 1 = 1

  • f(0) = 1

  • f(1) = 1² - 2×1 + 1 = 0

  • f(2) = 2² - 2×2 + 1 = 1

所以输出y:

y = [[1, 1],     [0, 1]]

3. 导数 f'(x) = 2x - 2

对每个位置计算导数:

  • f'(0) = -2

  • f'(0) = -2

  • f'(1) = 0

  • f'(2) = 2

关键点:gradient参数

当输出不是标量时,需要传入一个与输出y形状相同的gradient参数作为"权重":

gradient = torch.tensor([[1.0, 1.0], [1.0, 1.0]])
这相当于计算:
y.backward(gradient) = sum(y * gradient) 的梯度

实际计算过程

实际上计算的是:
loss = y[0,0]*1 + y[0,1]*1 + y[1,0]*1 + y[1,1]*1gradient = d(loss)/dx
于gradient全为1,最终x.grad就是每个位置的导数:
x_grad = [[f'(0), f'(0)],           [f'(1), f'(2)]] = [[-2, -2], [0, 2]]

数学验证

  • 位置[0,0]: x=0, f'(0) = -2 ✓

  • 位置[0,1]: x=0, f'(0) = -2 ✓

  • 位置[1,0]: x=1, f'(1) = 0 ✓

  • 位置[1,1]: x=2, f'(2) = 2 ✓

3.非标量的反向传播可以用标量的反向传播实现
import numpy as np import torch 
# f(x) = a*x**2 + b*x + c
x = torch.tensor([[0.0,0.0],[1.0,2.0]],requires_grad = True) # x需要被求导a = torch.tensor(1.0)b = torch.tensor(-2.0)c = torch.tensor(1.0)y = a*torch.pow(x,2) + b*x + c 
gradient = torch.tensor([[1.0,1.0],[1.0,1.0]])z = torch.sum(y*gradient)
print("x:",x)print("y:",y)z.backward()x_grad = x.gradprint("x_grad:\n",x_grad)

输出:x: tensor([[0., 0.],        [1., 2.]], requires_grad=True)y: tensor([[1., 1.],        [0., 1.]], grad_fn=)x_grad: tensor([[-2., -2.],        [ 0.,  2.]])
参考:https://download.csdn.net/blog/column/9886176/108303645
动手学习深度学习 | 2 预备知识-2.4 微积分
动手学习深度学习 | 2 预备知识-2.3 线性代数
动手学习深度学习 | 2 预备知识-2.1 数据操作 2.2 数据预处理
动手学习深度学习 | 安装

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/193183