1、在src\caffe\proto\caffe.proto中搜索message LayerParameter,在optional ReLUParameter relu_param = 123之后添加optional ReLU6Parameter relu6_param = 208; (最后的分号别忘了)

2、搜索message ReLUParameter,在这个ReLUParameter实现结构之后添加

// Message that stores parameters used by ReLU6Layer
message ReLU6Parameter {
  enum Engine {
    DEFAULT = 0;
    CAFFE = 1;
    CUDNN = 2;
  }
  optional Engine engine = 2 [default = DEFAULT];
}

支持proto头文件修改完毕,接下来添加所需的头文件和实现文件。

1.在blob/ssd/include/caffe/layers文件夹下新建relu6_layer.hpp,将


#ifndef CAFFE_RELU_LAYER_HPP_
#define CAFFE_RELU_LAYER_HPP_ #include <vector> #include "caffe/blob.hpp"
#include "caffe/layer.hpp"
#include "caffe/proto/caffe.pb.h" #include "caffe/layers/neuron_layer.hpp" namespace caffe { /**
* @brief Rectified Linear Unit non-linearity @f$ y = \min(6, \max(0, x)) @f$.
* The simple max is fast to compute, and the function does not saturate.
*/
template <typename Dtype>
class ReLU6Layer : public NeuronLayer<Dtype> {
public:
/**
* @param param provides ReLUParameter relu_param,
* with ReLULayer options:
* - negative_slope (\b optional, default 0).
* the value @f$ \nu @f$ by which negative values are multiplied.
*/
explicit ReLU6Layer(const LayerParameter& param)
: NeuronLayer<Dtype>(param) {} virtual inline const char* type() const { return "ReLU6"; } protected:
/**
* @param bottom input Blob vector (length 1)
* -# @f$ (N \times C \times H \times W) @f$
* the inputs @f$ x @f$
* @param top output Blob vector (length 1)
* -# @f$ (N \times C \times H \times W) @f$
* the computed outputs @f$
* y = \max(0, x)
* @f$ by default. If a non-zero negative_slope @f$ \nu @f$ is provided,
* the computed outputs are @f$ y = \max(0, x) + \nu \min(0, x) @f$.
*/
virtual void Forward_cpu(const vector<Blob<Dtype>*>& bottom,
const vector<Blob<Dtype>*>& top);
virtual void Forward_gpu(const vector<Blob<Dtype>*>& bottom,
const vector<Blob<Dtype>*>& top); /**
* @brief Computes the error gradient w.r.t. the ReLU inputs.
*
* @param top output Blob vector (length 1), providing the error gradient with
* respect to the outputs
* -# @f$ (N \times C \times H \times W) @f$
* containing error gradients @f$ \frac{\partial E}{\partial y} @f$
* with respect to computed outputs @f$ y @f$
* @param propagate_down see Layer::Backward.
* @param bottom input Blob vector (length 1)
* -# @f$ (N \times C \times H \times W) @f$
* the inputs @f$ x @f$; Backward fills their diff with
* gradients @f$
* \frac{\partial E}{\partial x} = \left\{
* \begin{array}{lr}
* 0 & \mathrm{if} \; x \le 0 \\
* \frac{\partial E}{\partial y} & \mathrm{if} \; x > 0
* \end{array} \right.
* @f$ if propagate_down[0], by default.
* If a non-zero negative_slope @f$ \nu @f$ is provided,
* the computed gradients are @f$
* \frac{\partial E}{\partial x} = \left\{
* \begin{array}{lr}
* \nu \frac{\partial E}{\partial y} & \mathrm{if} \; x \le 0 \\
* \frac{\partial E}{\partial y} & \mathrm{if} \; x > 0
* \end{array} \right.
* @f$.
*/
virtual void Backward_cpu(const vector<Blob<Dtype>*>& top,
const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom);
virtual void Backward_gpu(const vector<Blob<Dtype>*>& top,
const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom);
}; } // namespace caffe #endif // CAFFE_RELU_LAYER_HPP_
 

2.在blob/ssd/src/caffe/layers文件夹下新建relu6_layer.cpp,将

