神经网络常见激活函数(包含tensorflow2的api)

sigmoid

  • API:tf.nn.softmax
  • Sigmoid又叫作 Logistic 激活函数
  • y = 1 1 + e − x = tanh ( x 2 ) + 1 2 y = \frac{1}{1 + e^{-x}} = \frac{\text{tanh}(\frac{x}{2}) + 1}{2} y=1+ex1=2tanh(2x)+1
    • tanh ( x ) = sinh ( x ) cosh ( x ) = e x − e − x e x + e − x = 2 × sigmoid ( 2 × x ) − 1 \text{tanh}(x) = \frac{\text{sinh}(x)}{\text{cosh}(x)} = \frac{e^x - e^{-x}}{e^x + e^{-x}} = 2 \times \text{sigmoid}(2 \times x) - 1 tanh(x)=cosh(x)sinh(x)=ex+exexex=2×sigmoid(2×x)1
  • 缺点
    • 输出值y不以0为中心
    • exp的计算成本相对来说不低
    • 梯度消失:输出接近0或1的神经元,其梯度接近0,故权重不会更新或更新极小,并且,与此类神经元相连的神经元的权重更新的也很慢
  • 函数、函数导数形状及代码在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
def sigmoid(x):
    """
    sigmoid函数:y = 1 / (1 + e^{-x})
    :param x:
    :return:
    """
    return 1 / (1 + np.exp(-x))

def sigmoid_derivative(x):
    """
    sigmoid函数求导
    """
    x = tf.cast(x, dtype=tf.float32)
    with tf.GradientTape() as tape:
        tape.watch(x)
        # y = 1 / (1 + tf.exp(-x))
        y = tf.sigmoid(x)
    dy_dx = tape.gradient(y, x)
    return dy_dx.numpy()


def plot(x, y, title):
    plt.plot(x, y)
    plt.grid(True)
    plt.title(title)
    plt.show()

x = np.arange(-10, 10, 0.5)
# sigmoid函数
y_sigmoid = sigmoid(x=x)
# sigmoid函数求导
y_sigmoid_derivative = sigmoid_derivative(x=tf.constant(x))
# 独立画图
plot(x, y_sigmoid, title = 'sigmoid function')
plot(x, y_sigmoid_derivative, title = 'sigmoid derivative function')
# 集成画图
fig, ax1 = plt.subplots()
ax2 = ax1.twinx()
ax1.plot(x, y_sigmoid, c='b')
ax2.plot(x, y_sigmoid_derivative, c='r')
plt.grid(True)
plt.title('compare')
plt.show()

Tanh

  • API:tf.nn.tanh,实际是tf.math.tanh
  • 缺点:梯度消失
  • 优点:输出值y以0为中心
  • 函数、函数导数形状及代码
    在这里插入图片描述
def tanh_derivative(x):
    """
    tanh函数求导
    """
    x = tf.cast(x, dtype=tf.float32)
    with tf.GradientTape() as tape:
        tape.watch(x)
        y = tf.tanh(x)
    dy_dx = tape.gradient(y, x)
    return dy_dx.numpy()

ReLU(修正线性单元)

  • API:tf.nn.relu
  • y = m a x ( x , 0 ) y = max(x, 0) y=max(x,0)
  • 缺点
    • 输出值y不以0为中心
    • 死亡 ReLU :前向传导中,当x < 0,则神经元不激活,且该情况下的后向传播中,梯度为0,故权重无更新
    • 不能避免梯度爆炸问题(阈值限制)
  • 优点
    • 由于稀疏性,时间和空间复杂度更低;不涉及成本更高的指数运算
    • 避免梯度消失
  • 函数、函数导数形状及代码
    在这里插入图片描述
def relu(x):
    """
    rele函数:y = max(x, 0)
    :param x:
    :return:
    """
    return np.array([0 if num < 0 else num for num in x])

def relu_derivative(x):
    """
    relu函数求导
    """
    x = tf.cast(x, dtype=tf.float32)
    zeros = tf.fill(dims=x.shape, value=0.0)
    with tf.GradientTape() as tape:
        tape.watch(x)
        y = tf.math.maximum(x, zeros)
    dy_dx = tape.gradient(y, x)
    return dy_dx.numpy()

Leaky ReLU(渗漏型修正线性单元)

  • API:tf.nn.leaky_relu
  • y = m a x ( α × x , x ) y = max(\alpha \times x, x) y=max(α×x,x),一般情况下 0.1 ≤ α ≤ 0.3 0.1 \le \alpha \le 0.3 0.1α0.3
  • 缺点
    • 输出值y不以0为中心
    • 结果不连贯
    • 无法避免梯度爆炸问题;
    • 两部分均为线性(求导结果为常值: α \alpha α和1)
  • 优点
    • 能避免死亡 ReLU 问题,因为其在计算导数时允许较小的梯度
    • 由于不包含指数运算,所以计算速度比 ELU 快
  • 函数、函数导数形状及代码
    在这里插入图片描述

