资讯动态

Python-pytorch-自动求导

发布时间:2026/8/18 5:16:46 来源:尧图企业网站定制
PyTorch 自动求导Autograd 什么是自动求导自动求导Autograd是 PyTorch 最核心的特性之一它自动计算神经网络中所有参数的梯度让你无需手动推导和实现反向传播。PyTorch 使用动态计算图——每次前向传播都构建一张新图这意味着你可以使用 Python 原生的控制流if/for/while模型结构可以在每次迭代中改变。 核心概念requires_gradimporttorch# 创建可求导的张量xtorch.tensor([1.0,2.0,3.0],requires_gradTrue)print(x.requires_grad)# True# 或者事后设置xtorch.tensor([1.0,2.0,3.0])x.requires_grad_(True)# 原地修改注意尾部 _requires_gradTrue告诉 PyTorch这个张量的所有运算都要被追踪以便后续计算梯度。 梯度计算基本流程# 1. 定义变量需要梯度xtorch.tensor([2.0,3.0],requires_gradTrue)# 2. 定义计算构建计算图yx**23*x1# y x² 3x 1# dy/dx 2x 3# 3. 调用 backward() 计算梯度y.sum().backward()# y 是向量需要转为标量# 4. 查看梯度print(x.grad)# tensor([7., 9.]) ← 2*237, 2*339 ✓为什么需要.sum()再backward()backward()只能对标量调用。如果y是向量/矩阵需要先将其转为标量求和、求均值等。xtorch.randn(3,requires_gradTrue)yx*2# ❌ y.backward() ← 报错y 是向量# ✅ y.sum().backward() ← 正确先转为标量# ✅ y.mean().backward() ← 也可以取均值 梯度计算原理xtorch.tensor([1.0,2.0,3.0],requires_gradTrue)wtorch.tensor([0.5,0.3,0.2],requires_gradTrue)btorch.tensor(0.1,requires_gradTrue)# 前向传播z(x*w).sum()b# 标量输出# 反向传播自动计算 dz/dx, dz/dw, dz/dbz.backward()print(fdz/dx:{x.grad})# w [0.5, 0.3, 0.2]print(fdz/dw:{w.grad})# x [1.0, 2.0, 3.0]print(fdz/db:{b.grad})# 1.0 梯度累积与清零 ⭐PyTorch 默认累加梯度而非覆盖这是为 RNN 等多步反向传播设计的。xtorch.tensor([2.0],requires_gradTrue)foriinrange(3):yx**2y.backward()print(fStep{i}: grad {x.grad})# Step 0: grad [4.] ← 2*2# Step 1: grad [8.] ← 累加4 4# Step 2: grad [12.] ← 再累加8 4# 正确做法每次迭代清空梯度xtorch.tensor([2.0],requires_gradTrue)foriinrange(3):yx**2y.backward()print(fStep{i}: grad {x.grad})x.grad.zero_()# ← 清零在实际训练中使用optimizer.zero_grad()一次性清空所有参数梯度。 禁用梯度追踪torch.no_grad()— 禁用梯度计算在推理、评估时使用减少内存占用、加速计算。xtorch.randn(10,requires_gradTrue)# 方式一: with 语句推荐withtorch.no_grad():yx*2print(y.requires_grad)# False# 方式二: 装饰器torch.no_grad()defevaluate(model,data):returnmodel(data).detach()— 从计算图中分离创建一个共享数据但不参与梯度计算的新张量。xtorch.tensor([2.0],requires_gradTrue)yx**2# y 4zy.detach()# z 是 4但不与 x 关联wz**2# 与 x 无关不会反向传播到 xset_grad_enabled()— 条件控制withtorch.set_grad_enabled(is_train):outputmodel(input)lossloss_fn(output,target)⛓️ 阻止对部分参数求导# 方式一: requires_gradFalsewtorch.randn(3,5,requires_gradFalse)# 不更新btorch.randn(5,requires_gradTrue)# 更新# 方式二: 冻结模型层forparaminmodel.features.parameters():param.requires_gradFalse# 冻结 backbone# 方式三: optimizer 只传部分参数optimizeroptim.Adam(filter(lambdap:p.requires_grad,model.parameters()),lr1e-4) 梯度信息查看与调试xtorch.tensor([[1.0,2.0],[3.0,4.0]],requires_gradTrue)y(x**2).sum()y.backward()print(x.grad)# tensor([[2., 4.], [6., 8.]])# 梯度相关属性print(x.grad_fn)# None叶子节点print(y.grad_fn)# SumBackward0 — y 是由 sum 得到的# 查看计算图print(x.is_leaf)# True用户直接创建的叶子节点leaf node用户直接创建而非运算结果的张量。只有叶子节点的.grad会在backward()后被填充。 retain_graph — 保留计算图默认backward()后计算图被释放。如果需要对同一个输出多次调用backward()xtorch.tensor([2.0],requires_gradTrue)yx**3# y 8y.backward(retain_graphTrue)print(x.grad)# 12 ← 3*2² 12y.backward(retain_graphTrue)print(x.grad)# 24 ← 累加到 1212 24注意梯度累加⚠️ 绝大多数情况下不需要retain_graphTrue。只在多任务学习、GAN 训练等少数场景用到。 高阶梯度PyTorch 支持计算梯度的梯度二阶导数。xtorch.tensor([2.0],requires_gradTrue)yx**3# y x³# 一阶导: dy/dx 3x² 12grad1torch.autograd.grad(y,x,create_graphTrue)[0]print(grad1)# tensor([12.])# 二阶导: d²y/dx² 6x 12grad2torch.autograd.grad(grad1,x)[0]print(grad2)# tensor([12.])使用create_graphTrue保留梯度计算图以便计算更高阶导数。⚠️ 常见错误与解决错误原因解决backward()报错输出不是标量先.sum()或.mean()grad为None没设requires_gradTrue创建时设置或调用.requires_grad_()grad值不对忘记清零梯度累加每次迭代前optimizer.zero_grad()内存不足保留了不必要的计算图用torch.no_grad()或.detach()inplace操作报错修改了需要梯度的叶子节点避免对需要梯度的张量做原地操作 速查表需求代码启用梯度x torch.tensor([1.], requires_gradTrue)反向传播loss.backward()查看梯度x.grad清零梯度x.grad.zero_()禁用梯度with torch.no_grad():分离张量x.detach()冻结参数param.requires_grad False获取梯度值torch.autograd.grad(loss, x)保留计算图loss.backward(retain_graphTrue)创建高阶图torch.autograd.grad(y, x, create_graphTrue)[[pytorch-总览|← 返回总览]]

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价