#include <algorithm>
#include <vector> #include "caffe/layers/relu6_layer.hpp" namespace caffe { template <typename Dtype>
void ReLU6Layer<Dtype>::Forward_cpu(const vector<Blob<Dtype>*>& bottom,
const vector<Blob<Dtype>*>& top) {
const Dtype* bottom_data = bottom[0]->cpu_data();
Dtype* top_data = top[0]->mutable_cpu_data();
const int count = bottom[0]->count();
for (int i = 0; i < count; ++i) {
top_data[i] = std::min(std::max(bottom_data[i], Dtype(0)), Dtype(6));
}
} template <typename Dtype>
void ReLU6Layer<Dtype>::Backward_cpu(const vector<Blob<Dtype>*>& top,
const vector<bool>& propagate_down,
const vector<Blob<Dtype>*>& bottom) {
if (propagate_down[0]) {
const Dtype* bottom_data = bottom[0]->cpu_data();
const Dtype* top_diff = top[0]->cpu_diff();
Dtype* bottom_diff = bottom[0]->mutable_cpu_diff();
const int count = bottom[0]->count();
for (int i = 0; i < count; ++i) {
bottom_diff[i] = top_diff[i] *
((bottom_data[i] > 0 && bottom_data[i] < 6));
}
}
} #ifdef CPU_ONLY
STUB_GPU(ReLU6Layer);
#endif INSTANTIATE_CLASS(ReLU6Layer);
REGISTER_LAYER_CLASS(ReLU6); } // namespace caffe

3.在blob/ssd/src/caffe/layers文件夹下新建relu6_layer.cu,将

#include <algorithm>
#include <vector> #include "caffe/layers/relu6_layer.hpp" namespace caffe { template <typename Dtype>
__global__ void ReLU6Forward(const int n, const Dtype* in, Dtype* out) {
CUDA_KERNEL_LOOP(index, n) {
out[index] = in[index] < 0 ? 0: (in[index] > 6 ? 6 : in[index]);
}
} template <typename Dtype>
void ReLU6Layer<Dtype>::Forward_gpu(const vector<Blob<Dtype>*>& bottom,
const vector<Blob<Dtype>*>& top) {
const Dtype* bottom_data = bottom[0]->gpu_data();
Dtype* top_data = top[0]->mutable_gpu_data();
const int count = bottom[0]->count();
// NOLINT_NEXT_LINE(whitespace/operators)
ReLU6Forward<Dtype><<<CAFFE_GET_BLOCKS(count), CAFFE_CUDA_NUM_THREADS>>>(
count, bottom_data, top_data);
CUDA_POST_KERNEL_CHECK;
// << " count: " << count << " bottom_data: "
// << (unsigned long)bottom_data
// << " top_data: " << (unsigned long)top_data
// << " blocks: " << CAFFE_GET_BLOCKS(count)
// << " threads: " << CAFFE_CUDA_NUM_THREADS;
} template <typename Dtype>
__global__ void ReLU6Backward(const int n, const Dtype* in_diff,
const Dtype* in_data, Dtype* out_diff) {
CUDA_KERNEL_LOOP(index, n) {
out_diff[index] = in_diff[index] * ((in_data[index] > 0)
&& (in_data[index] < 6));
}
} template <typename Dtype>
void ReLU6Layer<Dtype>::Backward_gpu(const vector<Blob<Dtype>*>& top,
const vector<bool>& propagate_down,
const vector<Blob<Dtype>*>& bottom) {
if (propagate_down[0]) {
const Dtype* bottom_data = bottom[0]->gpu_data();
const Dtype* top_diff = top[0]->gpu_diff();
Dtype* bottom_diff = bottom[0]->mutable_gpu_diff();
const int count = bottom[0]->count();
// NOLINT_NEXT_LINE(whitespace/operators)
ReLU6Backward<Dtype><<<CAFFE_GET_BLOCKS(count), CAFFE_CUDA_NUM_THREADS>>>(
count, top_diff, bottom_data, bottom_diff);
CUDA_POST_KERNEL_CHECK;
}
} INSTANTIATE_LAYER_GPU_FUNCS(ReLU6Layer); } // namespace caffe

重新编译ssd。

