目标检测之Loss:softmaxLoss函数代码解读

本文详细介绍了Caffe框架中Softmax与SoftmaxWithLoss层的工作原理,包括Softmax层如何实现数值稳定性的计算、如何与Loss层结合计算分类损失,并解释了反向传播的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 在caffe中softmaxwithLoss是由两部分组成,softmax+Loss组成,其实主要就是为了caffe框架的可扩展性。


  表达式(1)是softmax计算表达式,(2)是sfotmaxLoss的计算损失表达。在caffe中是单独的计算每层的输入和输出,然后再进行向后传递data结果和向前传递diff的结果。

    caffe中softmax的计算:


      如上所示;在reshape阶段主要是进行相关参数维度的设定。softmax_axis主要是制定从哪个维度开始切,默认是1.后面主要是初始化了两个变量,sum_multiplier_和scale_局部变量的初始化。sum_multiplier_的形状是channel的大小,一般主要是通过矩阵乘法来实现每个feature map相对应的坐标数据进行相加或者相减或者其他的操作。scale通常情况下被用来当作临时的缓冲变量。这两个变量的使用在caffe中到处可见。接下来就是forward_cpu部分的代码。


      首先还是获取top和bottom的data,把bottom的data中的数据拷贝给top,以后就直接在top中进行计算。另外在caffe中,dim变量表示的C*W*H,spatial_dim 标识的是W*H。

      在上面首先是outer_num_样本数据中输入softmax的数据进行一个‘归一化’操作,大红色方框是为了找出当前instance中输入softmax的特征中的那个最大的数值,然后再减去那个最大数值防止产生数值计算方面的问题(例如在mnist数据集中,outer_num_是128代表的是batch的大小,inner_num_是1,这里的softmax前面链接的是inner product层,所以spatial_dim和inner_num的大小均为1,dim的大小是10,scale_data中其实也只有一个数,虽然caffe_copy之后有两行循环,其实由于inner_num是1,也就一行循环). 计算出最大的数值,然后把那个最大是数值乘以sum_multiplier_,就从1个数变成了C个数。继而做exp,把结果存放到topdata,然后把全部channel的数据求和(求和caffe使用矩阵和向量的乘法进行计算)存放到scale_data,形状是inner_num_,也就是W*H(其实就是1*1),最后就是除以求和结果啦。这么多的语句也就描述了表达式(1). 最主要的是考虑到了数值计算中存在的问题。

     下面就应该是softmaxWithLoss计算损失;


   上面是softmaxWithLoss的set函数,可以和很清楚地看到在初始化完成softmax_param这个参数之后,直接把type设置成了softmax,然后又通过工厂函数创建softmaxlayer,继而进行Set_up函数。可以看出softmaxWithLoss是内部创建了一个softmaxlayer。

    继续后面主要就是检查当前layer是否设定不对某个label进行计算Loss,也就是说,在mnist中有10个class,但是我只想对12345678进行分类,那就设定ignore_label为9.这个时候遇到标签是9的就不计算Loss。注意protobuf中没有设定默认的数值,has_xxx就返回false,只有设定了数值,才会true。后面的norm是为ignore服务的。

  接下来的reshape函数也没啥用处,就是设定了三个变量。softmax_axis_=1,outer_num_=128,inner_num_=1.需要注意的是outer_num_ * inner_num_必须和bottom[1]->count()给定的lable数相同。也就是说当softmax前面接inner product的时候,每个lable对应的是instance对应的类别(一个数),但是当softmax前面是卷积层的时候,每个label就不是一个数,而是一个矩阵,对应着每个 feature map中每个像素值的分类。下面就是计算Loss:


   这里寿面是计算softmax_layer_的forward函数,softmax_top_vec_其实是prob_的一个引用。prob_data的大小是N*C*1*1.static_cast<int>(label[i * inner_num_ + j])是从对应的instance中取出相对应的标签。如果当前的label和ignore label相同,那么就不计算Loss损失,这样就存在问题,假如128个instance中有10个不计算Loss,那么最终在计算Loss的平均的时候,是除以多少呢?这就用到了norm。count在这里统计我们计算了多少个instance的Loss数值。prob_data[i * dim + label_value * inner_num_ + j] dim是10,label_value是instance的标签来当作index来从prob中取数据(该instance的分类结果),j是0,因为W=H=1。


   get_normalizer在VAILD模式下会返回我们计算了多少个Loss的个数,也就是count。这个时候当前batch的Loss就已经放回到top[0]中去了。下一步要计算的就是Loss的反向传播。


### DFL (Distribution Focal Loss) 损失函数 DFL(Distribution Focal Loss)是一种用于目标检测中的回归任务的损失函数,特别适用于边界框预测。该损失函数通过引入分布的概念来改进传统的Focal Loss,在处理不平衡数据集方面表现出色。 #### 公式定义 DFL 的核心思想在于不仅关注最终预测值与真实值之间的差异,还考虑了预测值周围的概率分布情况。具体来说,对于一个离散化的边界框坐标 \( \hat{y} \),其对应的真值为 \( y \),那么 DFL 可以表示为: \[ \text{DFL}(p, y) = -\sum_{i=0}^{n-1} p_i(y) \log(\hat{p}_i) \] 其中: - \( n \) 是离散化后的类别数量; - \( p_i(y) \) 表示第 \( i \) 类别的理想分布权重,通常采用高斯分布或其他形式的概率密度函数计算得到; - \( \hat{p}_i \) 则是从模型输出经过softmax层转换后获得的实际预测概率向量; 此公式表明,当预测结果越接近于真实的分布时,损失会变得更小[^1]。 #### 含义解释 相比于传统的方法直接最小化均方误差(MSE)或平滑L1距离(smooth L1 loss),DFL 更加注重捕捉位置信息在整个空间内的相对关系。这样做可以使得网络学习到更加鲁棒的位置特征表达,并且有助于缓解正负样本极度不均衡带来的训练困难问题。此外,由于引入了分布概念,因此能够更好地适应不同尺度的目标物体定位需求[^2]。 ```python import torch.nn.functional as F def distribution_focal_loss(pred_dist, target_dist): """ 计算 Distribution Focal Loss 参数: pred_dist (Tensor): 预测的距离分布 [batch_size, num_classes] target_dist (Tensor): 真实的距离分布 [batch_size, num_classes] 返回: Tensor: 平均损失值 """ # 应用 softmax 获取预测概率分布 pred_prob = F.softmax(pred_dist, dim=-1) # 计算交叉熵并求平均 ce_loss = -(target_dist * torch.log(pred_prob)).mean() return ce_loss ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值