【Pytorch】功能性模块:(8)一文理解常用激活函数(Sigmoid,ReLU,ELU,GELU...)
一文理解常用激活函数1. Sigmoid公式Sigmoid(x)11exp(−x)\text{Sigmoid}(x) \frac{1}{1 \exp(-x)}Sigmoid(x)1exp(−x)1Sigmoid的函数形状如下图所示:对应的导数形式如下图所示Sigmoid函数的优点便于求导可以看到Sigmoid的梯度是平滑的函数能够压缩数据数据会压缩在0-1之间适合用于前向传播Sigmoid函数的缺点容易出现梯度消失Sigmoid的输出不是0均值幂函数计算相对比较耗时2. Tanh公式Tanh(x)tanh(x)exp(x)−exp(−x)exp(x)exp(−x)\text{Tanh}(x) \tanh(x) \frac{\exp(x) - \exp(-x)}{\exp(x) \exp(-x)}Tanh(x)tanh(x)exp(x)exp(−x)exp(x)−exp(−x)Tanh的函数形状如下图所示:对应的导数形式如下图所示tanh函数的优点将数据收敛到-11之间并且输出是0均值收敛速度比Sigmoid函数更快tanh函数的缺点仍然存在梯度消失的问题仍然存在幂指數运算计算成本很高3. ReLU公式f(x)max(0,x)f(x)\max(0, x)f(x)max(0,x)ReLU的函数形状如下图所示:对应的导数形式如下图所示ReLU函数的优点收敛速度更快解决了一部分梯度消失的问题ReLU函数的缺点没有完全解决梯度消失的问题在x轴为负的部分神经元的梯度始终为0,相当于神经元一旦失活后就不会被激活4. LeakyReLU公式LeakyReLU(x)max(0,x)negative_slope∗min(0,x)\text{LeakyReLU}(x) \max(0, x) \text{negative\_slope} * \min(0, x)LeakyReLU(x)max(0,x)negative_slope∗min(0,x)LeakyReLU的函数形状如下图所示:对应的导数形式如下图所示LeakyReLU函数的优点解决了ReLU中神经一旦失活就无法再次激活的问题LeakyReLU函数的缺点无法为正负输入值提供一致的关系预测可以看到不同区间的函数是不一致的5. ELU公式ELU(x)max(0,x)min(0,α∗(exp(x)−1))\text{ELU}(x) \max(0,x) \min(0, \alpha * (\exp(x) - 1))ELU(x)max(0,x)min(0,α∗(exp(x)−1))ELU的函数形状如下图所示:对应的导数形式如下图所示ELU函数的优点有ReLU所有的优点ELU函数的缺点计算相较ReLU来说会比较复杂效果也不一定比ELU好6. GELU公式GELU(x)x∗Φ(x)\text{GELU}(x) x * \Phi(x)GELU(x)x∗Φ(x)Φ(x)\Phi(x)Φ(x)is the Cumulative Distribution Function for Gaussian DistributionGELU的函数形状如下图所示:对应的导数形式如下图所示GELU函数的优点之前描述的所有的激活函数正则化和激活函数是分开进行的GELU是同时进行正则化和激活函数GELU函数的缺点暂无等待补充PS 上述图例代码importtorchimportmatplotlib.pylabaspltimporttorch.nn.functionalasFimportos func_pic_res./func_pic_res/ifnotos.path.exists(func_pic_res):os.makedirs(func_pic_res)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))# sigmoid激活函数deftest_Sigmoid():xtorch.arange(-10.0,10.0,0.1,requires_gradTrue)yx.sigmoid()xyplot(x,y,Sigmoid)# 导数y.sum().backward()xyplot(x,x.grad,grad of Sigmoid)deftest_Tanh():xtorch.arange(-10.0,10.0,0.1,requires_gradTrue)yx.tanh()xyplot(x,y,Tanh)# 导数y.sum().backward()xyplot(x,x.grad,grad of Tanh)deftest_ReLU():xtorch.arange(-10.0,10.0,0.1,requires_gradTrue)yx.relu()xyplot(x,y,ReLU)# 导数y.sum().backward()xyplot(x,x.grad,grad of ReLU)deftest_LeakyReLU():xtorch.arange(-10.0,10.0,0.1,requires_gradTrue)yF.leaky_relu(x,negative_slope0.1,inplaceFalse)xyplot(x,y,LeakyReLU(negative_slope0.1))# 导数y.sum().backward()xyplot(x,x.grad,grad of LeakyReLU(negative_slope0.1))deftest_ELU():xtorch.arange(-10.0,10.0,0.1,requires_gradTrue)yF.elu(x,alpha0.3,inplaceFalse)xyplot(x,y,ELU(alpha0.3))# 导数y.sum().backward()xyplot(x,x.grad,grad of ELU(alpha0.3))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)if__name____main__:test_Sigmoid()test_Tanh()test_ReLU()test_LeakyReLU()test_ELU()test_GELU()