2026/10/22 12:23:47

【Pytorch】Paper Reading: GELUs

【Pytorch】Paper Reading: GELUs Paper Reading: GELUs1. 简介文章全名 GAUSSIAN ERROR LINEAR UNITS GELUs这个激活函数是LZ在看BERT的时候提及到的因为对这个激活函数还不是很熟悉于是就补充下对应的知识。主要想知道几个问题激活函数是怎么实现的与之前的激活函数相比它的优势在什么地方使用它对训练结果有什么影响什么是GELUs是指高斯误差线性单元Gaussian Error Linear Unint, GELU,这是一种高性能的神经网络激活函数表达式为x Φ ( x ) x\Phi(x)xΦ(x)其中Φ ( x ) \Phi(x)Φ(x)表示的标准高斯累积分布函数GELU的非线性是根据输入的值对输入进行加权在ReLU中是按照( x 1 x 0 ) (x\textbf{1}_{x0})(x1x0​)也就是通过符号对输入进行门控在文中作者针对ReLUELU和GELU进行实验评估发现所有考虑的计算机视觉自然语言处理和语音性能都会有所改进这么牛不知道这种激活函数与板端的兼容性怎么样…2. Why GELU?学习深度学习我们最先接触的激活函数都是Sigmoid activations,常见的还有ReLUELU等但是这些激活函数或多或少都会有一定的缺陷具体可以看这篇文章。我们为了防止模型过拟合会对网络进行随机的正则化例如给隐藏层增加噪声或者进行dropout操作。这些正则化操作是独立于激活函数的同时也是独立于网络的输入的。于是作者想了一个新的激活函数就是本文的主角了GELU它本身就具有了随机正则化的效果这使得神经元的输出更加具有概率性。3. GELU具体是怎么做的呢作者想要创造出一个激活函数可以同时拥有以下的性质dropout随机让神经元失活具体的操作可以看成是输入随机乘以0zoneout随机将这个时刻的激活替换为上一时刻的激活也就是将输入随机乘以1ReLU 激活函数随机的将输入乘以0或者1综合上面的描述作者将输入随机乘以0或者1,具体是0还是1是随机确定的但是也由输入来进行确定。具体的操作如下可以将神经元的输入x xx乘以一个分布m B e r n o u l i ( Φ ( x ) ) mBernouli(\Phi(x))mBernouli(Φ(x)), 其中Φ ( x ) P ( X x ) , X N ( 0 , 1 ) \Phi(x)P(Xx), XN(0, 1)Φ(x)P(Xx),XN(0,1)是标准正态分布的累积分布函数作者选择这个分布是因为神经元的输入通常是服从正态分布的尤其是在batchnorm以后。在这种情况下随着x的输入越小那么输入被“丢弃”的概率会更高因此这个函数应用在输入的x是随机的并且在一定程度上依赖于输入。最终定义的GELU为G E L U ( x ) x P ( X x ) x Φ ( x ) x ⋅ 1 2 [ 1 e r f ( x 2 ) ] GELU(x) xP(Xx)x\Phi(x)x\cdot{\frac 12}[1erf(\frac x{\sqrt2})]GELU(x)xP(Xx)xΦ(x)x⋅21​[1erf(2​x​)]还有一个近似0.5 x ( 1 t a n h [ 2 π ( x 0.044715 x 3 ) ] ) 0.5x(1tanh[\sqrt{\frac 2 \pi}(x0.044715x^3)])0.5x(1tanh[π2​​(x0.044715x3)])在pytorch中可以按照如下方式进行验证defxyplot(x_vals,y_vals,name):plt.figure()plt.rcParams[figure.figsize](5,3.5)plt.plot(x_vals.detach().numpy(),y_vals.detach().numpy(),labelname,linewidth1.5,color#FF0000)plt.grid(True,linestyle:)plt.legend(locupper left)# dark_background, seaborn, ggplotplt.style.use(seaborn)axplt.gca()ax.spines[right].set_color(none)ax.spines[top].set_color(none)ax.spines[bottom].set_position((data,0))ax.spines[left].set_position((data,0))ax.spines[bottom].set_linewidth(0.5)ax.spines[left].set_linewidth(0.5)ax.xaxis.set_ticks_position(bottom)ax.yaxis.set_ticks_position(left)plt.savefig(func_pic_res{}.jpg.format(name))deftest_GELU():xtorch.arange(-10.0,10.0,0.1,requires_gradTrue)yF.gelu(x)xyplot(x,y,GELU)# 导数y.sum().backward()xyplot(x,x.grad,grad of GELU)defgelu(x):returnx*0.5*(1.0torch.erf(x/math.sqrt(2.0)))deftest_GLUE2():xtorch.arange(-10.0,10.0,0.1,requires_gradTrue)ygelu(x)xyplot(x,y,GELU2)# 导数y.sum().backward()xyplot(x,x.grad,grad of GELU2)最后测试得到的图如下所示这是使用pytoch内置GELU得到的图这是按照论文公式得到的图4. 结论接下来论文都是讲述一些实验了要是感兴趣的小伙伴可以自己去研究下哈总的结论就是作者对这个激活函数进行大量的实验GELU的准确性超过了ELU和ReLU所以想要可以成为非线性激活函数的一个替代方案。