深度网络中softmax_loss、Smooth L1 loss计算以及反向传播推导
2017-07-20 10:18
323 查看
SSD目标函数分为两个部分:对应默认框的位置loss(loc)和类别置信度loss(conf)。定义
为第i个默认框和对应的第j个ground
truth box,相应的类别为p。目标函数定义为:
其中,N为匹配的默认框。如果N=0,loss为零。
为预测框
和ground
truth box
的Smooth L1 loss,
值通过cross
validation设置为1。
定义如下:
其中,
为预测框,
为ground
truth。
为补偿(regress to offsets)后的默认框(
)的中心,
为默认框的宽和高。
传统欧式距离损失函数如下式所示:
(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)的导数。回忆一下我们刚才的 notation,Softmax-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)
为第i个默认框和对应的第j个ground
truth box,相应的类别为p。目标函数定义为:
其中,N为匹配的默认框。如果N=0,loss为零。
为预测框
和ground
truth box
的Smooth L1 loss,
值通过cross
validation设置为1。
定义如下:
其中,
为预测框,
为ground
truth。
为补偿(regress to offsets)后的默认框(
)的中心,
为默认框的宽和高。
传统欧式距离损失函数如下式所示:
(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)的导数。回忆一下我们刚才的 notation,Softmax-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() << " Lay a3da er 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); } }
相关文章推荐
- 深度学习torch之三(神经网络的前向传播和反向传播以及损失函数的基本操作)
- 深度学习: smooth L1 loss 计算
- 卷积神经网络(二):Softmax损失以及反向传播导数推导
- 深度卷积神经网络学习笔记2:步长不为1的卷积前向传播和反向传播
- 深度学习:神经网络中的前向传播和反向传播算法推导
- TensorFlow 深度学习框架 (2)-- 反向传播优化神经网络
- softmax 损失函数以及梯度推导计算
- caffe loss以及正则项反向传播过程
- TensorFlow 深度学习框架 (2)-- 反向传播优化神经网络
- TensorFlow 深度学习框架 (2)-- 反向传播优化神经网络
- C++从零实现深度神经网络之二——前向传播和反向传播
- TensorFlow 深度学习框架 (2)-- 反向传播优化神经网络
- TensorFlow 深度学习框架 (2)-- 反向传播优化神经网络
- 【机器学习】反向传播神经网络推导
- TensorFlow 深度学习框架 (2)-- 反向传播优化神经网络
- TensorFlow 深度学习框架 (2)-- 反向传播优化神经网络
- TensorFlow 深度学习框架 (2)-- 反向传播优化神经网络
- 全连接神经网络的前向和反向传播推导
- 神经网络中的反向传播法算法推导及matlab代码实现
- 神经网络基础和反向传播推导