(1) softmax loss

<1> softmax loss的函数形式为:

    (1)

zi为softmax的输入,f(zi)为softmax的输出。

<2> softmax loss对其输入zj求导:

     (2)

如果j==k,则zk是变量,否则zj是变量。

和的导数等于导数的和,对和中某个元素求导的话有:

(2) softmax_loss_layer.cpp中的Forward_cpu()函数:

 template <typename Dtype>
void SoftmaxWithLossLayer<Dtype>::Forward_cpu(
const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) {
// The forward pass computes the softmax prob values.
//调用softmax层的forward函数,得到对应的输出,存到prob_中
softmax_layer_->Forward(softmax_bottom_vec_, softmax_top_vec_);
const Dtype* prob_data = prob_.cpu_data();
//一般loss层有两个输入blob,网络的predict blob(bottom[0])和label blob(bottom[1])
const Dtype* label = bottom[]->cpu_data();
//dim = N*C*H*W / N = C*H*W
int dim = prob_.count() / outer_num_;
//count变量是计算loss时的有效样本数
int count = ;
Dtype loss = ;
for (int i = ; i < outer_num_; ++i) {
for (int j = ; j < inner_num_; j++) {
//读取label
const int label_value = static_cast<int>(label[i * inner_num_ + j]);
//如果该样本的label等于deploy中softmaxWithLoss中设定的参数ignore_label_,则该样本不参与前向和后向计算
if (has_ignore_label_ && label_value == ignore_label_) {
continue;
}
//判断label_value是否大于等于0
DCHECK_GE(label_value, );
//判断label_value是否小于prob_.shape(softmax_axis_)=C
DCHECK_LT(label_value, prob_.shape(softmax_axis_));
//对于softmax的输出channel,计算label_value索引对应的channel中prob的log.对应公式(1)
loss -= log(std::max(prob_data[i * dim + label_value * inner_num_ + j],
Dtype(FLT_MIN)));
//有效样本数加一
++count;
}
}
//最终在训练日志中显示的loss为计算的总loss除以有效样本数
top[]->mutable_cpu_data()[] = loss / get_normalizer(normalization_, count);
if (top.size() == ) {
top[]->ShareData(prob_);
}
}

(3) softmax_loss_layer.cpp中的Backward_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[]) {
LOG(FATAL) << this->type()
<< " Layer cannot backpropagate to label inputs.";
}
if (propagate_down[]) {
Dtype* bottom_diff = bottom[]->mutable_cpu_diff();
const Dtype* prob_data = prob_.cpu_data();
//将softmax的输出prob_复制给bottom[0]的diff(梯度) blob
caffe_copy(prob_.count(), prob_data, bottom_diff);
const Dtype* label = bottom[]->cpu_data();
int dim = prob_.count() / outer_num_;
int count = ;
for (int i = ; i < outer_num_; ++i) {
for (int j = ; j < inner_num_; ++j) {
const int label_value = static_cast<int>(label[i * inner_num_ + j]);
if (has_ignore_label_ && label_value == ignore_label_) {
for (int c = ; c < bottom[]->shape(softmax_axis_); ++c) {
bottom_diff[i * dim + c * inner_num_ + j] = ;
}
} else {
//对应公式(2),在反传梯度时,label索引对应的diff减1,其他不变。
bottom_diff[i * dim + label_value * inner_num_ + j] -= ;
++count;
}
}
}
// Scale gradient
//top[0]->cpu_diff()[0] = N
//N / count
Dtype loss_weight = top[]->cpu_diff()[] /
get_normalizer(normalization_, count);
caffe_scal(prob_.count(), loss_weight, bottom_diff);
}
}

最新文章

  1. 一步一步搭框架(asp.netmvc+easyui+sqlserver)-03
  2. 重温WCF之WCF传输安全(十三)(2)基于SSL的WCF匿名客户端(转)
  3. SQL Server技术问题之游标优缺点
  4. 学习Android,最简单的按钮提示文本信息
  5. .net平台下socket异步通讯(代码实例)
  6. javascript 事件响应
  7. Selenium+Python进行web自动化测试(Demo+API)
  8. vscode 添加 includePath
  9. ES7的新特性
  10. golang BDD testcase framework.
  11. java修饰符用法
  12. 关于Spring Security中无Session和无状态stateless
  13. scp拷贝文件报错-bash: scp: command not found
  14. 使用Vmware安装linux且配置终端可以连接虚拟机总结
  15. vue.js权威指南----代码解释实例
  16. layui的分页
  17. 【洛谷 P1501】 [国家集训队]Tree II(LCT)
  18. 【hdoj_2100】Lovekey(大数+字符处理)
  19. percona xtradb cluster test
  20. 第一次课堂作业---circle

热门文章

  1. apache ignite系列(九):使用ddl和dml脚本初始化ignite并使用mybatis查询缓存
  2. Ubuntu 14.04 java环境安装配置(不是openJAVA)
  3. centos7 下安装mysql5.7 数据库并使用nevicat连接数据库
  4. 让Samba支持Windows10的自动发现
  5. Hive导入数据到HBase,再与Phoenix映射同步
  6. centos C++ ccache llvm编译环境配置
  7. ssh免密码登陆(集群多台机器之间免密码登陆)
  8. 微服务SpringCloud之注册中心Consul
  9. Hadoop 文件系统命令行基础
  10. python语言程序设计基础 习题 天天向上的力量(math.pow)