BLOG

个人博客,记录学习与生活

机器学习激活函数

Published Dec. 4, 2020, 8:43 p.m. by kkk

对神经网络中的激活函数进行整理、汇总。

神经网络,特别是深度神经网络,神经网络的叠加起到效果,并实现其强大的拟合能力,很重要的就是其各层输出的非线性变换,也即是各层的激活函数。

激活函数最主要的作用就是进行非线性变换,各种激活函数的不断变化在于其它特性,例如有的激活函数反向传播容易梯度消失或爆炸,实践上不同激活函数网络有着不同的适应场景,在此,对常用的一些激活函数作总结。

实际使用中隐层基本都使用ReLU系激活函数(ReLU, LeakyReLU, PReLU, ELU, SELU等),Sigmoid、Softmax通常出现在二分类、多分类的输出层,而其它激活函数就很少出现了。

keras中,激活函数的应用用两种方式:通过构建激活函数层;初始化层时传递激活函数作为参数。

model.add(layers.Dense(64))
model.add(layers.Activation(activations.relu))
# or
model.add(layers.Dense(64, activation='relu'))

ReLU

基本是最长使用的激活函数,兼顾计算速度、导数性质、非线性变换、稀疏性等方面,计算很简单,公式如下: $$ ReLU(x) = max(0, x) $$

def relu(x):
    return np.maximum(x, 0)

# tf
tf.nn.relu(x)
tf.keras.activations.relu(x)

relu

LeakyReLU

属于ReLU的改进版本,在左侧引入了一个梯度(斜率)值。

注:LeakyReLU中,该梯度值为给定值(超参数),如果是训练参数(模型参数),则称之为Parametric ReLU, PReLU。 $$ LeakyReLU(x) = \cases { x & x>0\\ \gamma x & x<=0 } $$

def leakyrelu(x, gamma):
     return np.maximum(x, 0) + np.minimum(0, gamma * x)

# tf
tf.nn.leaky_relu(x, alpha=0.2)
tf.keras.activations.relu(x, alpha=0.2)

leaky_relu

ELU

全称Exponential Linear Unit,也是ReLU的改进版本,处理的是ReLU不零中心化的问题,由于ReLU是非零中心化的,会给后一层神经网络引入偏置偏移。但是ELU相对ReLU的问题主要就是计算慢 $$ ELU = \cases{ x &x>0\\ \gamma(e^x-1) &x<=0 } $$

def elu(x):
    return np.maximum

# tf
tf.keras.activations.elu(x, alpha=1.0)

elu

SELU

全称Scaled Exponential Linear Unit,也就是Scaled ELU,直译就是缩放的指数线性函数,提出自2017年,SELU可以使网络自正则化,即输出均值为0,标准差为1的数据,效果效果相较于其它网络会好很多,但是需要满足一定条件

  • 输入特征需要标准化

  • 隐藏层权重必须采用LeCun Initialization

  • 网络架构必须是序列型,在非序列性网络(如RNN)中使用的话不能确保自正则化,也不会一定优于其它激活函数的训练效果
  • 原论文只证明了所有隐藏层都是密集层(Dense)时,能够自正则化,其它类型的网络不确定

隐藏层激活函数选择建议:SELU>ELU>leaky ReLU>ReLU>tanh>logistic,如果网络架构导致SELU无法自正则化,ELU会优于SELU,如果比较在意运行延迟,可以选择leaky ReLU,如果不想调整另外的超参数,可以使用Keras默认的(比如leaky ReLU的$\alpha$为0.3)。

而如果时间和计算资源稍微充裕,可以交叉验证其它的几个激活函数效果:RReLU(如果网络过拟合)、PReLUde(如果训练样本集非常大),而速度第一位的话,ReLU是最佳选择(许多库对ReLU有特别的硬件优化)

$$ SELU = \cases{ scale * x & x>0\\ scale * alpha * (e^x - 1), & x <=0 } $$

