#include <algorithm>
#include <cfloat>
#include <vector> #include "caffe/layers/softmax_loss_layer.hpp"
#include "caffe/util/math_functions.hpp" namespace caffe { template <typename Dtype>
__global__ void SoftmaxLossForwardGPU(const int nthreads,
const Dtype* prob_data, const Dtype* label, Dtype* loss,
const int num, const int dim, const int spatial_dim,
const bool has_ignore_label_, const int ignore_label_,
Dtype* counts) {
CUDA_KERNEL_LOOP(index, nthreads) {
const int n = index / spatial_dim;
const int s = index % spatial_dim;
const int label_value = static_cast<int>(label[n * spatial_dim + s]);
if (has_ignore_label_ && label_value == ignore_label_) {
loss[index] = ;
counts[index] = ;
} else {
loss[index] = -log(max(prob_data[n * dim + label_value * spatial_dim + s],
Dtype(FLT_MIN)));
counts[index] = ;
}
}
} template <typename Dtype>
void SoftmaxWithLossLayer<Dtype>::Forward_gpu(
const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) {
softmax_layer_->Forward(softmax_bottom_vec_, softmax_top_vec_);
const Dtype* prob_data = prob_.gpu_data();
const Dtype* label = bottom[]->gpu_data();
const int dim = prob_.count() / outer_num_;
const int nthreads = outer_num_ * inner_num_;
// Since this memory is not used for anything until it is overwritten
// on the backward pass, we use it here to avoid having to allocate new GPU
// memory to accumulate intermediate results in the kernel.
Dtype* loss_data = bottom[]->mutable_gpu_diff();
// Similarly, this memory is never used elsewhere, and thus we can use it
// to avoid having to allocate additional GPU memory.
Dtype* counts = prob_.mutable_gpu_diff();
// NOLINT_NEXT_LINE(whitespace/operators)
SoftmaxLossForwardGPU<Dtype><<<CAFFE_GET_BLOCKS(nthreads),
CAFFE_CUDA_NUM_THREADS>>>(nthreads, prob_data, label, loss_data,
outer_num_, dim, inner_num_, has_ignore_label_, ignore_label_, counts);
Dtype loss;
caffe_gpu_asum(nthreads, loss_data, &loss);
Dtype valid_count = -;
// Only launch another CUDA kernel if we actually need the count of valid
// outputs.
if (normalization_ == LossParameter_NormalizationMode_VALID &&
has_ignore_label_) {
caffe_gpu_asum(nthreads, counts, &valid_count);
}
top[]->mutable_cpu_data()[] = loss / get_normalizer(normalization_,
valid_count);
if (top.size() == ) {
top[]->ShareData(prob_);
}
} template <typename Dtype>
__global__ void SoftmaxLossBackwardGPU(const int nthreads, const Dtype* top,
const Dtype* label, Dtype* bottom_diff, const int num, const int dim,
const int spatial_dim, const bool has_ignore_label_,
const int ignore_label_, Dtype* counts) {
const int channels = dim / spatial_dim; CUDA_KERNEL_LOOP(index, nthreads) {
const int n = index / spatial_dim;
const int s = index % spatial_dim;
const int label_value = static_cast<int>(label[n * spatial_dim + s]); if (has_ignore_label_ && label_value == ignore_label_) {
for (int c = ; c < channels; ++c) {
bottom_diff[n * dim + c * spatial_dim + s] = ;
}
counts[index] = ;
} else {
bottom_diff[n * dim + label_value * spatial_dim + s] -= ;
counts[index] = ;
}
}
} template <typename Dtype>
void SoftmaxWithLossLayer<Dtype>::Backward_gpu(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_gpu_diff();
const Dtype* prob_data = prob_.gpu_data();
const Dtype* top_data = top[]->gpu_data();
caffe_gpu_memcpy(prob_.count() * sizeof(Dtype), prob_data, bottom_diff);
const Dtype* label = bottom[]->gpu_data();
const int dim = prob_.count() / outer_num_;
const int nthreads = outer_num_ * inner_num_;
// Since this memory is never used for anything else,
// we use to to avoid allocating new GPU memory.
Dtype* counts = prob_.mutable_gpu_diff();
// NOLINT_NEXT_LINE(whitespace/operators)
SoftmaxLossBackwardGPU<Dtype><<<CAFFE_GET_BLOCKS(nthreads),
CAFFE_CUDA_NUM_THREADS>>>(nthreads, top_data, label, bottom_diff,
outer_num_, dim, inner_num_, has_ignore_label_, ignore_label_, counts); Dtype valid_count = -;
// Only launch another CUDA kernel if we actually need the count of valid
// outputs.
if (normalization_ == LossParameter_NormalizationMode_VALID &&
has_ignore_label_) {
caffe_gpu_asum(nthreads, counts, &valid_count);
}
const Dtype loss_weight = top[]->cpu_diff()[] /
(get_normalizer(normalization_, valid_count) * Caffe::getThreadNum());
caffe_gpu_scal(prob_.count(), loss_weight , bottom_diff);
}
} INSTANTIATE_LAYER_GPU_FUNCS_DISABLE_FP16(SoftmaxWithLossLayer); } // namespace caffe

outer_num_:相当于batch_size

dim: c*w*h

spatial_dim(inner_num_):w*h

