深度网络中softmax_loss、Smooth L1 loss计算以及反向传播推导

SSD目标函数分为两个部分:对应默认框的位置loss(loc)和类别置信度loss(conf)。定义x_{ij}^{p}=\left\{ 1,0 \right\}   为第i个默认框和对应的第j个ground truth box,相应的类别为p。目标函数定义为:

L(x,c,l,g)=\frac{1}{N}(L_{conf}(x,c)+\alpha L_{loc}(x,l,g) )

其中,N为匹配的默认框。如果N=0,loss为零。L_{conf} 为预测框l和ground truth box g的Smooth L1 loss,\alpha 值通过cross validation设置为1。

L_{loc} 定义如下:

其中,l为预测框,g为ground truth。(cx,cy)为补偿(regress to offsets)后的默认框(d)的中心,(w,h)为默认框的宽和高。


传统欧式距离损失函数如下式所示:

 

                       (f1)

 

它在 Logistic Regression 里其到的作用是讲线性预测值转化为类别概率:假设 (f2) 是第i 个类别的线性预测结果,带入Softmax 的结果其实就是先对每一个   exponential 变成非负,然后除以所有项之和进行归一化,现在每个 (f3)就可以解释成观察到的数据x  属于类别i 的概率,或者称作似然 (Likelihood)

然后 Logistic Regression 目标函数是根据最大似然原则来建立的,假设数据 x 所对应的类别为y,则根据我们刚才的计算最大似然就是要最大化Oy  的值 (通常是使用 negative log-likelihood 而不是 likelihood,也就是说最小化-log(oy)  的值,这两者结果在数学上是等价的。) Softmax-Loss 其实就是把两者结合到一起,只要把Oy  的定义展开即可

softmaxloss损失函数:

注意,这里的log代表ln的意思,即:=

                                 (f4)

其中,y为图像所属于的类别编号,是真实的标签值;z为图像所对应的数据,这个数据也是输入softmax层的数据这个数据是深度神经网络输出的数据比如如果我们要写一个 Logistic Regression 的 solver,那么因为要处理的就是这个东西,比较自然地就可以将整个东西合在一起来考虑,或者甚至将(f2)  的定义直接一起带进去然后对w  b  进行求导来得到 Gradient Descent update rule,例如我们之前介绍 Gradient Descent 的时候举的两类 Logistic Regression 的例子就是这样做的。

反过来,如果是在设计 Deep Neural Networks 的库,则可能会倾向于将两者分开来看待:因为 Deep Learning 的模型都是一层一层叠起来的结构,一个计算库的主要工作是提供各种各样的 layer,然后让用户可以选择通过不同的方式来对各种 layer 组合得到一个网络层级结构就可以了。比如用户可能最终目的就是得到各个类别的概率似然值,这个时候就只需要一个 Softmax Layer,而不一定要进行 Multinomial Logistic Loss 操作;或者是用户有通过其他什么方式已经得到了某种概率似然值,然后要做最大似然估计,此时则只需要后面的 Multinomial Logistic Loss 而不需要前面的 Softmax 操作。因此提供两个不同的 Layer 结构比只提供一个合在一起的 Softmax-Loss Layer 要灵活许多。从代码的角度来说也显得更加模块化。但是这里自然地就出现了一个问题:numerical stability

让我们回到 Softmax-Loss 层,由于该层没有参数,我们只需要计算向后传递的导数就可以了,此外由于该层是最顶层,所以不用使用 chain rule 就可以直接计算对于最终输出(loss)的导数。回忆一下我们刚才的 notationSoftmax-Loss 层合在一起的时候我们用(f5)  来表示,它有两个输入,一个是 true label ,直接来自于最底部的数据层,并且我们不需要对数据层做任何的 gradient descent 参数更新,所以我们不需要像那个输入进行 back propagation,但是另外一个输入z 则来自于下面的计算层,对于 Logistic Regression 或者普通的 DNNs 下面会是一个全连通的线性内积层,不过具体是什么我们也不需要关心,只要把 (f6) 计算出来丢给下面让他们自己去算后面的就好了。根据普通的微积分知识,我们很容易算出:

 

     ;

  

   K=1,2,…..m m类别; 

其中   Softmax-Loss 的中间步骤 Softmax 在 Forward Pass 的计算结果,k=1,…..,m,表示softmax的输入端口编号

 

求出之后,令,求出了zk输出端口应该呈现出来的值。应该进行调整的数量(f7)

                                 (f8)

// CPU反向传导
template <typename Dtype>
void SoftmaxWithLossLayer<Dtype>::Backward_cpu(const vector<Blob<Dtype>*>& top,
    const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom) {
  if (propagate_down[1]) {
    LOG(FATAL) << this->type()
               << " Layer cannot backpropagate to label inputs.";
  }
  if (propagate_down[0]) {
    Dtype* bottom_diff = bottom[0]->mutable_cpu_diff();
    const Dtype* prob_data = prob_.cpu_data();
    // 先将正向传导时计算的prob_数据(f(y_k))拷贝至偏导
    caffe_copy(prob_.count(), prob_data, bottom_diff);
    const Dtype* label = bottom[1]->cpu_data();
    int dim = prob_.count() / outer_num_;
    int count = 0;
    for (int i = 0; i < outer_num_; ++i) {
      for (int j = 0; j < inner_num_; ++j) {
        const int label_value = static_cast<int>(label[i * inner_num_ + j]);
        // 如果为忽略标签,则偏导为0
        if (has_ignore_label_ && label_value == ignore_label_) {
          for (int c = 0; c < bottom[0]->shape(softmax_axis_); ++c) {
            bottom_diff[i * dim + c * inner_num_ + j] = 0;
          }
        } else {
          // 计算偏导,预测正确的bottom_diff = f(y_k) - 1,其它不变
          bottom_diff[i * dim + label_value * inner_num_ + j] -= 1;//使用label直接找到预测正确的Zj
          ++count;
        }
      }
    }
    // top[0]->cpu_diff()[0] = 1.0,已在SetLossWeights()函数中初始化
    Dtype loss_weight = top[0]->cpu_diff()[0] /
                        get_normalizer(normalization_, count);
    // 将bottom_diff归一化
    caffe_scal(prob_.count(), loss_weight, bottom_diff);
  }
}

  • 1
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值