ELU(指数线性单元)

  • API:tf.nn.elu
  • y = x i f x > 0 e l e s α × ( e x − 1 ) y = x \quad if \quad x \gt 0 \quad eles \quad \alpha \times (e^{x} -1) y=xifx>0elesα×(ex1),一般情况下 0.1 ≤ α ≤ 0.3 0.1 \le \alpha \le 0.3 0.1α0.3
  • 缺点
    • 输出值y不以0为中心
    • 由于包含指数运算,所以计算时间更长
    • 无法避免梯度爆炸问题;
    • 两部分均为线性(求导结果为常值: α \alpha α和1)
  • 优点
    • 能避免死亡 ReLU 问题
    • 能得到负值输出,这能帮助网络向正确的方向推动权重和偏置变化
    • 在计算梯度时能得到激活,而不是让它们等于 0。
  • 函数、函数导数形状及代码
    在这里插入图片描述
def elu(x, a=0.2):
    """
    elu函数:y = x if x > 0 else a * (e^x - 1)
    :param x:
    :return:
    """
    return np.array([num if num > 0 else a * (np.exp(num) - 1) for num in x])

SELU(扩展型指数线性单元)

  • API:tf.nn.selu
  • y = λ × x i f x > 0 e l e s λ × α × ( e x − 1 ) y = \lambda \times x \quad if \quad x \gt 0 \quad eles \quad \lambda \times \alpha \times (e^{x} -1) y=λ×xifx>0elesλ×α×(ex1)
  • 说明
    • SELU 函数也需要 lecun_normal 进行权重初始化(网络参数会被初始化一个正态分布)
    • 如果你想使用 dropout,你也必须使用名为 Alpha Dropout 的特殊版本
  • 缺点
    • 输出值y不以0为中心
    • 新激活函数
  • 优点
    • 内部归一化的速度比外部归一化快,这意味着网络能更快收敛
    • 不可能出现梯度消失或爆炸问题
  • 函数、函数导数形状及代码
    在这里插入图片描述
def selu(x, a=1.673263, lam=1.0507):
    """
    rele函数:y = lam * x if x > 0 else lam * a * (e^x - 1)
    :param x:
    :return:
    """
    y = np.array([num if num > 0 else a * (np.exp(num) - 1) for num in x])
    return lam * y

GELU

  • y = 0.5 × x × ( 1 + tanh ⁡ ( 2 π × ( x + 0.044715 × x 3 ) ) ) y = 0.5 \times x \times (1 + \tanh(\sqrt{\frac{2}{\pi}} \times (x + 0.044715 \times x ^ 3))) y=0.5×x×(1+tanh(π2 ×(x+0.044715×x3)))
  • 缺点
    • 输出值y不以0为中心
    • 新激活函数
  • 优点
    • 似乎是 NLP 领域的当前最佳;尤其在 Transformer 模型中表现最好
    • 能避免梯度消失问题
  • 函数、函数导数形状及代码
    在这里插入图片描述
def gelu(x):
    """
    gelu函数
    :param x:
    :return:
    """
    return 0.5 * x * (1 + np.tanh(np.sqrt(2 / np.pi) * (x + 0.044715 * np.power(x, 3))))

def gelu_derivative(x):
    """
    gelu函数求导
    """
    x = tf.cast(x, dtype=tf.float32)
    with tf.GradientTape() as tape:
        tape.watch(x)
        y = 0.5 * x * (1 + tf.math.tanh(tf.math.sqrt(2 / np.pi) * (x + 0.044715 * tf.math.pow(x, 3))))
    dy_dx = tape.gradient(y, x)
    return dy_dx.numpy()

Swish

  • Sigmoid又叫作 Logistic 激活函数
  • y = x 1 + e − x y = \frac{x}{1 + e^{-x}} y=1+exx
  • 缺点
    • 输出值y不以0为中心
    • 新函数
  • 优点:输出可能下降,即使在输入值增大的情况下
  • 函数、函数导数形状及代码
    在这里插入图片描述
def swish(x):
    """
    swish函数:y = x / (1 + e^{-x})
    :param x:
    :return:
    """
    return x / (1 + np.exp(-x))

def swish_derivative(x):
    """
    sigmoid函数求导
    """
    x = tf.cast(x, dtype=tf.float32)
    with tf.GradientTape() as tape:
        tape.watch(x)
        y = x * tf.sigmoid(x)
    dy_dx = tape.gradient(y, x)
    return dy_dx.numpy()

Reference

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值