PyTorch深度学习框架60天进阶学习计划 - 第4天:自动微分系统
PyTorch深度学习框架60天进阶学习计划 - 第4天:自动微分系统!如果文章对你有帮助,还请给个三连好评,感谢感谢!
·
PyTorch深度学习框架60天进阶学习计划 - 第4天:自动微分系统
学习目标
理解
requires_grad属性传播机制
掌握计算图构建原理
熟练使用detach()和no_grad()控制梯度计算
实现自定义函数的自动微分
对比动态图与静态图模式差异
计算雅可比矩阵与二阶导数
目录
计算图与梯度传播原理
requires_grad属性工作机制
梯度计算控制技术
自定义函数微分实现
动态图与静态图对比
高阶导数计算实践
代码运行流程图
完整代码实现
梯度计算调试技巧
1. 计算图与梯度传播原理
PyTorch使用动态计算图记录张量操作,反向传播时自动计算梯度。
计算图结构示例
x = torch.tensor(2.0, requires_grad=True)
y = x 2
z = y + torch.exp(x)
节点关系:
x (requires_grad=True)
│
└─ y = x^2 (grad_fn=)
│
└─ z = y + e^x (grad_fn=)
梯度传播过程
z.backward()
print(x.grad) # 输出:2x + e^x = 22 + e^2 ≈ 4 + 7.389 = 11.389
2. requires_grad属性工作机制
属性传播规则表:
| 操作类型 | 输出张量requires_grad | 说明 |
|---|---|---|
| 新建张量 | 手动设置 | torch.tensor(..., requires_grad=True) |
| 数学运算 | 自动继承 | 任一输入为True则输出为True |
| in-place操作 | 保持原值 | 会破坏计算图,需谨慎使用 |
| 索引操作 | 自动继承 | 切片后的张量保留梯度信息 |
代码验证
a = torch.randn(3, requires_grad=True)
b = torch.ones(3)
c = a + b # c.requires_grad = True
d = c[1:] # d.requires_grad = True
print(c.requires_grad) # 输出:True
print(d.requires_grad) # 输出:True
3. 梯度计算控制技术
两种梯度控制方法对比:
| 方法 | 作用域 | 计算图影响 | 典型应用场景 |
|---|---|---|---|
| detach() | 单个张量 | 切断历史计算图 | 冻结网络部分参数 |
| no_grad() | 代码块 | 禁用全部梯度计算 | 模型推理/参数更新 |
detach()示例
x = torch.tensor(2.0, requires_grad=True)
y = x.detach() 2 # y的创建不记录计算历史
y.backward() # 会报错,因为y与x的计算图已断开
no_grad()示例
with torch.no_grad():
y = x 2 + 3*x # 不会构建计算图
z = y.mean()
z.backward() # 报错:在no_grad块内操作无法反向传播
4. 自定义函数微分实现
使用@torch.jit.script创建静态图函数:
动态图模式
def dynamic_sigmoid(x):
return 1 / (1 + torch.exp(-x))
x = torch.tensor([1.0], requires_grad=True)
y = dynamic_sigmoid(x)
y.backward()
print(x.grad) # 输出:sigmoid(1)*(1-sigmoid(1)) ≈ 0.1966
静态图模式
@torch.jit.script
def static_sigmoid(x: torch.Tensor) -> torch.Tensor:
return 1 / (1 + torch.exp(-x))
x = torch.tensor([1.0], requires_grad=True)
y = static_sigmoid(x)
y.backward()
print(x.grad) # 输出相同结果,但计算图被优化
5. 动态图与静态图对比
特性对比表:
| 特性 | 动态图(Eager Mode) | 静态图(Script Mode) |
|---|---|---|
| 调试难度 | 支持实时调试 | 需要编译后调试 |
| 计算优化 | 无优化 | 编译器自动优化 |
| 控制流 | 支持Python原生控制流 | 需使用TorchScript语法 |
| 部署能力 | 不可直接部署 | 可导出为独立模型 |
| 内存占用 | 较高 | 较低 |
6. 高阶导数计算实践
雅可比矩阵计算
def jacobian_example():
x = torch.tensor([1.0, 2.0], requires_grad=True)
y = torch.stack([x[0]2 + x[1], x[1]3])
jacobian = []
for i in range(y.size(0)):
grad = torch.autograd.grad(y[i], x, retain_graph=True)[0]
jacobian.append(grad)
return torch.stack(jacobian)
print(jacobian_example())
输出:tensor([[2., 1.],
[0., 12.]])
二阶导数计算
x = torch.tensor(3.0, requires_grad=True)
y = x3 + 2*x
一阶导
dy_dx = torch.autograd.grad(y, x, create_graph=True)[0]
二阶导
d2y_dx2 = torch.autograd.grad(dy_dx, x)[0]
print(dy_dx.item()) # 3*3² + 2 = 29
print(d2y_dx2.item()) # 6*3 = 18
7. 代码运行流程图
8. 完整代码实现
import torch
二阶导数计算示例
def higher_order_derivatives():
x = torch.tensor(2.0, requires_grad=True)
# 一阶计算
with torch.enable_grad():
y = x 3
dy_dx = torch.autograd.grad(y, x, create_graph=True)[0]
# 二阶计算
d2y_dx2 = torch.autograd.grad(dy_dx, x, retain_graph=True)[0]
return dy_dx.item(), d2y_dx2.item()
print(higher_order_derivatives()) # 输出:(12.0, 12.0)
9. 梯度计算调试技巧
常见问题排查表:
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| 梯度为None | 未设置requires_grad=True | 检查张量梯度属性 |
| 计算图丢失 | 使用in-place操作 | 改用非in-place方法 |
| 内存泄漏 | 未及时释放计算图 | 使用detach()或no_grad() |
| 梯度爆炸 | 学习率过大 | 添加梯度裁剪 |
| 梯度消失 | 网络层过深 | 使用残差连接 |
清华大学全三版的《DeepSeek教程》完整的文档需要的朋友,关注我私信:deepseek 即可获得。
怎么样今天的内容还满意吗?再次感谢朋友们的观看,关注GZH:凡人的AI工具箱,回复666,送您价值199的AI大礼包。最后,祝您早日实现财务自由,还请给个赞,谢谢!
火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。
更多推荐

所有评论(0)