GELU的两个初等函数近似是怎么来的
By 苏剑林 | 2020-03-26 | 61466位读者 |GELU,全称为Gaussian Error Linear Unit,也算是RELU的变种,是一个非初等函数形式的激活函数。它由论文《Gaussian Error Linear Units (GELUs)》提出,后来被用到了GPT中,再后来被用在了BERT中,再再后来的不少预训练语言模型也跟着用到了它。随着BERT等预训练语言模型的兴起,GELU也跟着水涨船高,莫名其妙地就成了热门的激活函数了。
在GELU的原始论文中,作者不仅提出了GELU的精确形式,还给出了两个初等函数的近似形式,本文来讨论它们是怎么得到的。
GELU函数 #
GELU函数的形式为
GELU(x)=xΦ(x)
其中Φ(x)是标准正态分布的累积分布函数,即
Φ(x)=∫x−∞e−t2/2√2πdt=12[1+erf(x√2)]
这里erf(x)=2√π∫x0e−t2dt。然后原论文还提了两个近似:
xΦ(x)≈xσ(1.702x)
以及
xΦ(x)≈12x[1+tanh(√2π(x+0.044715x3))]
现在仍然有不少Transformer架构模型的实现都是用近似(4)作为GELU函数的实现。不过很多框架已经有精确的erf计算函数了,所以初等函数近似形式的价值可能不会很大,因此大家就当是一道数学分析练习题吧~
用啥近似 #
显然,要找GELU的近似形式,就相当于找Φ(x)近似,这也等价于找erf(x√2)的近似。
首先,我们要解决第一个问题:用什么函数来近似。从erf(x)图像我们可以看出它的特点:
1、它是一个奇函数,即erf(x)=−erf(−x);
2、它单调递增,并且limx→−∞erf(x)=−1,limx→+∞erf(x)=1。
奇函数我们有很多,比如x2n+1,sinx,tanx,tanhx等,并且奇函数的叠加、复合函数依然是奇函数,比如sin(x+x3);又是奇函数,又单调递增且有界的,我们最容易想到的可能是tanhx,事实上,tanhx确实跟erf(x)很相似。
因此,我们可以从tanhx出发,构造一些可能的拟合形式,比如
{tanh(ax+bx3+cx5)atanhx+btanh3x+ctanh5xatanhbx+ctanhdx+etanhfx⋮
怎样近似 #
有了待拟合的形式之外,下面要考虑的就是怎么拟合、以什么标准拟合的问题了,说白了,就是想个办法求出各项系数来。一般来说,有两种思路:局部拟合和全局拟合。
局部拟合 #
局部拟合基于泰勒展开,比如考虑近似形式tanh(ax+bx3),我们在x=0处展开,得到
erf(x√2)−tanh(ax+bx3)=(√2π−a)x+(a33−b−13√2π)x3+…
让前两项为0,刚好得到两个方程,求解得到
a=√2π,b=4−π3√2π3/2
代入xΦ(x),并换成数值形式,那么就是
xΦ(x)≈12x[1+tanh(√2π(x+0.0455399x3))]
全局拟合 #
式(8)已经跟式(4)很接近了,但是第二个系数还是差了点。这是因为(8)纯粹是局部近似的结果,顾名思义,局部近似在局部会很精确,比如上面的推导是基于x=0处的泰勒展开,因此在x=0附近会比较精确,但是离0远一点时误差就会更大。因此,我们还需要考虑全局误差。
比较容易想到的全局误差是积分形式的,比如用g(x,θ)去逼近f(x)时,我们去算
minθ∫[f(x)−g(x,θ)]2dx或minθ∫|f(x)−g(x,θ)|dx
但是,每个x处的误差重要性可能不一样,因此为了不失一般性,还要乘以一个权重λ(x),即
minθ∫λ(x)[f(x)−g(x,θ)]2dx或minθ∫λ(x)|f(x)−g(x,θ)|dx
不同的λ(x)会导致不同的解,哪个λ(x)最适合,也不容易选择。
因此,我们不去优化这种积分形式的误差,我们优化一个更直观的min−max形式的误差:
minθmaxx|f(x)−g(x,θ)|
这个式子很好理解,就是“找一个适当的θ,使得最大的|f(x)−g(x,θ)|都尽可能小”,这样的目标符合我们的直观理解,并且不涉及到权重的选取。
混合拟合 #
基于这个思想,我们固定a=√2π,然后去重新求解tanh(ax+bx3)。固定这个a是因为它是一阶局部近似,我们希望保留一定的局部近似,同时希望b能尽可能帮我们减少全局误差,从而实现局部近似与全局近似的混合。所以,现在我们要求解
minbmaxx|erf(x√2)−tanh(ax+bx3)|
用scipy可以轻松完成求解:
import numpy as np
from scipy.special import erf
from scipy.optimize import minimize
def f(x, b):
a = np.sqrt(2 / np.pi)
return np.abs(erf(x / np.sqrt(2)) - np.tanh(a * x + b * x**3))
def g(b):
return np.max([f(x, b) for x in np.arange(0, 4, 0.001)])
options = {'xtol': 1e-10, 'ftol': 1e-10, 'maxiter': 100000}
result = minimize(g, 0, method='Powell', options=options)
print(result.x)
最后得到b=0.035677337314877385,对应的形式就是:
xΦ(x)≈12x[1+tanh(√2π(x+0.04471491123850965x3))]
最后几位有效数字可能有误差,但前面部分已经跟式(4)完美契合了~补充说明下,式(4)提出自论文《Approximations to the Cumulative Normal Function and its Inverse for Use on a Pocket Calculator》,已经是40多年前的结果了。
至于第一个近似,则来自论文《A logistic approximation to the cumulative normal distribution》,它是直接用σ(λx)全局逼近Φ(x)的结果,即
minλmaxx|Φ(x)−σ(λx)|
解得λ=1.7017449256323682,即
Φ(x)≈σ(1.7017449256323682x)
这跟式(3)同样很吻合。
文章小结 #
本文带大家一起做了道数学分析题——介绍了GELU激活函数,并试图探索了它的两个近似形式的来源,成功了水出了这篇博文~
转载到请包括本文地址:https://spaces.ac.cn/archives/7309
更详细的转载事宜请参考:《科学空间FAQ》
如果您还有什么疑惑或建议,欢迎在下方评论区继续讨论。
如果您觉得本文还不错,欢迎分享/打赏本文。打赏并非要从中获得收益,而是希望知道科学空间获得了多少读者的真心关注。当然,如果你无视它,也不会影响你的阅读。再次表示欢迎和感谢!
如果您需要引用本文,请参考:
苏剑林. (Mar. 26, 2020). 《GELU的两个初等函数近似是怎么来的 》[Blog post]. Retrieved from https://spaces.ac.cn/archives/7309
@online{kexuefm-7309,
title={GELU的两个初等函数近似是怎么来的},
author={苏剑林},
year={2020},
month={Mar},
url={\url{https://spaces.ac.cn/archives/7309}},
}
July 16th, 2020
erf()的函数形式漏掉了系数:
erf(x)=1√π∫x−xe−t2dt=2√π∫x0e−t2dt
是的,感谢指正,已修改。
July 17th, 2021
“其中Φ(x)是标准正态分布的累积概率函数”,应该是累积分布函数吧
谢谢,改过来了。
其实“累积概率函数”也没啥毛病,不会引起歧义,既然提出来了,那就按照标准的来吧~
August 8th, 2022
[...]GELU的两个初等函数近似是怎么来的[...]
August 22nd, 2022
您好!
您的网站可能不可能接受客座帖子?
谢谢
主要看内容对不对博主的审美哈哈。
October 10th, 2023
您好,叨扰了,公式(15)中左侧是否多了一个x,即应该为“Φ(x)≈⋯”?
是的,已更正,谢谢。
September 26th, 2024
写的很棒。我还有一个疑问:
求解 erf(x)的近似的原因是erf(x)
x∗σ(x)
也是可以的呢?
你是指用xσ(x)来替换GELU,还是用xσ(x)来近似GELU,前者现在LLM都已经这样做了,后者本文也已经讨论了。
嗯嗯,我看到了,那个激活函数起名叫 silu