您的位置:首页 > 其它

8、TensorFlow 中的激活函数

2017-11-26 11:15 232 查看

一、深层神经网络为什么需要激活函数?

非线性激活函数的主要作用

提供网络的非线性建模能力,增强模型的表达能力,双隐层神经网络能够解决任意复杂的分类问题

将原始特征从低维空间映射到高维空间(从多项式角度看——它隐含的找到了所需的高次特征项(更好的特征),从而简化了繁重的计算)

线性函数不能用作激活函数的原因

线性函数的线性组合仍然是线性函数

不能解决线性不可分问题

二、激活函数的分类、演化及优缺点

1、激活函数的分类

Traditional:
sigmoid(logistic)、tanh


RELU Family:
RELU、Leaky RELU、PRELU、RRELU


Exponential Family:
ELU、SELU




2、激活函数的演化及优缺点

Sigmoid 的优缺点

优点:

可以把输入映射到(0, 1)区间,可以用来表示概率
(eg:logistic regression)


在物理意义上最为接近生物神经元

缺点:

梯度消失问题

首先明确一点:误差反向传播时,梯度包含了f′(zl)和上一层的误差项(又包含了f′(zl+1):z 为权重加权和)两个乘法因子,具体反向传播推导见此链接

一个原因是:由于 sigmoid 的导数f′(zl)区间为(0, 0.25],所以其极易落入饱和区,导致梯度非常小,权重接近不变,无法正常更新

另一个原因是:误差不断向底层传递的过程中,f′(zl)会呈
指数倍
增加,而其值域为(0, 0.25],所以梯度
越往后传递
值越小,最终导致权重无法正常更新

Sigmoid outputs are not zero-centered(待补充?还不是很清楚为什么?)

Tanh 的优缺点

优点:

Tanh outputs are zero-centered,把输入映射到(-1, 1)区间

缺点:

虽然 tanh 的导数f′(zl)区间为(0, 1],但仍然会导致梯度消失问题!

在 RNN 中的应用:

RNN 中为什么要采用 tanh 而不是 RELU 作为激活函数?



RELU 的优缺点

优点:

比 sigmoid/tanh 收敛的更快(6x),creating
sparse representations
with true zeros( more likely to be linearly separable)

其导数在其
权重和(z)
大于 0 的时候为 1,从而误差可以很好的传播,权重可以正常更新

缺点:

其导数在其
权重和(z)
小于 0 的时候为 0,会导致梯度值为0,从而权重无法正常更新

输出具有偏移现象,即输出均值恒大于零



RELU 的变种



ELU

右侧线性部分使得 ELU 能够缓解梯度消失,而左侧软饱能够让 ELU 对输入变化或噪声更鲁棒



SELU(出自 Self-Normalizing Neural Networks )

激活函数有一个不动点,网络深了以后每一层的输出都是均值为 0 方差为 1

可以防止梯度消失和梯度爆炸

代码实现如下:

def selu(x):
with ops.name_scope('elu') as scope:
alpha = 1.6732632423543772848170429916717
scale = 1.0507009873554804934193349852946
return scale*tf.where(x>=0.0, x, alpha*tf.nn.elu(x))


三、激活函数实战建议

Use ReLU with a samll learning rate


Try out ELU / Leaky RELU / SELU

Try out tanh but don not expect much and never use sigmoid

Output layer should use
softmax
for classification or
liner
for regression

四、激活函数在 TensorFow 中的实现

# All activation ops apply componentwise, and produce
# a tensor of the same shape as the input tensor

tf.sigmoid(x, name = None) == tf.nn.sigmoid(x, name = None)
# y = 1 / (1 + exp(-x))

tf.tanh(x, name = None)  == tf.nn.tanh(x, name = None)
# y = (exp(x) - exp(-x)) / (exp(x) + exp(-x))

tf.nn.relu(features, name=None)
# y = max(features, 0)

tf.nn.elu(features, name=None)
# exp(features) - 1 if < 0, features otherwise

tf.nn.relu6(features, name=None)
# y = min(max(features, 0), 6)

tf.nn.crelu(features, name=None)
# concat 后的结果为:[relu(features), -relu(features)],一个是relu,一个是relu关于y轴对称的形状

tf.nn.softplus(features, name=None)
# y = log(exp(features) + 1)

tf.nn.softsign(features, name=None)
# y = features / (abs(features) + 1)


五、参考资料

1、深度学习中的激活函数导引

2、Must Know Tips/Tricks in Deep Neural Networks (by Xiu-Shen Wei)

3、https://cs231n.github.io/neural-networks-1/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: