SMU: smooth activation function for deep networks using smoothing maximum technique
1.介绍
尽管ReLU有一些严重的缺点,但由于其简单性,ReLU成为深度学习中最常见的选择。本文在已知激活函数Leaky ReLU近似的基础上,提出了一种新的激活函数,称之为Smooth Maximum Unit(SMU)。用SMU替换ReLU,ShuffleNet V2模型在CIFAR100数据集上得到了6.22%的提升。
神经网络是深度学习的支柱。激活函数是神经网络的大脑,在深度神经网络的有效性和训练中起着核心作用。ReLU由于其简单性而成为深度学习领域的常用选择。尽管它很简单,但ReLU有一个主要的缺点,即ReLU死亡问题,在这种情况下,多达50%的神经元在网络训练期间死亡。
为了克服ReLU的不足,近年来提出了大量的激活方法,其中Leaky ReLU、Parametric ReLU 、ELU、Softplus、随机化Leaky ReLU是其中的几种,它们在一定程度上改善了ReLU的性能。
Swish是谷歌脑组提出的非线性激活函数,对ReLU有一定的改善;GELU是另一种常用的平滑激活函数。可以看出,Swish和GELU都是ReLU的光滑近似。近年来,人们提出了一些提高ReLU、Swish或GELU性能的非线性激活方法,其中一些是ReLU或Leaky ReLU的光滑逼近方法,还有TanhSoft、EIS、Padé激活单元、正交Padé激活单元、Mish、ErfAct等。maximum function在原点处是非光滑的。在本文中,作者将探讨maximum function的平滑逼近如何影响网络的训练和性能。
Maximum Function定义如下:
式1函数|x|在原点是不可微的。因此,从上式可以看出最大值函数在原点处也是不可微的。这里可以用Smooth函数来近似|x|函数。对于本文的其余部分,我们将只考虑两个近似| x, 在深度学习问题中使用这两个函数和近似的结果比其他近似|x|可以得到更好的结果。
注意,从上面平滑地近似|x|,而从下面平滑地近似|x|。这里 是一个平滑参数,当取 无穷大 时,近似函数平滑地逼近|x|。这里erf是高斯误差函数,定义如下:
现将式(1)中的|x|函数替换为,则最大函数的光滑逼近公式如下:
式2同理,可以推导出的光滑近似公式:
式3注意,当无穷大,;当, 。对于和的特定值,可以近似已知的激活函数。例如,, ,得到:
式4这是maxout族中的一个简单情况,而通过考虑和的非线性选择可以发现更复杂的情况。对于和的特定值,可以得到ReLU和Leaky ReLU的平滑近似。例如,考虑和,有ReLU的平滑近似:
式5GELU是ReLU的光滑近似。注意,如果方程(5)中取,则可以逼近GELU激活函数,这也表明GELU是ReLU的光滑近似。此外,考虑和α,可以得到Leaky ReLU或Parametric ReLU的光滑逼近,这取决于α是超参数还是可学习参数。
式6请注意,式(5)和式(6)下端近似为ReLU或Leaky ReLU。同样地,可以从式(3)推导出近似函数,它将近似上面的ReLU或Leaky ReLU。
式(6)对输入变量x的相应导数为:
式7其中,
称方程(6)中的函数为Smooth Maximum Unit(SMU)。可以将方程(3)中的和α替换为一个函数,称之为SMU-1。对于所有的实验,将使用SMU和SMU-1作为激活函数。
2. 代码实现:
# coding=utf-8
import tensorflow as tf
import numpy as np
def SMU(x,alpha=0.25):
mu = tf.get_variable('SMU_mu', shape=(),
initializer=tf.constant_initializer(1000000),
dtype=tf.float32)
print("******")
print(mu)
print("******")
return ((1+alpha)*x + (1-alpha)*x*tf.math.erf(mu*(1-alpha)*x))/2
def SMU1(x,alpha=0.25):
mu = tf.get_variable('SMU1_mu', shape=(),
initializer=tf.constant_initializer(4.352665993287951e-9),
dtype=tf.float32)# tf.compat.v1.get_variable('SMU_mu', shape=(),
return ((1+alpha)*x+tf.math.sqrt(tf.math.square(x-alpha*x)+tf.math.square(mu)))/2
from keras.utils.generic_utils import get_custom_objects
get_custom_objects().update({'SMU': Activation(SMU)})
get_custom_objects().update({'SMU1': Activation(SMU1)})
应(调)用:
conv=Convolution1D(10, 1,strides=1,padding="valid", activation='SMU')