深度学习模型之激活函数(Activation Function)

(介绍激活函数的文章非常多,但是暂时没看到结合“游乐场”进行试验的,也就写这篇文章的出发点。)
一、激活函数是什么?
激活函数,英文Activation Function,个人理解,激活函数是实现神经元的输入和输出之间非线性化。
二、为什么需要非线性化?
以下通过“游乐场”里的例子看看线性函数的局限性。
对于明显的“一刀切”问题,线性函数还可以解决。

但是,对于要画曲线的问题就“无能为力”,但是现实世界中能简单“一刀切”的问题毕竟少,更广泛的是下图的非线性问题。

三、有哪些激活函数(activation function)
重点参考以下网站:https://blog.csdn.net/u011684265/article/details/78039280
- ReLU
- Tanh
- Sigmoid

1. ReLU
Rectified Linear Unit(ReLU) - 用于隐层神经元输出
公式
曲线
RELU特点:
输入信号 <0 时,输出都是0,>0 的情况下,输出等于输入
ReLU 的优点:
Krizhevsky et al. 发现使用 ReLU 得到的 SGD 的收敛速度会比 sigmoid/tanh 快很多
ReLU 的缺点:
训练的时候很”脆弱”,很容易就”die”了
例如,一个非常大的梯度流过一个 ReLU 神经元,更新过参数之后,这个神经元再也不会对任何数据有激活现象了,那么这个神经元的梯度就永远都会是 0.
如果 learning rate 很大,那么很有可能网络中的 40% 的神经元都”dead”了。

结果有点像个“菱形”,毕竟看看ReLU的定义,可以理解。
2. sigmoid
公式:sigmoid函数也叫 Logistic 函数,用于隐层神经元输出,取值范围为(0,1),它可以将一个实数映射到(0,1)的区间,可以用来做二分类。
在特征相差比较复杂或是相差不是特别大时效果比较好。
sigmoid缺点:
-
激活函数计算量大,反向传播求误差梯度时,求导涉及除法
-
反向传播时,很容易就会出现梯度消失的情况,从而无法完成深层网络的训练
-
Sigmoids函数饱和且kill掉梯度。
-
Sigmoids函数收敛缓慢。
下面解释为何会出现梯度消失:
反向传播算法中,要对激活函数求导,sigmoid 的导数表达式为:
sigmoid 原函数及导数图形如下:
由图可知,导数从 0 开始很快就又趋近于 0 了,易造成“梯度消失”现象

可以较为“圆滑”地解决问题,但是训练次数相对多一些。
3.Tanh
公式
曲线
也称为双切正切函数,取值范围为[-1,1]。
tanh在特征相差明显时的效果会很好,在循环过程中会不断扩大特征效果。
与 sigmoid 的区别是,tanh 是 0 均值的,因此实际应用中 tanh 会比 sigmoid 更好

能够比较“光滑”地解决问题。
四、更多激活函数
The following table compares the properties of several activation functions that are functions of one fold x from the previous layer or layers:



(真够多的,分三次截图才截完!)
The following table lists activation functions that are not functions of a single fold x from the previous layer or layers:

图片来源,来自wiki,强大的wiki。
五、code
# 函数add_layer,添加一个神经网络隐藏层
# layoutname,隐藏层的名字
# inputs,隐藏层的输入,也就是前一层
# in_size,输入的纬度,也就是前一层的neurons数目
# out_size,输出的纬度,也就是该隐藏层的neurons数目
# activatuib_funaction,激活函数
def add_layer(layoutname, inputs, in_size, out_size, activatuib_funaction=None):
with tf.name_scope(layoutname):
with tf.name_scope('weights'):
Weights=tf.Variable(tf.random_normal([in_size,out_size], stddev=0.1),name='W') #stddev=0.1,无意中试过,加这个,效率速度快很多。
tf.summary.histogram('Weights',Weights) #histogram_summary用于生成分布图,也可以用scalar_summary记录存数值
with tf.name_scope('biases'):
# biases=tf.Variable(tf.zeros([1,out_size])+0.1,name='b')
biases = tf.Variable(tf.constant(0.1, shape=[out_size]), name='b')
tf.summary.histogram('Biases',biases)
with tf.name_scope('Wx_plus_b'):
Wx_plus_b=tf.add(tf.matmul(inputs,Weights),biases)
# Wx_plus_b=tf.matmul(inputs, Weights) + biases
if activatuib_funaction is None:
outputs=Wx_plus_b
else :
outputs=activatuib_funaction(Wx_plus_b)
return outputs
num_HiddenNeurons1 = 60 # 中间隐藏层第一层,80个代表特征
num_HiddenNeurons2 = 40 # 隐藏层第二层
num_HiddenNeurons3 = 20 # 隐藏层第三层
with tf.name_scope('first_hindden_layer'):
first_hindden_layer=add_layer("first_hindden_layer",X_input,features,num_HiddenNeurons1,activatuib_funaction=tf.tanh)
with tf.name_scope('second_hindden_layer'):
second_hindden_layer=add_layer("second_hindden_layer",first_hindden_layer,num_HiddenNeurons1,num_HiddenNeurons2,activatuib_funaction=tf.tanh)
with tf.name_scope('third_hindden_layer'):
third_hindden_layer=add_layer("third_hindden_layer",second_hindden_layer,num_HiddenNeurons2,num_HiddenNeurons3,activatuib_funaction=tf.tanh)
with tf.name_scope('prediction'):
y_prediction =add_layer('prediction',third_hindden_layer,num_HiddenNeurons3,numClasses,activatuib_funaction=None)
# y_prediction的输出并不是概率分布,没有经过softmax
# [[ 84.97052765 47.09545517]
# [ 84.97052765 47.09545517]]
y_prediction_softmax = tf.nn.softmax(y_prediction)
with tf.name_scope('Save'):
saver = tf.train.Saver(max_to_keep=4) #保留最近四次的模型
如果用图片解释,大概是以下这个:

六、Tensorflow支持的Activation Function
http://www.tensorfly.cn/tfdoc/api_docs/python/nn.html
Activation Functions
The activation ops provide different types of nonlinearities for use in neural networks. These include smooth nonlinearities (sigmoid
, tanh
, and softplus
), continuous but not everywhere differentiable functions (relu
, relu6
, and relu_x
), and random regularization (dropout
).
All activation ops apply componentwise, and produce a tensor of the same shape as the input tensor.
