神经网络常见激活函数-sigmoid函数
sigmoid
1 函数+求导
-
sigmoid
函数
σ ( x ) = 1 1 + e ( − x ) \sigma(x) = \frac{1}{1+e^{(-x)}} σ(x)=1+e(−x)1 -
sigmoid
函数求导
d d x σ ( x ) = d d x ( 1 1 + e − x ) = e − x ( 1 + e − x ) 2 = ( 1 + e − x ) − 1 ( 1 + e − x ) 2 = 1 1 + e − x − 1 ( 1 + e − x ) 2 = σ ( x ) − σ ( x ) 2 = σ ( x ) ( 1 − σ ( x ) ) \begin{aligned} \frac{d}{dx}\sigma(x) & = \frac{d}{dx}\left( \frac{1}{1+e^{-x}} \right) \\ & = \frac{e^{-x}}{(1+e^{-x})^2} \\ & = \frac{(1+e^{-x})-1}{(1+e^{-x})^2} \\ & = \frac{1}{1+e^{-x}} - \frac{1}{(1+e^{-x})^2} \\ & = \sigma(x)-\sigma(x)^2 \\ & = \sigma(x)(1-\sigma(x)) \end{aligned} dxdσ(x)=dxd(1+e−x1)=(1+e−x)2e−x=(1+e−x)2(1+e−x)−1=1+e−x1−(1+e−x)21=σ(x)−σ(x)2=σ(x)(1−σ(x))
在神经网络的梯度计算中,通过缓存每层的 Sigmoid 函数输出值,即可在需 要的时候计算出其导数.
2 函数和导函数图像
-
画图
import pandas as pd import numpy as np from matplotlib import pyplot as plt def sigmoid(x): return 1/(1+np.exp(-x)) x = np.linspace(-4,4,1000) y = [sigmoid(i) for i in x] y1 = [sigmoid(i)*(1-sigmoid(i)) for i in x] y2 = [1 for i in x] ax = plt.gca() plt.plot(x,y,label='Sigmoid') plt.plot(x,y1,label='Derivative') plt.plot(x,y2,color='black',linestyle='--') #设置上边和右边无边框 ax.spines['right'].set_color('none') ax.spines['top'].set_color('none') #设置x坐标刻度数字或名称的位置 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.legend(loc = 6)
3 优缺点
-
sigmoid 函数优点:
-
值域为 [ 0 , 1 ] [0,1] [0,1],适合输出概率值:
sigmoid
函数的值域为 ( 0 , 1 ) (0,1) (0,1),非常适合作为模型的输出函数,用于输出 ( 0 , 1 ) (0,1) (0,1) 范围内的概率值。它可以用于将预测概率作为输出的模型(如风控中的评分卡、逻辑回归等),例如表示二分类的类别概率或置信度。 -
输出值限定在 0 到 1,对神经元输出进行归一化:
由于
sigmoid
函数的输出范围是 ( 0 , 1 ) (0,1) (0,1),它对每个神经元的输出进行了“软”归一化,将任意实数输入压缩到 ( 0 , 1 ) (0,1) (0,1) 之间。(这里注意sigmoid和softmax的区别,经过sigmoid的所有输出加起来不等于1) -
连续可导,提供平滑的梯度值:
sigmoid
函数是连续可导的(即可微),能够提供非常平滑的梯度值,防止模型训练过程中出现突变的梯度(即避免“跳跃”的输出值)。
-
-
sigmoid 函数缺点:
- 梯度消失问题:从
sigmoid
函数的导数图像可以看出,其导数的最大值只有 0.25。当输入 x x x 在 [ − 5 , 5 ] [-5,5] [−5,5] 的范围之外时,导数值几乎接近于 0。这种情况会导致训练过程中神经元处于饱和状态(即导数趋于 0),反向传播时权重几乎得不到更新,从而使得模型难以训练,这种现象被称为梯度消失问题。 - 输出不以 0 为中心:
sigmoid
函数的输出总是大于 0(即不以 0 为中心),这会降低权重更新的效率。下一层神经元会接收到上一层输出的全正信号作为输入,导致权重更新时出现“zig-zag”现象。因此,sigmoid
激活函数通常不适合放在神经网络的隐藏层,而一般用于最后的输出层。 - 计算量大及计算复杂度高:
sigmoid
函数需要进行指数运算,计算量较大且计算复杂度高,训练耗时。此外,随着输入值的增大,sigmoid
函数的导数会迅速减小,容易产生梯度消失问题。
- 梯度消失问题:从
-
补充说明:
- 梯度消失问题:
sigmoid
函数在深层神经网络中容易导致梯度消失问题,但在浅层网络或输出层中使用时,这个问题的影响相对较小。因此,sigmoid
函数通常用于输出层,而不是隐藏层。** - 替代方案:在现代深度学习中,
ReLU
(Rectified Linear Unit)及其变体(如Leaky ReLU
、ELU
等)通常被用作隐藏层的激活函数,因为它们能够有效缓解梯度消失问题,并且计算速度更快。 - zig-zag 现象:具体来说,当激活函数的输出不以 0 为中心(如
sigmoid
函数的输出总是大于 0),会导致反向传播时梯度的更新方向不一致,从而使得权重在优化过程中沿着“锯齿形”路径缓慢收敛。
- 梯度消失问题:
4 pytorch 中的sigmoid函数
-
代码
import torch f = torch.nn.Sigmoid() x = torch.randn(2) sigmoid_x = f(x) print(f"x: \n{x}") print(f"sigmoid_x:\n{sigmoid_x}") """输出""" x: tensor([ 0.0259, -2.4006]) sigmoid_x: tensor([0.5065, 0.0831])
5 tensorflow中的sigmoid函数
-
代码
python: 3.10.9
tensorflow: 2.18.0
import tensorflow as tf f = tf.nn.sigmoid x = tf.random.normal([2]) sigmoid_x = f(x) print(f"x: \n{x}") print(f"sigmoid_x:\n{sigmoid_x}") """输出""" x: [-1.2805938 -1.4400458] sigmoid_x: [0.21744916 0.19153824]