Hi,大家好,我是编程小6,很荣幸遇见你,我把这些年在开发过程中遇到的问题或想法写出来,今天说一说GELU函数的近似,希望能够帮助你!!!。
GELU(Gaussian Error Linear Unit)函数的定义为
其中
考虑高斯误差函数
通过令得
由于高斯误差函数里面涉及了指数运算和积分运算,如何利用初等函数进行拟合,对于提高运算效率就显得比较有意义了。
高斯误差函数的图像为
from scipy.special import erf
import numpy as np
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.spines['right'].set_visible(False)
ax.spines['top'].set_color('none')
ax.xaxis.set_ticks_position('bottom')
ax.spines['bottom'].set_position(('data',0))
ax.yaxis.set_ticks_position('left')
ax.spines['left'].set_position(('data',0))
x=np.linspace(-5,5,100)
y=erf(x)
plt.plot(x,y)
plt.title('graph of erf function')
plt.show()
可以验证erf(x)为奇函数,首先想到的是利用tanh(x)做近似。可以考虑两种拟合方式,局部拟合和全局拟合。全局拟合也就是数学里面的一致性问题。这里只考虑利用对erf(x)进行拟合。
局部拟合考虑利用泰勒展开,拟合前几项的系数
则
令
求解得到
此时,拟合的函数为
import numpy as np
import matplotlib.pyplot as plt
a=np.sqrt(2/np.pi)
b=(4-np.pi)/(3*np.sqrt(2)*np.pi**(3/2))
b1=(4-np.pi)/(6*np.pi)
x=np.linspace(-5,5,100)
#y=erf(x)
def gelu(x):
return 1/2*x*(1+erf(x/np.sqrt(2)))
def gelu_pro1(x):
return 1/2*x*(1+np.tanh(np.sqrt(2/np.pi)*(x+b1*x**3)))
fig, ax = plt.subplots()
ax.spines['right'].set_visible(False)
ax.spines['top'].set_color('none')
ax.xaxis.set_ticks_position('bottom')
ax.spines['bottom'].set_position(('data',0))
ax.yaxis.set_ticks_position('left')
ax.spines['left'].set_position(('data',0))
plt.plot(x,gelu(x))
plt.plot(x,gelu_pro1(x),'r-')
plt.legend(['gelu','gelu_pro'])
plt.title('performance of the approximate')
plt.show()
考虑到中的求解能够保证对GELU的一阶近似,这里我们先固定a,然后对b进行求解。即
import numpy as np
from scipy.special import erf
from scipy.optimize import minimize
a=np.sqrt(2/np.pi)
def f(x,b):
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)
今天的分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。
上一篇
已是最后文章
下一篇
已是最新文章