乐于分享
好东西不私藏

AI和大模型——激活函数

AI和大模型——激活函数

一、激活函数

在大模型的底层框架,深度学习中一个很重要的概念就是激活函数。在神经网络中,激活函数就是一个数学函数,说得再准确一些就是一个非线性的数学函数。即通过线性的数据输入得到一个非线性的结果。在多层的神经网络中,它个非线性的输出结果就是下一层需要的数据输入。

二、激活函数的作用

通过定义其实就可以看出来激活函数的作用,它主要有三种:

  1. 引入非线性
    这是激活函数的最重要的作用,由于神经网络的神经元计算抽象后类似于y=wx+b,也就是说无论增加多少层其基本的线性情况是无法改变的。而实际的数据在引入过于复杂后,利用线性无法准确描述数据的分布。此时就需要引入非线性来进行描述。这也是书籍和各种视频中经常见到的曲线处理的例程的解释的底层原因。
  2. 限制输出的范围
    这个其实类似于归一化,防止数据跳动的范围过大导致数据处理的复杂和边界管理问题且便于对数据分类的描述
  3. 便于反向传播中的梯度处理
    一个好的激活函数,可以让求导变得更简单和快捷,从而能够在反向传播中通过梯度控制来进行参数的更新

三、常见的激活函数

在神经网络中,常见的激活函数主要有以下几种:

  1. sigmoid函数


    此函数的优势在于对数据的输出范围限制在了(0,1)之间,对于处理二分数据非常合适。不过它也有自身的缺点,就是当数据进入边界区时,此时进行求导时,其梯度的结果趋近于0。当在深度学习的神经网络中进行链式求导就会导致梯度消失,从而反向传播失效。另外它输出的始终在正区间内,容易产生之字形震荡,对于一些有负值的数据来说可能就不适合。
  2. ReLU及其变体
    ReLU(x)=max(0,x)
    此函数的优势在于计算简单,并且解决梯度消失的问题,而且由于其函数输出的特点(小于0的神经元输出0),产生稀疏性(即从大量的数据中,筛选出关键的数据项,忽略掉众多的非关键数据项)。但它的缺点也很明显,它有可能导致神经元死亡。即在参数更新时如果导致神经元的输入恒为负值时,它的输出梯度则永远为0.即神经元已经死亡。
    所以为了解决上面的ReLU的问题,又产生了很多变体,典型的有Leaky ReLU,其公式为:
    LeakyReLU(x)=max(αx,x)
    其中α是一个很小的常数(比如0.01),它用来处理输入参数小于零时,给一个参数,不让它输出0.从而可以引导神经元恢复正常,避免神经元的死亡。

  3. GeLU


    此函数数的目的同样是为了解决ReLU中的神经元死亡的现象,其通过将输入数据概率化分布输出来实现对数据的处理。特别是在输入为0时形成一个平滑的曲线,消除了相关的数据突然的结果变化
  4. Softmax

softmax

这个公式的输出范围也在(0,1)之间,输出和为1。作为一种概率分布,它更适合于多分类神经网络。它们图形如下:
active

四、如何选择

一个良好的神经网络,其实就是在正向传播和反向传播时能够快速的处理数据并能够进行良好的梯度控制,并快速收敛到最优的情况。所以在选择一个激活函数时,要根据实际的数据情况和需求进行正确的选择。
可以采用下面的方式进行激活函数的选择(激活函数的位置在于神经网络中上一层输出的结果与其到下一层的输入之间):

  1. 数据的特点
    比如数据有无正负值,像音视频信号或差分相关等信号,此时就可以使用LeakyReLU,网络太深就要考虑GeLU,如果只有正值(图像像素),就可以使用ReLU。如果数据用对称性就可以使用ELU,如果不对称可以使用ReLU等。
  2. 训练过程的处理
    比如出现了神经元死亡现象,就可以考虑使用LeakyReLU,GeLU等;如果验证集的损失函数上升则可以考虑使用GeLU;如果出现了局部最小值现象,就可以考虑一些非单调的激活函数如Mish等。

在如今的大模型中,常用的激活函数以GeLU和SwiGLU为主。当然,在实际的选择中还会受到各种情况的限制,这就需要小伙伴们自行根据情况处理了。

五、总结

神经网络应用的场景很多,不同领域可能也有不同需求。虽然对于大多数的大模型应用开发者来说不必掌握这些细节。但明白其中的原理还是对应用开发者有着重要的作用。