https://blog.csdn.net/weixin_34260991/article/details/87106463

这里使用比较简单的定义方式,只是在原有的激活函数调用中加入。

准备工作
下载MXNet源代码,确认可以顺利编译通过。推荐在Linux下进行此操作:

https://mxnet.incubator.apache.org/get_started/install.html

编写激活函数先前和先后传递
在src/operator/mshadow_op.h里面,加入新的激活函数向前传递和向后的函数:

/*!
* \brief RBF Unit
* \author Yuzhong Liu
*/
struct rbf {
template<typename DType>
MSHADOW_XINLINE static DType Map(DType x) {
return DType(expf(-x*x));
}
};

struct rbf_grad {
template<typename DType>
MSHADOW_XINLINE static DType Map(DType x, DType a) {
return DType(-2 * x * a);
}
};
添加调用方法
在src/operator/leaky_relu-inl.h里面,激活函数的调用方式:

namespace leakyrelu {
enum LeakyReLUOpInputs {kData, kGamma};
enum LeakyReLUOpOutputs {kOut, kMask};
# 定义新的激活函数名称
enum LeakyReLUOpType {kLeakyReLU, kPReLU, kRReLU, kELU, kRBF};
enum LeakyReLUOpResource {kRandom};
} // namespace leakyrelu

struct LeakyReLUParam : public dmlc::Parameter<LeakyReLUParam> {
// use int for enumeration
int act_type;
float slope;
float lower_bound;
float upper_bound;
DMLC_DECLARE_PARAMETER(LeakyReLUParam) {
DMLC_DECLARE_FIELD(act_type).set_default(leakyrelu::kLeakyReLU)
.add_enum("rrelu", leakyrelu::kRReLU)
.add_enum("leaky", leakyrelu::kLeakyReLU)
.add_enum("prelu", leakyrelu::kPReLU)
.add_enum("elu", leakyrelu::kELU)
# 添加激活函数枚举
.add_enum("rbf", leakyrelu::kRBF)
.describe("Activation function to be applied.");
DMLC_DECLARE_FIELD(slope).set_default(0.25f)
.describe("Init slope for the activation. (For leaky and elu only)");
DMLC_DECLARE_FIELD(lower_bound).set_default(0.125f)
.describe("Lower bound of random slope. (For rrelu only)");
DMLC_DECLARE_FIELD(upper_bound).set_default(0.334f)
.describe("Upper bound of random slope. (For rrelu only)");
}
};

