挤压函数是什么?把任意大小的输入压到一个有限区间里
挤压函数(Squashing Function)是一类能把任意大小的输入值“挤压”到一个有限的区间之内的函数。无论输入是多大的正数还是多小的负数,输出都会被限制在一个固定的范围里,而且通常是单调递增的:输入越大,输出越大,但越接近区间的边界,增长得越缓慢。
典型的挤压函数
Sigmoid 函数,也叫逻辑函数:把任意实数压缩到 0 到 1 之间。输入为零时输出 0.5;输入很大时输出趋近于 1;输入很小时输出趋近于 0。它的曲线呈现出平滑的 S 形。由于输出在 0 到 1 之间,它可以被理解为一个概率,因此被用于逻辑回归和神经网络的二分类输出层。
Tanh 函数,也叫双曲正切函数:把任意实数压缩到负 1 到 1 之间,形状也是 S 形,但以零为中心,输入为零时输出也为零。它实际上可以由 Sigmoid 函数经过缩放和平移得到。由于输出以零为中心,在神经网络的隐藏层中,它通常比 Sigmoid 函数的训练效果更好。
在神经网络中的作用
在早期的人工神经网络中,挤压函数是最常用的激活函数。一方面,它为网络引入了非线性,让网络能够学习复杂的关系;另一方面,它把每个神经元的输出限制在一个固定的范围内,不会无限地增大,这让网络的计算更加稳定,也在一定程度上模仿了生物神经元的“激活”和“饱和”的特性。
挤压函数在神经网络的理论中也占有重要的地位:1989 年,George Cybenko 证明了万能逼近定理,指出只要隐藏层的神经元足够多,使用 Sigmoid 这类挤压函数作为激活函数的单隐藏层神经网络,就能以任意精度逼近任何连续函数。Kurt Hornik 等人在同一时期也证明了类似的结论,他们的论文中正是使用了“挤压函数”这一说法。
挤压带来的问题
挤压函数也有一个明显的缺点:当输入很大或很小时,函数曲线变得非常平坦,导数接近于零,这叫“饱和”。在训练深层神经网络时,误差需要通过反向传播一层层地传回去,每经过一层都要乘以激活函数的导数。如果很多层的神经元都处于饱和状态,梯度就会变得越来越小,靠近输入的那些层几乎无法得到训练,这就是梯度消失问题。Sigmoid 函数的导数最大值只有 0.25,问题尤其严重。正因为如此,在 2010 年代以后,ReLU 这类在正数区域不会饱和的激活函数,逐渐取代了挤压函数,成为深度神经网络隐藏层的首选。
今天的用途
挤压函数并没有消失,它们在一些特定的地方仍然不可替代:Sigmoid 函数常用于二分类的输出层和多标签分类;在长短期记忆网络和门控循环单元中,Sigmoid 函数被用作“门”,决定让多少信息通过,Tanh 函数被用来生成候选的状态值;在注意力机制和各种门控结构中也很常见。此外,Geoffrey Hinton 等人在 2017 年提出的胶囊网络中,有一个专门命名为 squash 的函数,它不是作用在单个数值上,而是把一个向量的长度压缩到 0 到 1 之间,同时保持它的方向不变,用向量的长度来表示某个实体存在的概率。