Pytorch反向传播梯度始终为None

原因

可能在将需要求梯度的tensor放置在cuda上时出错,如

import torch

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

x = torch.rand(10, 3).to(device)
w = torch.rand(3, 1, requires_grad=True).to(device)
t = (x @ w).sum()
t.backward()
print(w.grad)

# return: None

错误原因:对需要求梯度的张量做了一次to(device)导致叶节点发生变化

一种处理方式如下:

# device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
device = torch.device('cpu')

torch.manual_seed(123)
x = torch.rand(10, 3).to(device)
w = torch.rand(3, 1, requires_grad=True)
w1 = w.to(device)
t = (x @ w1).sum()
t.backward()
print(w.grad)

# return: 
# tensor([[4.4321],
        [4.1784],
        [5.2859]])

这种方式看似work,实际上在写训练模块时,要将w1写在循环内,后续梯度求导就会出现问题,参数得不到更新

正确的处理方式

直接利用人家写好的接口就行啦,别花里胡哨的,.cuda() ,to(device)的。

import torch

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

torch.manual_seed(123)
x = torch.rand(10, 3).to(device)
w = torch.rand(3, 1, requires_grad=True, device=device)
t = (x @ w).sum()
t.backward()
print(w.grad)

# return:
# tensor([[4.4321],
         [4.1784],
         [5.2859]], device='cuda:0')

这样用就不会有什么问题了。

### PyTorch反向传播和自动求导的工作原理 #### 什么是反向传播反向传播是一种用于优化神经网络模型参数的重要方法。在这一过程中,通过计算损失函数相对于各个参数的偏导数来调整权重和其他可学习参数。这些导数值随后被用来更新模型参数,从而最小化目标损失函数[^2]。 #### 自动求导的作用 PyTorch 提供了一种强大的工具——自动求导机制,该机制可以自动生成并执行复杂的梯度计算过程。这种能力显著减轻了开发者手动推导复杂导数的任务负担,同时也提高了开发效率和准确性。具体来说,PyTorch 使用动态计算图结构支持前向传播阶段的操作记录,并基于此完成后续的反向传播运算[^1]。 #### 动态计算图的特点 不同于一些静态定义图形系统的框架(如早期版本 TensorFlow),PyTorch 构建了一个动态计算图。这意味着每次运行程序时都会重新创建一个新的计算图,这样就可以更方便地处理具有不同形状的数据或者涉及条件分支逻辑的情况。当我们在代码里执行某些 tensor 运算的时候,实际上就是在构建这张图的一部分节点及其连接关系;而一旦进入 backward() 方法调用,则会沿着已建立好的路径逆序遍历各层操作以累积所需的梯度信息[^4]。 #### 实现细节说明 以下是几个关键概念和技术要点: - **链式法则的应用** 在数学上利用多变量复合函数微分公式即所谓的“链式法则”,逐级累加局部变化率直至得到全局敏感程度指标。这是整个流程的核心理论依据之一[^3]。 - **张量属性 `.grad` 和 `requires_grad=True` 设置** 对于需要追踪历史以便参与梯度下降的学习对象而言,必须显式指定其 requires_grad 属性为 True 。之后每当此类 Tensor 发生改变后,系统便会同步维护关联的历史记录以及相应位置上的瞬时斜率值存储到 .grad 字段当中待查取使用。 - **关闭/开启 Autograd 功能** 如果存在部分中间结果仅作临时用途而不希望额外消耗内存保存冗余数据的话,可以通过上下文管理器 torch.no_grad 或者设置 detach 来暂时屏蔽掉这部分区域内的监控活动。 - **高维情况下的 Jacobian 向量积技巧** 特殊场景下如果只关心特定方向上的投影效果而非完整的 Hessian Matrix 表达形式,那么借助 PyTorch 内置接口可以直接高效获取所需成分组合成果,无需显式展开全部矩阵表达式再做乘法运算,有效节省资源开销[^5]。 ```python import torch # 示例:简单的线性回归模型演示如何运用 autograd 计算梯度 x = torch.tensor([1., 2., 3.], requires_grad=False).unsqueeze(-1) # 输入特征 y_true = torch.tensor([2., 4., 6.]) # 真实标签 w = torch.randn((1,), dtype=torch.float, requires_grad=True) # 初始化随机权值 w b = torch.zeros((1,), dtype=torch.float, requires_grad=True) # 初始偏差 b 设定为零 def model(x): return x @ w.t() + b # 定义预测方程 y_hat=f(x;θ) for epoch in range(10): predictions = model(x) # 正向传播获得估计输出 loss = ((predictions.squeeze()-y_true)**2).mean() # MSE Loss Function if w.grad is not None: # 清除之前的残差积累项以防叠加错误 w.grad.zero_() if b.grad is not None: b.grad.zero_() loss.backward() # 执行误差回传步骤填充 grad 成员变量内容 with torch.no_grad(): # 更新参数时不需继续跟踪新产生的依赖链条 step_size = 0.01 # 学习速率超参调节因子 w -= step_size * w.grad # 参数修正规则应用GD策略 b -= step_size * b.grad print(f'Final weights={w.item()}, bias={b.item()}') ``` 上述脚本展示了基本的一次迭代周期内正向推理、代价评估及反馈校准全过程的具体实现方式。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值