softmax_loss.cpp的代码:

outer_num_ = bottom[]->count(, softmax_axis_);
inner_num_ = bottom[]->count(softmax_axis_ + );

其实可以看出来count的只取前,不取后,(0, softmax_axis_)只取了0这一个轴

softmax_loss.cu 和 softmax_loss.cpp源码的更多相关文章

  1. Mavlink_main.cpp源码学习

    int mavlink_main(int argc, char *argv[]) { if (argc < 2) { usage();                               ...

  2. Caffe源码-SGDSolver类

    SGDSolver类简介 Solver类用于网络参数的更新,而SGDSolver类实现了优化方法中的随机梯度下降法(stochastic gradient descent),此外还具备缩放.正则化梯度 ...

  3. android后台截屏实现(2)--screencap源码修改

    首先找到screencap类在Android源码中的位置,/442/frameworks/base/cmds/screencap/screencap.cpp 源码如下: /* * Copyright ...

  4. 【精解】EOS标准货币体系与源码实现分析

    EOS智能合约中包含一个exchange合约,它支持用户创建一笔交易,是任何两个基本货币类型之间的交易.这个合约的作用是跨不同币种(都是EOS上的标准货币类型)的,通过各自与EOS主链价值进行锚定,然 ...

  5. duilib 使用图片素材或者算法给窗体增加阴影(源码和demo)

    转载请说明原出处,谢谢:http://blog.csdn.net/zhuhongshu/article/details/42580877 之前我写的程序使用阴影时,一直是使用codeproject网站 ...

  6. Caffe源码-Solver类

    Solver类简介 Net类中实现了网络的前向/反向计算和参数更新,而Solver类中则是对此进行进一步封装,包含可用于逐次训练网络的Step()函数,和用于求解网络的优化解的Solve()函数,同时 ...

  7. Caffe源码-InsertSplits()函数

    InsertSplits()函数 在Net初始化的过程中,存在一个特殊的修改网络结构的操作,那就是当某层的输出blob对应多个其他层的输入blob时,会在输出blob所在层的后面插入一个新的Split ...

  8. Caffe源码-Blob类

    Blob类简介 Blob是caffe中的数据传递的一个基本类,网络各层的输入输出数据以及网络层中的可学习参数(learnable parameters,如卷积层的权重和偏置参数)都是Blob类型.Bl ...

  9. Caffe源码-SyncedMemory类

    SyncedMemory类简介 最近在阅读caffe源码,代码来自BVLC/caffe,基本是参照网络上比较推荐的 Blob-->Layer-->Net-->Solver 的顺序来分 ...

随机推荐

  1. web前端_Vue框架_设置浏览器上方的标题和图标

    在创建Vue项目时一般会用默认的项目标题和图标,如下图所示: 不是很美观也可能不符合项目的需求,所以有时候就需要改变项目在浏览器上方的标签名称或者图标. 找到项目根目录的index.html,如图: ...

  2. 一个github搞定微信小程序支付系列

    详情请前往github下载示例代码 源码中包含 支付.退款 功能 so easy,项目经理再也不用担心微信支付啦 是的,已经over了

  3. Android教程

    转载,但请务必在明确位置注明出处! http://stormzhang.com/android/2014/07/07/learn-android-from-rookie/ Android Killer ...

  4. POJ1182【种类并查集】

    思路: ---来源百度 0表示它与根结点为同类, 1表示它吃根结点, 2表示它被根结点吃. 判断两个点a, b的关系,我们令p = Find(a), q = Find(b),即p, q分别为a, b子 ...

  5. Oculus Rift, HTC Vive, SONY PSVR的全面对比

    http://blog.csdn.net/xoyojank/article/details/50927572 这次有幸参加了GDC 2016, 终于把三大设备体验了个遍, 也试玩了很多不错的VR游戏. ...

  6. [Xcode 实际操作]一、博主领进门-(4)设置项目的属性

    目录:[Swift]Xcode实际操作 本文将演示如何设置项目的属性. 点击项目名称[DemoApp],打开项目信息面板. [Identity识别]设置区域 [Display Name]:DemoAp ...

  7. centos 7.3 安装vmtools,解决无法编译共享文件夹模块

    环境说明: vmware 12.5.0 build-4352439 centos 7.3.1611   64位,内核版本:Linux version 3.10.0-514.16.1.el7.x86_6 ...

  8. 【NOI省选模拟】小奇的花园

    「题目背景」 小奇在家中的花园漫步时,总是会思考一些奇怪的问题. 「问题描述」 小奇的花园有n个温室,标号为1到n,温室以及以及温室间的双向道路形成一棵树. 每个温室都种植着一种花,随着季节的变换,温 ...

  9. MyBatist庖丁解牛(三)

    从MyBatis代码实现的角度来看,MyBatis的主要的核心部件有以下几个: SqlSession:作为MyBatis工作的主要顶层API,表示和数据库交互的会话,完成必要数据库增删改查功能: Ex ...

  10. Hexo搭建博客教程(1) - 安装环境与本地搭建

    前言 搭建个人博客一般有两种选择,一个是使用WordPress,但是需要将博客搭建在服务器上,不过搭建好后写文章方便,适合没有程序基础的人使用.另一个是使用Hexo,相对简洁高效,不需要服务器,既可以 ...