Loss及其梯度

部署运行你感兴趣的模型镜像

一、Loss及其梯度

一、常见的Loss函数类型

  1. Mean squared error(均方差,mse)
    1. 基本形式
      1. loss=∑[y−fθ(x)]2loss=\sum[y-f_\theta(x)]^2loss=[yfθ(x)]2
      2. L2−norm=∣∣y−fθ(x)∣∣2L2-norm=||y-f_\theta(x)||_2L2norm=yfθ(x)2
      3. loss=norm(y−fθ(x))2loss=norm(y-f_\theta(x))^2loss=norm(yfθ(x))2
    2. mse求导
      ▽loss▽θ=2∗∑[y−fθ(x)]∗▽fθ(x)▽θ \frac{\triangledown loss}{\triangledown \theta}=2*\sum{\left[ y-f_{\theta}\left( x \right) \right]}*\frac{\triangledown f_{\theta}\left( x \right)}{\triangledown \theta} θloss=2[yfθ(x)]θfθ(x)
  2. Cross Entropy Loss(交叉熵)
    1. 可用于二分类(binary)和多分类(multi-class)问题
    2. 使用时常与softmax搭配使用

二、使用Pytorch自动求导

1、autograd.grad函数使用

  1. torch.autograd.grad(mse,[w])
    1. mse:给出的值
    2. [w]:自变量,切记requires_grad=True
      1. 可以使用w.requires_grad_(True)修改。
      2. 可以在生成的时候设置requires_grad=True
  2. 相关代码
# 以f(x) = xw+b 为例
# x初始值为1,w为dim=1、值为2的tensor,b假设为0
#----------------------------------------------------------------------------------
x = torch.ones(1)
w = torch.full([1],2)
mse = F.mse_loss(torch.ones(1),x*w) # 第一个参数给的是pred值,第二个参数给的是label值
w.requires_grad_(True) #告诉pytorch需要梯度信息
mse=F.mse_loss(torch.ones(1),x*w) #静态图需要更新信息
#----------------------------------------------------------------------------------
print("mse = ",mse)
print("grad = ",torch.autograd.grad(mse,[w]))
# 输出: mse =  tensor(1.)
# 输出:grad =  (tensor([2.]),)

2、loss.backward函数使用

  1. F.mse_loss(pred,label):求解出mse的值
    1. pred:是预测值
    2. label:是真实计算出的参数
  2. w.backward() :反向传播求出梯度
  3. 相关代码
# 以f(x) = xw+b 为例
# x初始值为1,w为dim=1、值为2的tensor,b假设为0
#----------------------------------------------------------------------------------
x = torch.ones(1)
w = torch.full([1],2,requires_grad=True)
mse = F.mse_loss(torch.ones(1),x*w)
mse.backward()
grad = w.grad
#----------------------------------------------------------------------------------
print("mse = ",mse)
print("grad = ",grad)
# mse =  tensor(1., grad_fn=<MeanBackward0>)
# grad =  tensor([2.])

三、Softmax激活函数

1、soft version of max简介

  1. 在深度学习中,softmax在多分类的场景中使用广泛。他讲一些输入映射为[0-1]之间的实数,并且归一化保证和为1。

2、Softmax定义:

  1. 函数:
    S(yi)=eyi∑jeyj S\left( y_i \right) =\frac{e^{y_i}}{\sum_j^{}{e^{yj}}} S(yi)=jeyjeyi
  2. 演示
    在这里插入图片描述