template<typename xpu>
class LeakyReLUOp : public Operator {
public:
explicit LeakyReLUOp(LeakyReLUParam param) {
param_ = param;
}

virtual void Forward(const OpContext &ctx,
const std::vector<TBlob> &in_data,
const std::vector<OpReqType> &req,
const std::vector<TBlob> &out_data,
const std::vector<TBlob> &aux_args) {
using namespace mshadow;
using namespace mshadow::expr;
size_t expected = param_.act_type == leakyrelu::kPReLU ? 2 : 1;
CHECK_EQ(in_data.size(), expected);
Stream<xpu> *s = ctx.get_stream<xpu>();
Tensor<xpu, 3> data;
Tensor<xpu, 3> out;
Tensor<xpu, 3> mask;
Tensor<xpu, 1> weight;
int n = in_data[leakyrelu::kData].shape_[0];
int k = in_data[leakyrelu::kData].shape_[1];
Shape<3> dshape = Shape3(n, k, in_data[leakyrelu::kData].Size()/n/k);
data = in_data[leakyrelu::kData].get_with_shape<xpu, 3, real_t>(dshape, s);
out = out_data[leakyrelu::kOut].get_with_shape<xpu, 3, real_t>(dshape, s);
if (param_.act_type == leakyrelu::kRReLU) {
mask = out_data[leakyrelu::kMask].get_with_shape<xpu, 3, real_t>(dshape, s);
}
switch (param_.act_type) {
case leakyrelu::kLeakyReLU: {
Assign(out, req[leakyrelu::kOut], F<mshadow_op::xelu>(data, param_.slope));
break;
}
case leakyrelu::kPReLU: {
weight = in_data[leakyrelu::kGamma].get<xpu, 1, real_t>(s);
Assign(out, req[leakyrelu::kOut],
F<mshadow_op::xelu>(data, broadcast<1>(weight, out.shape_)));
break;
}
case leakyrelu::kRReLU: {
if (ctx.is_train) {
Random<xpu>* prnd = ctx.requested[leakyrelu::kRandom].get_random<xpu, real_t>(s);
mask = prnd->uniform(mask.shape_);
mask = mask * (param_.upper_bound - param_.lower_bound) + param_.lower_bound;
Assign(out, req[leakyrelu::kOut], F<mshadow_op::xelu>(data, mask));
} else {
const float slope = (param_.lower_bound + param_.upper_bound) / 2.0f;
Assign(out, req[leakyrelu::kOut], F<mshadow_op::xelu>(data, slope));
}
break;
}
case leakyrelu::kELU: {
Assign(out, req[leakyrelu::kOut], F<mshadow_op::elu>(data, param_.slope));
break;
}
# RBF向前
case leakyrelu::kRBF: {
Assign(out, req[leakyrelu::kOut], F<mshadow_op::rbf>(data));
break;
}
default:
LOG(FATAL) << "Not implmented";
}
}

virtual void Backward(const OpContext & ctx,
const std::vector<TBlob> &out_grad,
const std::vector<TBlob> &in_data,
const std::vector<TBlob> &out_data,
const std::vector<OpReqType> &req,
const std::vector<TBlob> &in_grad,
const std::vector<TBlob> &aux_args) {
using namespace mshadow;
using namespace mshadow::expr;
size_t expected = param_.act_type == leakyrelu::kPReLU ? 2 : 1;
CHECK_EQ(out_grad.size(), 1U);
CHECK_EQ(req.size(), expected);
CHECK_EQ(in_data.size(), expected);
Stream<xpu> *s = ctx.get_stream<xpu>();
Tensor<xpu, 3> output;
Tensor<xpu, 3> data;
Tensor<xpu, 3> gdata;
Tensor<xpu, 3> grad;
Tensor<xpu, 3> mask;
Tensor<xpu, 1> weight;
Tensor<xpu, 1> grad_weight;
int n = out_grad[leakyrelu::kOut].shape_[0];
int k = out_grad[leakyrelu::kOut].shape_[1];
Shape<3> dshape = Shape3(n, k, out_grad[leakyrelu::kOut].Size()/n/k);
grad = out_grad[leakyrelu::kOut].get_with_shape<xpu, 3, real_t>(dshape, s);
gdata = in_grad[leakyrelu::kData].get_with_shape<xpu, 3, real_t>(dshape, s);
output = out_data[leakyrelu::kOut].get_with_shape<xpu, 3, real_t>(dshape, s);
if (param_.act_type == leakyrelu::kRReLU) {
mask = out_data[leakyrelu::kMask].get_with_shape<xpu, 3, real_t>(dshape, s);
}
if (param_.act_type == leakyrelu::kPReLU) {
data = in_data[leakyrelu::kData].get_with_shape<xpu, 3, real_t>(dshape, s);
}
switch (param_.act_type) {
case leakyrelu::kLeakyReLU: {
Assign(gdata, req[leakyrelu::kData], F<mshadow_op::xelu_grad>(output, param_.slope) * grad);
break;
}
case leakyrelu::kPReLU: {
weight = in_data[leakyrelu::kGamma].get<xpu, 1, real_t>(s);
grad_weight = in_grad[leakyrelu::kGamma].get<xpu, 1, real_t>(s);
grad_weight = sumall_except_dim<1>(F<prelu_grad>(data) * grad);
gdata = F<mshadow_op::xelu_grad>(data, broadcast<1>(weight, data.shape_)) * grad;
break;
}
case leakyrelu::kRReLU: {
Assign(gdata, req[leakyrelu::kData], F<mshadow_op::xelu_grad>(output, mask) * grad);
break;
}
case leakyrelu::kELU: {
Assign(gdata, req[leakyrelu::kData], F<mshadow_op::elu_grad>(output, param_.slope) * grad);
break;
}
# RBF向前
case leakyrelu::kRBF: {
data = in_data[leakyrelu::kData].get_with_shape<xpu, 3, real_t>(dshape, s);
Assign(gdata, req[leakyrelu::kData], F<mshadow_op::rbf_grad>(data, output) * grad);
break;
}
default:
LOG(FATAL) << "Not implmented";
}
}

private:
LeakyReLUParam param_;
}; // class LeakyReLUOp
从重新编译,并测试
import mxnet as mx
from mxnet import autograd
a = mx.nd.random_uniform(-1, 1, shape=[3, 3]) +0.5
a.attach_grad()

with autograd.record():
b = mx.nd.LeakyReLU(data=a, act_type='rbf')

print a, b
参考资料
https://mxnet.incubator.apache.org/how_to/new_op.html
http://blog.csdn.net/qq_20965753/article/details/66975622?utm_source=debugrun&utm_medium=referral
---------------------
作者:weixin_34260991
来源:CSDN
原文:https://blog.csdn.net/weixin_34260991/article/details/87106463
版权声明:本文为博主原创文章,转载请附上博文链接!

