前言
论文地址:链接: https://arxiv.org/pdf/1908.08681.pdf.
源码地址:链接: https://github.com/digantamisra98/Mish.
贡献:
- 提出了一种新型的自正则化的非单调激活函数Mish: f ( x ) = x t a n h ( s o f t p l u s ( x ) ) = x t a n h ( l n ( 1 + e x ) ) f(x) = xtanh(softplus(x)) = xtanh(ln(1+e^x)) f(x)=xtanh(softplus(x))=xtanh(ln(1+ex));
- 从公式角度探究了Mish和Swish之间的联系
- 提出一种一阶导数如何作为正则化器帮助优化深度神经网络的直接猜想,但是并没有证实。
Mish的特性(Proprties):
- 无上界,非饱和,避免了因饱和而导致梯度为0(梯度消失/梯度爆炸),进而导致训练速度大大下降;
- 有下界,在负半轴有较小的权重,可以防止ReLU函数出现的神经元坏死现象;同时可以产生更强的正则化效果;
- 自身本就具有自正则化效果(公式可以推导),可以使梯度和函数本身更加平滑(Smooth),且是每个点几乎都是平滑的,这就更容易优化而且也可以更好的泛化。随着网络越深,信息可以更深入的流动。
- x<0,保留了少量的负信息,避免了ReLU的Dying ReLU现象,这有利于更好的表达和信息流动。
- 连续可微,避免奇异点
- 非单调
一、背景
\qquad 卷积层的线性操作 + 激活函数的非线性操作是卷积神经网络的两个最基础的模块。在早期时候,Sigmod和Tanh两个激活函数被广泛的使用,但因为它们容易饱和进而容易引发梯度消失/爆炸,且效率低下,所以逐渐被非饱和线性分段激活函数ReLU所取代,因为ReLU函数解决了梯度问题,且表现出更好的泛化性和提升收敛速度。但是ReLU激活函数也具有很明显的缺点:x<0部分容易引发神经元坏死,损失梯度信息。所以今年来,先后出现了Leaky ReLU、ELU、SELU、PReLU、RReLU、Swish等一系列的激活函数对ReLU函数进行了改进。我们从Swish激活函数 f ( x ) = x ∗ s i g m o i d ( β x ) f(x) = x * sigmoid(\beta x) f(x)=x∗sigmoid(βx)中逐渐意识到:平滑连续的函数轮廓(曲线)可以更好的传播信息。所以我们希望创建一个更平滑的(每个点都自带自正则化效果 增强平滑能力)的这么一个函数。
\qquad 我们的灵感来自于Swish的自门控(self_gating)性质:非调制输入x ∗ * ∗ 输入的非线性函数的输出。我们基于出提出了一种新型的自正则化的非单调激活函数 M i s h : f ( x ) = x t a n h ( s o f t p l u s ( x ) ) Mish: f(x) = xtanh(softplus(x)) Mish:f(x)=xtanh(softplus(x)).
二、Mish Activation
公式: f ( x ) = x t a n h ( s o f t p l u s ( x ) ) = x t a n h ( l n ( 1 + e x ) ) f(x) = xtanh(softplus(x)) = xtanh(ln(1+e^x)) f(x)=xtanh(softplus(x))=xtanh(ln(1+ex));这里的f(x)范围大概在 [ ≈ \approx ≈-0.31, ∞ \infty ∞]
函数图像和导函数图像:
另外我们还比较了很多和Mish激活函数图像很相似的函数,如下图:
\qquad
我们可以发现,虽然这些函数和Mish函数的形状很相似,都是相对比较平滑的,但是比较其性能效果来说,Mish激活函数明显更好更平稳(唯一能比的
x
l
o
g
(
t
a
n
h
(
e
x
)
xlog(tanh(e^x)
xlog(tanh(ex))稳定性不足)。而且Mish激活函数会随着网络的深度加深,信息可以更深入的流动,效果更好。
\qquad 这是为什么呢?同样的都是平滑的曲线,形状也相似,为什呢Mish激活函数的效果这么好呢?这个问题将在下节继续讨论。
三、self-regularization、smooth
从直观上来说,Mish 函数和 Swish函数是很相似的,如对Mish函数求一阶导数:
\qquad
我们从直觉上猜测:
Δ
x
\Delta x
Δx可能是一个预处理器,在每个横坐标x上进行处理,使梯度更加平滑。具体的直觉上我们觉得正是这个预处理使激活函数更加平滑也更容易优化。而这里的
Δ
x
\Delta x
Δx就是模仿了这中优化器行为,给函数本身提供了一种更强的自正则化(self-regularization)的效果,使梯度更平滑。这也就能解释了为什么同样的都是平滑的曲线,形状也相似,Mish激活函数的效果却比其他的函数效果好这么多。且随着网络的深度加深,Mish函数由于其更平滑的梯度,信息可以更深入的流动,效果会更好。
上图3可以看出Mish激活函数平滑的轮廓可以让梯度更好的流动,输出的部分(output landscapes)会更加的平滑一些。
\qquad
从图4也可以进一步的看出Mish函数要比ReLU和Swish函数平滑(Smooth)很多。而且Mish的最小值更宽,提高了泛化能力,ReLU和Swish有多个局部最小值。与ReLU和Swish网络相比,Mish得到的损耗最小,验证了Mish对损耗面的预处理效果。
\qquad 但是关于这种激活函数一阶导数作为正则化器帮助优化深度神经网络的直接猜想,并没有得到证实,这种机制如果能研究出原因,可能可以为神经网络带来重大影响,有待后面证明。
四、Mish Properties
论文总结了Mish函数的6大特性:
- 无上界,非饱和,避免了因饱和而导致梯度为0(梯度消失/梯度爆炸),进而导致训练速度大大下降;
- 有下界,在负半轴有较小的权重,可以防止ReLU函数出现的神经元坏死现象;同时可以产生更强的正则化效果;
- 自身本就具有自正则化效果(公式可以推导),可以使梯度和函数本身更加平滑(Smooth),且是每个点几乎都是平滑的,这就更容易优化而且也可以更好的泛化。随着网络越深,信息可以更深入的流动。
- x<0,保留了少量的负信息,避免了ReLU的Dying ReLU现象,这有利于更好的表达和信息流动。
- 连续可微,避免奇异点
- 非单调
五、论文实验结果
Mish better empirical results than Swish, ReLU, and Leaky ReLU.
六、Pytorch实现
简单版本:
class Mish(nn.Module):
"""
Mish 激活函数
https://arxiv.org/pdf/1908.08681.pdf
https://github.com/digantamisra98/Mish/blob/master/Mish/Torch/mish.py
"""
@staticmethod
def forward(x):
return x * F.softplus(x).tanh() # softplus(x) = ln(1 + exp(x)
高效版本:
class MemoryEfficientMish(nn.Module):
"""
一种高效的Mish激活函数 不采用自动求导(自己写前向传播和反向传播) 更高效
"""
class F(torch.autograd.Function):
@staticmethod
def forward(ctx, x):
# 前向传播
# save_for_backward函数可以将对象保存起来,用于后续的backward函数
# 会保留此input的全部信息,并提供避免in_place操作导致的input在backward中被修改的情况
ctx.save_for_backward(x)
return x.mul(torch.tanh(F.softplus(x))) # x * tanh(ln(1 + exp(x)))
@staticmethod
def backward(ctx, grad_output):
# 反向传播
x = ctx.saved_tensors[0]
sx = torch.sigmoid(x)
fx = F.softplus(x).tanh()
return grad_output * (fx + x * sx * (1 - fx * fx))
def forward(self, x):
return self.F.apply(x)
Reference
链接: 博客1.