虽然公式如上,实际上scale, alpha是给定的值,分别为alpha=1.67326324scale=1.05070098。当使用Lecun initialization时,会保留相邻层的标准差和方差。

def selu(x):
    return np.maximum(x, 0) + np.minimum(0, scale * alpha * (np.exp(x)-1))

# tf
tf.nn.selu(x)
tf.keras.activations.selu(x)

# 层中
tf.keras.layers.Dense(64, kernel_initializer='lecun_normal', activation='selu')

selu

tanh

双曲正切函数,使用比较少 $$ tanh(x) = \frac{e^x - e^{-x}}{e^x + e^{-x}} $$

def tanh(x):
    return np.tanh(x)

# tf
tf.nn.tanh(x)
tf.keras.activations.tanh(x)

tanh

Sigmoid

信号处理中常会用到的函数,Logistic Regress中使用的也是sigmoid函数,Sigmoid函数也叫Logistic函数,以前作为所有网络层的激活函数,但发现有问题,后来就基本都开始用ReLU了,问题主要是两点:

  • 导数易饱和,当输入过大或者过小时,导数都向0饱和,导致层数增加后,开始层的参数变化非常微小
  • 平均值为0.5,而不是0

$$ Sigmoid(x) = \frac{1}{1+e^{-x}} $$

def sigmoid(x):
    return 1 / (1 + np.exp(-x))

# tf
tf.nn.sigmoid(x)
tf.keras.activations.sigmiod(x)

另外还有Hard-sigmoid,其实就是为了简化计算,采用近似的方式,近似方式是通过一阶泰勒展开,在值在-11之间的区域,公式可见: $$ HardSigmoid(x) = \cases{ 1 & x>2.5\\ 0.2 x + 0.5 &-2.5 <= x<=2.5\\ 0 &x<-2.5 } $$

sigmoid

Softmax

可当作多元的sigmiod,将标量值转变为概率值,通常用在最后一层,计算多分类的概率值。 $$ sigmoid(xi) = \frac{e^{xi}}{\sum_i e^{xi}} $$

# 输入为2阶张量
def sigmoid(x):
    fra = np.exp(x)
    div = np.sum(fra, axis=1)
    return fra / div

# tf
tf.nn.softmax(x)
tf.keras.activations.softmax(x)

Softplus

可以看作是ReLU函数的平滑版本,定义为: $$ Softplus(x) = \log(1+e^x) $$ 其倒数恰好为Logistic函数,具有单侧一直、宽兴奋边界的特性,但是没有稀疏激活性。

def softplus(x):
     return np.log(1+np.exp(x))

# tf
tf.nn.softmax(x)
tf.keras.activations.softmax(x)

softplus

Softsign

类似于Softplus,也是对某一函数的近似,Softsign是对Sign(就是阶跃函数)的平滑版本,从起名就可以看出来,公式如下: $$ Softsign(x) = \frac{x}{\vert x\vert +1} $$

def softsign(x):
    return x / (np.abs(x) + 1)

# tf
tf.nn.softsign(x)
tf.keras.activations.softsign(x)

softsign

Swish

由于是2017年才提出,使用不多,是一种self-gated激活函数,具有一个可学习的参数,公式如下: $$ Swish(x) = x\sigma(\beta x) $$ 其中$\sigma(\cdot)$是可看作一种软性额门控机制,当$\beta x$接近1时,门处于“开”状态,激活函数输出近似与$x$,而当$\sigma(\beta x)$接近0时,门处于“关”状态,激活函数输出近似于0。

def swish(x, beta):
    sig = 1 / (1 + np.exp(-beta * x))
    return x * sig

# tf
# 都是默认beta=1,且不提供beta的参数调节
tf.nn.swish(x) 
tf.keras.activations.swish(x)

swish


Share this post
< Pre: 机器学习评估指标 Pos: 模型训练方法和参数初始化方法 >
1499 comments