MXNet 定义新激活函数(Custom new activation function)的更多相关文章

  1. 浅谈深度学习中的激活函数 - The Activation Function in Deep Learning

    原文地址:http://www.cnblogs.com/rgvb178/p/6055213.html版权声明:本文为博主原创文章,未经博主允许不得转载. 激活函数的作用 首先,激活函数不是真的要去激活 ...

  2. The Activation Function in Deep Learning 浅谈深度学习中的激活函数

    原文地址:http://www.cnblogs.com/rgvb178/p/6055213.html 版权声明:本文为博主原创文章,未经博主允许不得转载. 激活函数的作用 首先,激活函数不是真的要去激 ...

  3. 《Noisy Activation Function》噪声激活函数(一)

    本系列文章由 @yhl_leo 出品,转载请注明出处. 文章链接: http://blog.csdn.net/yhl_leo/article/details/51736830 Noisy Activa ...

  4. 激活函数:Swish: a Self-Gated Activation Function

    今天看到google brain 关于激活函数在2017年提出了一个新的Swish 激活函数. 叫swish,地址:https://arxiv.org/abs/1710.05941v1 pytorch ...

  5. caffe中的sgd,与激活函数(activation function)

    caffe中activation function的形式,直接决定了其训练速度以及SGD的求解. 在caffe中,不同的activation function对应的sgd的方式是不同的,因此,在配置文 ...

  6. TensorFlow Activation Function 1

    部分转自:https://blog.csdn.net/caicaiatnbu/article/details/72745156 激活函数(Activation Function)运行时激活神经网络中某 ...

  7. ML 激励函数 Activation Function (整理)

    本文为内容整理,原文请看url链接,感谢几位博主知识来源 一.什么是激励函数 激励函数一般用于神经网络的层与层之间,上一层的输出通过激励函数的转换之后输入到下一层中.神经网络模型是非线性的,如果没有使 ...

  8. 转载-聊一聊深度学习的activation function

    目录 1. 背景 2. 深度学习中常见的激活函数 2.1 Sigmoid函数 2.2 tanh函数 2.3 ReLU函数 2.4 Leaky ReLu函数 2.5 ELU(Exponential Li ...

  9. TensorFlow实战第一课(session、Variable、Placeholder、Activation Function)

    莫烦tensorflow教学 1.session会话控制 Tensorflow 中的Session, Session是 Tensorflow 为了控制,和输出文件的执行的语句. 运行session.r ...

随机推荐

  1. shell编程之99乘法表

    #99乘法表#!/bin/bash #第一种写法 ` #`seq ` 使用反撇号括起来的(不是单引号),表示命令替换 do for j in `seq $i` #seq可以使用变量 do echo - ...

  2. 用session防止网站页面被频繁刷新

    session防止网站页面频繁被刷新 <?php //公司网站老是受到攻击,这是之前在网上看到的一个用session防止IP频繁访问的方法,我们公司用的是Memcache,都差不多,就是存储方式 ...

  3. 【Audiophobia UVA - 10048 】【Floyd算法】

    题目大意:从a城市到b城市的路径中,尽可能让一路上的最大噪音最小. 题目思路:设d [ i ][ j ]表示 i 到 j 的最大噪音的最小值. 那么d [ i ][ j ] = min( d[ i ] ...

  4. Python使用pip安装TensorFlow模块

    1.首先确保已经安装python,然后用pip来安装matplotlib模块. 2.进入到cmd窗口下,建议执行python -m pip install -U pip setuptools进行升级. ...

  5. 在命令行中执行kms命令激活Microsoft Office 2010

    激活office2010的命令是什么?激活office2010除了使用office2010激活工具之外,还可以使用kms命令来激活office2010,但是office2010激活命令还需考虑32位或 ...

  6. HDU3109: Worms(字符串变换类 DP)

    pro:开始有一个字母虫,然后字母虫在每一天可以选择自己身上的部分字母变换,变换规则形如A->BC. 现状给定最终字母虫的字符串,求最少用了多少天. 如有规则A->BC,B->AC, ...

  7. zabbix4.2.5常见问题指南

    一.zabbix配置postgres监控 rpm -ivh https://download.postgresql.org/pub/repos/yum/9.5/redhat/rhel-7-x86_64 ...

  8. PC端自适应布局

    截止目前,国内绝大多数内容为主的网站(知乎,果壳,V2EX,网易新闻等)均使用内容区定宽布局,大多数电商网站(网易考拉,京东,聚美优品)也使用了内容区定宽的布局,也有些网站使用了自适应布局: 天猫 内 ...

  9. 解读 v8 排序源码

    前言 v8 是 Chrome 的 JavaScript 引擎,其中关于数组的排序完全采用了 JavaScript 实现. 排序采用的算法跟数组的长度有关,当数组长度小于等于 10 时,采用插入排序,大 ...

  10. .net Web 项目的文件/文件夹上传下载

    以ASP.NET Core WebAPI 作后端 API ,用 Vue 构建前端页面,用 Axios 从前端访问后端 API ,包括文件的上传和下载. 准备文件上传的API #region 文件上传  ...