SSD: ReLU6的更多相关文章

  1. 移动端目标识别(3)——使用TensorFlow Lite将tensorflow模型部署到移动端(ssd)之Running on mobile with TensorFlow Lite (写的很乱,回头更新一个简洁的版本)

    承接移动端目标识别(2) 使用TensorFlow Lite在移动设备上运行         在本节中,我们将向您展示如何使用TensorFlow Lite获得更小的模型,并允许您利用针对移动设备优化 ...

  2. SSD框架训练自己的数据集

    SSD demo中详细介绍了如何在VOC数据集上使用SSD进行物体检测的训练和验证.本文介绍如何使用SSD实现对自己数据集的训练和验证过程,内容包括: 1 数据集的标注2 数据集的转换3 使用SSD如 ...

  3. 光驱SSD安装Win7+ubuntu系统双系统

    准备条件: U盘,32GB,三星品牌 SSD,120GB,三星品牌 win7旗舰版,Ghost系统(安装简单嘛),Ylmf_Ghost_Win7_SP1_x64_2016_1011.iso ubunt ...

  4. 创建Azure DS 虚拟机并附加SSD硬盘

    $subscriptionName = "Windows Azure Enterprise Trial" #订阅名称 $location = "China East&qu ...

  5. 关闭电脑SSD的磁盘碎片整理

    小白往往会把机械硬盘时代的习惯带进固态硬盘时代,比如碎片整理.机械硬盘时代砖家最喜欢告诉小白:“系统慢了吧?赶紧碎片整理撒.”小白屁颠屁颠地整理去了.殊不知碎片整理对于SSD来说完全就是种折磨.这种“ ...

  6. SQL Server 2014新特性探秘(2)-SSD Buffer Pool Extension

    简介     SQL Server 2014中另一个非常好的功能是,可以将SSD虚拟成内存的一部分,来供SQL Server数据页缓冲区使用.通过使用SSD来扩展Buffer-Pool,可以使得大量随 ...

  7. Macbook SSD硬盘空间不够用了?来个Xcode大瘦身吧!

    原文转自:http://www.jianshu.com/p/03fed9a5fc63    日期:2016-04-22 最近突然发现我的128G SSD硬盘只剩下可怜的8G多,剩下这么少的一点空间连X ...

  8. 搭把手教美工妹妹如何通过升级SSD提升电脑性能

    -----by LinHan 不单单适用于妹子,我这名的意思的妹子也能看懂. 以下教程依据实践和部分互联网资料总结得出,向博客园, CSDN的前辈们致谢:同时,如有说的不正确或有不到位的地方,麻烦指出 ...

  9. [archlinux][hardware] ThankPad T450自带SSD做bcache之后的使用寿命分析

    这个分析的起因,是由于我之前干了这两个事: [troubleshoot][archlinux][bcache] 修改linux文件系统 / 分区方案 / 做混合硬盘 / 系统转生大!手!术!(调整底层 ...

随机推荐

  1. Android系统更新防互刷功能实现与分析【转】

    本文转载自:https://blog.csdn.net/huangyabin001/article/details/44465145 版权声明:本文为博主原创文章,未经博主允许不得转载.    htt ...

  2. matlab做聚类分析

    说明:如果是要用matlab做kmeans聚类分析,直接使用函数kmeans即可.使用方法:kmeans(输入矩阵,分类个数k). 转载一: MATLAB提供了两种方法进行聚类分析: 1.利用 clu ...

  3. CF 1087解题报告

    cf解题报告 记录一下吧 做出:T1 rating :-97 想起几个月前做不出T1还是有点小搞笑呀2333 T1 双指针+特判 T2 发现k特别小,枚举剩余系 还要判断是否是能被n整除 移项发现可以 ...

  4. CentOS7.2中systemctl的使用

    CentOS 7.x开始,CentOS开始使用systemd服务来代替daemon,原来管理系统启动和管理系统服务的相关命令全部由systemctl命令来代替. 1.原来的 service 命令与 s ...

  5. UVALive 7512 November 11th 题解

    思路:心态大崩,最多不讲了,最少应该是三个一组,比如......应该是.S..S.,这样占的最多 代码: #include<set> #include<map> #includ ...

  6. Android开发——去掉系统自带标题栏的几种方式

    https://blog.csdn.net/qq_28585471/article/details/75991613 今天在练习自定义标题栏(Android初级开发(四)——补充3)的过程中遇到了隐藏 ...

  7. 关于C#引用ExceptionPolicy.HandleException(ex, "LogAndReplace", out exceptionToReplace);

    http://www.cnblogs.com/Terrylee/archive/2006/07/03/enterprise_library2_1.html 要使用ExceptionPolicy.Han ...

  8. HDU 3507 Print Article(斜率优化)

    显然的斜率优化模型 但是单调队列维护斜率单调性的时候出现了莫名的锅orz 代码 #include <cstdio> #include <algorithm> #include ...

  9. js作用域题目

    window.number = 4var obj = { 'number': 4, 'tbl': (function(){ this.number *= 2; console.log(this.num ...

  10. jmeter线程组之间传参

    背景介绍: 使用jmeter做登录和搜索接口的测试: 登录接口请求头为:Content-Type: application/x-www-form-urlencoded; charset=UTF-8 搜 ...