当前位置: 首页 > news >正文

神经网络中 标量求导和向量求导

0. 引出问题

在神经网络反向传播过程中 loss = [loss₁,loss₂, loss₃],为什么 ∂loss/∂w

∂loss₁/∂w 
∂loss₂/∂w
∂loss₃/∂w 

∂loss₁/∂w 和 loss 维度一样都是三位向量 ,[∂loss₁/∂w, ∂loss₂/∂w, ∂loss₃/∂w] 就变成3*3的矩阵
如下所示:

import torchw = torch.tensor([1.0, 2.0,3.0], requires_grad=True)
loss = w * 3  
print("loss: \n", loss)loss_m = []for i, val in enumerate(loss):w.grad = None  # 清零val.backward(retain_graph=True)print(f"∂loss{i+1}/∂w = {w.grad}")loss_m.append(w.grad.clone())print("loss_m: \n", torch.stack(loss_m))

输出结果:

loss: tensor([3., 6., 9.], grad_fn=<MulBackward0>)∂loss1/∂w = tensor([3., 0., 0.])
∂loss2/∂w = tensor([0., 3., 0.])
∂loss3/∂w = tensor([0., 0., 3.])loss_m: tensor([[3., 0., 0.],[0., 3., 0.],[0., 0., 3.]])

loss: tensor([3., 6., 9.]) 为向量,对w求导时为矩阵
但是 w.grad 必须 是标量或张量,不能是向量矩阵

1. 标量求导

import torchw = torch.tensor([1.0, 2.0,3.0], requires_grad=True)
loss = w * 3  
print("loss: \n", loss)loss_m = []
# 方法1:分别计算
for i, val in enumerate(loss):w.grad = None  # 清零val.backward(retain_graph=True)print(f"∂loss{i+1}/∂w = {w.grad}")loss_m.append(w.grad.clone())print("loss_m: \n", torch.stack(loss_m))grads = torch.autograd.grad(loss.sum(), w,retain_graph=True)
print("grads: \n", grads)  grads1 = torch.autograd.grad(loss.mean(), w)[0]
print("grads1: \n", grads1) 

输出;

loss: tensor([3., 6., 9.], grad_fn=<MulBackward0>)
∂loss1/∂w = tensor([3., 0., 0.])
∂loss2/∂w = tensor([0., 3., 0.])
∂loss3/∂w = tensor([0., 0., 3.])
loss_m: tensor([[3., 0., 0.],[0., 3., 0.],[0., 0., 3.]])
grads: (tensor([3., 3., 3.]),)
grads1: tensor([1., 1., 1.])

同样的例子:

import torch# 3个样本的真实数据
x = torch.tensor([[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]], requires_grad=True)
y_true = torch.tensor([1.0, 2.0, 3.0])# 线性模型:y = w₁x₁ + w₂x₂
w = torch.tensor([0.5, 0.5], requires_grad=True)
predictions = (x @ w)  # [1.5, 3.5, 5.5]
print("预测值:", predictions)
# 计算每个样本的梯度
individual_grads = []
for i in range(3):loss = (predictions[i] - y_true[i])**2loss.backward(retain_graph=True)individual_grads.append(w.grad.clone())w.grad.zero_()print("样本1梯度:", individual_grads[0]) 
print("样本2梯度:", individual_grads[1])  
print("样本3梯度:", individual_grads[2])  # 标量梯度:自动综合
total_loss = ((predictions - y_true)**2).mean()
total_loss.backward()# 验证:标量梯度 = 向量梯度的平均
manual_average = (individual_grads[0] + individual_grads[1] + individual_grads[2]) / 3print("手动平均:", manual_average)  
print("标量结果:", w.grad)  

输出结果:

预测值: tensor([1.5000, 3.5000, 5.5000], grad_fn=<MvBackward0>)
样本1梯度: tensor([1., 2.])
样本2梯度: tensor([ 9., 12.])
样本3梯度: tensor([25., 30.])
手动平均: tensor([11.6667, 14.6667])
标量结果: tensor([11.6667, 14.6667])

训练神经网络是为了最小化整体损失,不是单独优化每个样本

# 实际训练:最小化平均损失
batch_loss = individual_losses.mean()  # 标量
batch_loss.backward()  # 得到平均梯度
optimizer.step()       # 朝平均最优方向更新

2. 什么时候需要向量梯度?

仅用于研究:分析样本敏感性

def compute_sample_gradients(model, x, y):"""仅用于分析,不用于训练"""grads = []for xi, yi in zip(x, y):model.zero_grad()pred = model(xi.unsqueeze(0))loss = ((pred - yi) ** 2)loss.backward()grads.append(model.weight.grad.clone())return grads  # 每个样本的单独梯度
http://www.xdnf.cn/news/1338931.html

相关文章:

  • 如何通过传感器选型优化,为设备寿命 “续航”?
  • 机器学习6
  • RootDB:一款开源免费的Web报表工具
  • 0821 sqlite3_get_table函数(数据库函数的补充)
  • Vue.js 中使用 Highcharts 构建响应式图表 - 综合指南
  • 遥感机器学习入门实战教程|Sklearn案例⑤:集成学习方法全览
  • Python学习-- 数据库和MySQL入门
  • CentOS 7常用国内源配置:阿里云、腾讯云、华为云、清华源
  • pycharm编译器如何快速掌握一个新模块的使用方法
  • JeeSite 快速开发平台:全能企业级快速开发解决方案
  • 【图像算法 - 20】慧眼识病:基于深度学习与OpenCV的植物叶子疾病智能识别系统
  • Python-Pandas GroupBy 进阶与透视表学习
  • 中国之路 向善而行 第三届全国自驾露营旅游发展大会在阿拉善启幕
  • Android14内核调试 - boot vendor_boot
  • 06高级语言逻辑结构到汇编语言之逻辑结构转换 for (...; ...; ...)
  • uni-app:实现文本框的自动换行
  • Android - 资源类型 MINE Type
  • 教育场景下禁用html5播放器拖动进度条的例子
  • 医疗信息化实战:引领医疗行业数字化转型实践
  • 华为AUTOSAR质量目标与开发实践
  • FCN网络结构讲解与Pytorch逐行讲解实现
  • Go语言中的迭代器模式与安全访问实践
  • open3d-点云函数:变换:旋转,缩放、平移,齐次变换(R,T)等
  • 开源,LangExtract-Python库用LLM从非结构化文本提取结构化信息
  • 移动应用抓包与调试实战 Charles工具在iOS和Android中的应用
  • 自然语言处理——04 注意力机制
  • 基于Spring Cloud Gateway动态路由与灰度发布方案对比与实践指导
  • 记一次 .NET 某光谱检测软件 内存暴涨分析
  • CentOS7安装部署PostgreSQL
  • 搭建FTP文件共享服务器