您的位置:首页 > 理论基础 > 计算机网络

tiny_cnn源码阅读(2)-激活函数

2016-05-29 14:46 447 查看
激活函数概述
identiti函数

sigmoid函数

relu函数

leaky_relu

elu

softmax

tanh

tanh p1m2

源码阅读

参考

激活函数概述

神经网络都有各个层组成,在不同的层中,用到不同的激活函数。在看layer之前,先了解一下定义的激活函数。

数据”经过一个神经网络时,经过卷积或池化等运算后,最终输出的一个值。这个“输出值”就是经过激活函数计算的来的,反向求导,也是对激活函数来求导的。

激活函数通常有以下性质:

非线性:如果激活函数都为线性,那么神经网络的最终输出都是和输入呈线性关系;显然这不符合事实。

可导性:神经网络的优化都是基于梯度的,求解梯度时需要确保函数可导。

单调性:激活函数是单调的,否则不能保证神经网络抽象的优化问题为凸优化问题了。

输出范围有限:激活函数的输出值的范围是有限时,基于梯度的方法会更加稳定。输入值范围为(−∞,+∞),如果输出范围不加限制,虽然训练会更加高效,但是learning rate将会更小,且给工程实现带来许多困难。

f(x)≈x(x≈0):当x≈0时,需要满足这个条件。这样权重初始化为很小的值时,训练神经网络会更加高效。否则需要细心设置权重的初始值。

identiti函数

从名字看出,这是个“相等”学习函数,数据通过这个函数不会有任何变化。所以其函数
float_t f(const vec_t& v, cnn_size_t i)
返回变量的值,求导时导数为
1


sigmoid函数

sigmoid函数定义为:

f(x)=1(1+e−x)

它是是连续、光滑、严格单调的非线性函数,它把数值(-inf, +inf)映射到了(0 , 1)。它的导数

df(y)=y(1−y)

relu函数

relu函数定义为

f(x)=max(0,x)

当信号小于0时,输出为0;信号大于0时,输出值为信号的值。rule函数计算非常简单,只需要一个阀值就可以得到激活值,不用进行复杂的计算。使用SGD时,用rule代替sigmod/tanh的话,收敛速度会快很多。

leaky_relu

leaky_relu定义为:

f(x)={ax,x<0x,x≥0

使用rule时,如果一个很大的梯度经过relu神经元,那么这个神经元可能不会再对其他数据起作用了,这会造成部分这个神经元“死掉”,使用leaky_relu可以解决这个问题。a的值很小,这样可以保留部分负值信息。

定义为:当x<0时,f(x)=(e^x-x)

elu

elu定义为:

f(x)={a(ex−1),x<0x,x≥0

elu全称为exponential linear unit。

softmax

softmax用来归一化,把输出值归一化为(0,1)之间的值,且总和为1。对于SoftMax输出,可以理解为概率。计算过程为:

1、求出集合中最大的值alpha。

2、使用指数,将数值转换为0-1之间的数exp(v[i]-alpha)。

3、归一化,即将上步求得的数值求和sum,所求结果为exp(v[i]-alpha)/sum。

tanh

tanh的定义为

f(x)=ex−e−xex+e−x

它的形状和sigmod有点像,但是它是0均值的,取值范围为(-1,1)。

tanh p1m2

这是tanh的变形,定义为:

f(x)=exex+e−x

源码阅读

激活函数在tiny-cnn-master/tiny_cnn/activations/activation_function.h中。

首先定义了基类
function


class function {
public:
function() = default;
function(const function &) = default;
#ifndef CNN_DEFAULT_MOVE_CONSTRUCTOR_UNAVAILABLE
function(function &&) = default;
#endif
function &operator =(const function &) = default;
#ifndef CNN_DEFAULT_ASSIGNMENT_OPERATOR_UNAVAILABLE
function &operator =(function &&) = default;
#endif
virtual ~function() = default;

virtual float_t f(const vec_t& v, cnn_size_t index) const = 0;//前向传播

// dfi/dyi
virtual float_t df(float_t y) const = 0;//反向求导

// dfi/dyk (k=0,1,..n)
virtual vec_t df(const vec_t& y, cnn_size_t i) const { vec_t v(y.size(), 0); v[i] = df(y[i]); return v; }

// target value range for learning
virtual std::pair<float_t, float_t> scale() const = 0;//输出值的范围
};


函数
float_t f(const vec_t&, cnn_size_t index)
为前向传播,
float_t df(float_t y)
vec_t df(const vec_t& y, cnn_size_t i)
为求导,前者是对一个数求导,后者是对容器所有数求导。
std::pair<float_t, float_t> scale()
是来控制函数输出的范围。

前向传播和反向传播都是虚函数,在其派生类中有实现。

参考

【机器学习】神经网络-激活函数-面面观(Activation Function)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息