3、Softmax求导:

  1. i==j
    pi=∂eai∑k=1Neak p_i=\partial \frac{e^{a_i}}{\sum\nolimits_{k=1}^N{e^{a_k}}} pi=k=1Neakeai
    ∂pj∂aj=∂eai∑k=1Neak∂aj=eai(∑k=1Neak−eaj)(∑k=1Neak)2=eaj∑k=1Neak×(∑k=1Neak−eaj)∑k=1Neak=pi(1−pj) \frac{\partial p_j}{\partial a_j}=\frac{\partial \frac{e^{a_i}}{\sum\nolimits_{k=1}^N{e^{a_k}}}}{\partial a_j}=\frac{e^{a_i}\left( \sum\nolimits_{k=1}^N{e^{a_k}}-e^{a_j} \right)}{\left( \sum\nolimits_{k=1}^N{e^{a_k}} \right) ^2}=\frac{e^{a_j}}{\sum\nolimits_{k=1}^N{e^{a_k}}}\times \frac{\left( \sum\nolimits_{k=1}^N{e^{a_k}}-e^{a_j} \right)}{\sum\nolimits_{k=1}^N{e^{a_k}}}=p_i\left( 1-p_j \right) ajpj=ajk=1Neakeai=(k=1Neak)2eai(k=1Neakeaj)=k=1Neakeaj×k=1Neak(k=1Neakeaj)=pi(1pj)

  2. i!=j
    pi=∂eai∑k=1Neak p_i=\partial \frac{e^{a_i}}{\sum\nolimits_{k=1}^N{e^{a_k}}} pi=k=1Neakeai
    ∂pj∂aj=∂eai∑k=1Neak∂aj=0−eajeai(∑k=1Neak)2=−eaj∑k=1Neak×eai∑k=1Neak=−pj⋅pi \frac{\partial p_j}{\partial a_j}=\frac{\partial \frac{e^{a_i}}{\sum\nolimits_{k=1}^N{e^{a_k}}}}{\partial a_j}=\frac{0-e^{a_j}e^{a_i}}{\left( \sum\nolimits_{k=1}^N{e^{a_k}} \right) ^2}=\frac{-e^{a_j}}{\sum\nolimits_{k=1}^N{e^{a_k}}}\times \frac{e^{a_i}}{\sum\nolimits_{k=1}^N{e^{a_k}}}=-p_j·p_i ajpj=ajk=1Neakeai=(k=1Neak)20eajeai=k=1Neakeaj×k=1Neakeai=pjpi

  3. 公式合并

    ∂pj∂aj={pi(1−pj)  if  i=j−pj⋅pi            if  i≠j \frac{\partial p_j}{\partial a_j}=\begin{cases} p_i\left( 1-p_j \right) \,\, if\,\,i=j\\ -p_j·p_i\,\, \,\, \,\, \,\, \,\, \,\, if\,\,i\ne j\\ \end{cases} ajpj={pi(1pj)ifi=jpjpiifi=j

    1. 使用Kronecker delta
      δij={1    if  i=j0    if  i≠j \delta ij=\begin{cases} 1 \,\, \,\,if\,\,i=j\\ 0 \,\, \,\,if\,\,i\ne j\\ \end{cases} δij={1ifi=j0ifi=j
      ∂pi∂aj=pi(δij−pj) \frac{\partial p_i}{\partial a_j}=p_i\left( \delta _{ij}-p_j \right) ajpi=pi(δijpj)

4、Softmax函数及其求导:

a = torch.rand(3)
a.requires_grad_(True)
p = F.softmax(a,dim=0) #会自动完成建图操作
grad0 = torch.autograd.grad(p[0],[a],retain_graph=True) #必须是dim为1的
grad1 = torch.autograd.grad(p[1],[a],retain_graph=True)
grad2 = torch.autograd.grad(p[2],[a],retain_graph=True)

print("a = ",a)
print("p = ",p)
print("grad0 = ",grad0)
print("grad1 = ",grad1)
print("grad2 = ",grad2)
#-------------------------------------------------------------------------------
# a =  tensor([0.2260, 0.5295, 0.0540], requires_grad=True)
# p =  tensor([0.3128, 0.4238, 0.2634], grad_fn=<SoftmaxBackward>)
# grad0 =  (tensor([ 0.2150, -0.1326, -0.0824]),)
# grad1 =  (tensor([-0.1326,  0.2442, -0.1116]),)
# grad2 =  (tensor([-0.0824, -0.1116,  0.1940]),)

您可能感兴趣的与本文相关的镜像

PyTorch 2.5

PyTorch 2.5

PyTorch
Cuda

PyTorch 是一个开源的 Python 机器学习库,基于 Torch 库,底层由 C++ 实现,应用于人工智能领域,如计算机视觉和自然语言处理

<think>好的,我现在需要回答用户关于深度学习中未参与loss计算的参数的梯度更新情况的问题。首先,我得理解用户的问题到底是什么。用户想知道,如果某个参数在计算loss时没有被用到,那么这个参数在训练过程中会不会得到梯度更新。这个问题涉及到深度学习中的反向传播机制以及参数更新的原理。 接下来,我需要回忆一下深度学习的相关知识。在神经网络中,梯度是通过反向传播算法计算的。反向传播是基于链式法则,从loss开始,逐层向后计算每个参数的梯度。如果某个参数在前向传播的过程中没有被使用到,那么它就不会对最终的loss产生任何影响,因此在反向传播时,这个参数的梯度就无法被计算出来,也就是梯度为0或者不存在。这样的话,在参数更新的步骤中,比如使用SGD或者Adam优化器时,这个参数就不会被更新,保持初始化的值不变。 但是,可能存在一些特殊情况需要考虑。例如,在某些复杂的网络结构中,参数可能间接地影响loss,但用户的问题明确说是“未参与loss计算”,所以应该排除这种情况。还有一种情况是,如果参数虽然不直接影响loss,但通过其他途径间接影响,比如在GAN中的生成器参数可能通过判别器间接影响loss,但这时候生成器的参数其实是参与到了loss计算中的,所以这种情况也不属于用户的问题范畴。 然后,我需要验证这些思考是否正确。比如,可以举一个简单的例子:假设有一个神经网络,其中某一层的权重参数在前向传播时没有被使用到,那么这个参数在计算loss时自然不会被涉及到。在反向传播时,由于该参数没有参与前向计算,所以其梯度不会被计算,也就无法更新。这个例子应该能说明问题。 同时,用户提供的引用中有提到关于参数更新的内容,比如引用3中提到了手工计算参数更新的步骤,包括前向传播、计算损失、反向传播梯度等步骤。如果参数未参与前向传播,那么在第7步计算Δw和Δb时,这些参数的梯度自然无法得到,因此不会被更新。这进一步支持了我的理解。 另外,引用4中讨论了loss及其梯度计算,特别是关于softmax函数的梯度计算。虽然这主要是关于参与loss计算的参数的梯度推导,但反过来,如果参数不参与loss计算,那么这些推导中的相关项就不会存在,导致梯度为零。 可能还需要考虑一些框架实现的问题,比如在PyTorch或TensorFlow中,如果参数没有被包含在计算图中,那么框架会自动忽略这些参数的梯度计算。例如,在PyTorch中,如果一个参数没有被任何涉及到loss计算的操作所使用,那么该参数的grad属性会保持为None,或者在反向传播时不会被计算,因此在优化器更新时也不会被改变。 但是,用户的问题可能还涉及到更复杂的情况,比如参数是否属于某个模块,但未被当前使用的loss函数所涉及。比如,在多任务学习中,可能存在多个子网络,每个子网络对应不同的loss。如果某个子网络的参数在某个任务中没有被使用,那么在该任务的loss计算中,这些参数不会得到梯度更新。但如果是多任务联合训练,所有参数可能都会被不同的loss所涉及,这时候情况又会不同。但用户的问题比较明确,是“未参与loss计算”,所以应该指完全未被任何loss计算涉及的参数。 总结一下,未参与loss计算的参数在反向传播时不会得到梯度,因此不会被更新。这样的参数在训练过程中将保持初始值,可能影响模型的性能,因为它们没有根据数据进行调整。在实际应用中,需要确保所有需要训练的参数都被正确地包含在计算图中,并且参与到loss计算中,以便优化器能够更新它们。 最后,我需要将以上思考整理成结构清晰的回答,并生成相关问题。同时,检查是否需要引用提供的资料。例如,引用3提到了参数更新的步骤,可以引用来说明梯度计算的过程。引用4关于梯度计算也可以作为支持,说明如果参数未参与,则梯度无法计算。因此,在回答中适当加入这些引用,以增强可信度。</think>在深度学习中,未参与loss计算的参数确实会导致梯度不更新。具体原因及机制如下: ### 梯度更新的核心逻辑 1. **梯度计算依赖计算图** 反向传播通过自动微分机制建立的计算图进行梯度计算。只有参与loss计算的参数才会在计算图中形成连接路径,从而获得有效梯度值。未参与loss计算的参数在计算图中处于"孤立"状态,无法获得梯度更新信号[^3]。 2. **数学推导验证** 假设参数$w$未参与前向传播计算,则: $$ \frac{\partial \mathcal{L}}{\partial w} = \frac{\partial \mathcal{L}}{\partial y} \cdot \frac{\partial y}{\partial w} = \frac{\partial \mathcal{L}}{\partial y} \cdot 0 = 0 $$ 这意味着优化器执行`w = w - η·0`时,参数值保持不变[^4]。 3. **框架实现验证** 以PyTorch为例,通过监控参数的`requires_grad`属性和`grad`属性可验证: ```python import torch w = torch.randn(3, requires_grad=True) # 定义参数 y = torch.tensor(0) # 未使用w的计算 loss = y.sum() loss.backward() print(w.grad) # 输出:None ``` ### 特殊场景分析 | 场景类型 | 梯度表现 | 典型示例 | |---------|---------|---------| | 直接未参与计算 | 梯度为0 | 定义但未使用的网络分支参数 | | 间接参与计算 | 梯度正常 | GAN中生成器参数通过判别器间接影响loss | | 条件参与计算 | 梯度间歇更新 | 动态网络中选择性激活的模块参数 | ### 工程实践建议 1. 使用网络可视化工具(如TensorBoard)检查计算图连接 2. 监控参数更新统计量(如权重变化量标准差) 3. 对冻结参数显式设置`requires_grad=False`以提高效率[^3] ### 典型问题排查流程 ```mermaid graph TD A[参数未更新] --> B{检查计算图连接} B -->|未连接| C[修正网络结构] B -->|已连接| D{检查梯度值} D -->|梯度为0| E[检查激活函数/初始化] D -->|梯度正常| F[检查优化器配置] ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值