整流线性单元(Rectified linear unit,ReLU) 是现代神经网络中最常用的激活函数,大多数前馈神经网络默认使用的激活函数,它提供了一种非常简单的非线性变换。给定元素 x
,ReLU 函数被定义为该元素与 0 的最大值。ReLU函数定义如下:
代码:
import numpy as np
import matplotlib.pyplot as plt
# 定义ReLU函数
def relu(x):
return np.maximum(0, x)
# 生成一些输入值,这里可以设置成其他的数值
x_values = np.linspace(-5, 5, 100)
# 计算对应的ReLU输出值
y_values = relu(x_values)
# 绘制ReLU函数的图像
plt.plot(x_values, y_values, label='ReLU Function')
plt.title('ReLU Activation Function')
plt.xlabel('Input')
plt.ylabel('Output')
plt.axhline(0, color='black',linewidth=0.5)
plt.axvline(0, color='black',linewidth=0.5)
plt.grid(color = 'gray', linestyle = '--', linewidth = 0.5)
plt.legend()
plt.show()
生成图像如下:
x > 0
区域上,不会出现梯度饱和、梯度消失的问题,梯度永远是常量;产生这种现象的两个原因:参数初始化不合理;learning rate 太高导致在训练过程中参数更新太大。
sigmoid 函数又称 Logistic 函数,用于隐层神经元输出,它将范围 (-inf,inf) 中的任意输入压缩到区间 (0,1) 中的某个值,可以用来做二分类。sigmoid 函数定义如下:
代码:
# -*-coding:utf-8-*-
import numpy as np
import matplotlib.pyplot as plt
# 定义Sigmoid函数
def sigmoid(x):
return 1 / (1 + np.exp(-x))
# 生成一些输入值
x_values = np.linspace(-7, 7, 200)
# 计算对应的Sigmoid输出值
y_values = sigmoid(x_values)
# 绘制Sigmoid函数的图像
plt.plot(x_values, y_values, label='Sigmoid Function')
plt.title('Sigmoid Activation Function')
plt.xlabel('Input')
plt.ylabel('Output')
plt.axhline(0, color='black',linewidth=0.5)
plt.axvline(0, color='black',linewidth=0.5)
plt.grid(color = 'gray', linestyle = '--', linewidth = 0.5)
plt.legend()
plt.show()
生成图像如下:
Tanh 函数也称为双曲正切函数,取值范围为 (-1,1)。Tanh函数定义如下:
它的导数是:
代码:
import numpy as np
import matplotlib.pyplot as plt
# 定义 tanh 函数
def tanh(x):
return np.tanh(x)
# 定义 tanh 函数的导数
def tanh_derivative(x):
return 1 - np.tanh(x)**2
# 生成一些输入值
x_values = np.linspace(-5, 5, 200)
# 计算 tanh 函数的输出值和导数值
y_tanh = tanh(x_values)
y_derivative = tanh_derivative(x_values)
# 绘制 tanh 函数及其导数在同一坐标轴中的图像
plt.plot(x_values, y_tanh, label='tanh Function')
plt.plot(x_values, y_derivative, label='tanh Derivative')
plt.title('tanh Function and its Derivative')
plt.xlabel('Input')
plt.ylabel('Output / Derivative')
plt.axhline(0, color='black', linewidth=0.5)
plt.axvline(0, color='black', linewidth=0.5)
plt.grid(color='gray', linestyle='--', linewidth=0.5)
plt.legend()
plt.show()
生成图像如下:
Tanh 函数图像及导数图像如上,当输入接近 0 时,Tanh 函数的导数接近最大值 1。可理解为 sigmoid 函数的变形,输入在任一方向上远离 0 点,导数越接近 0。
使用 sigmoid 激活函数可以处理二分类任务,而在处理多分类问题的时,就需要使用 softmax 函数。它将一个实数向量(通常称为 logits)转换为概率分布。
输出规则: 将输入向量中的每个元素转换为一个位于 (0, 1) 之间的值,使得所有元素的和等于 1。这种转换后的好处是向量可以解释为一个概率分布,其中每个元素表示对应类别的概率。softmax 函数公式如下:
import numpy as np
import matplotlib.pyplot as plt
# 定义 Softmax 函数
def softmax(x):
exp_x = np.exp(x)
return exp_x / np.sum(exp_x, axis=-1, keepdims=True)
# 生成一些输入值
x_values = np.linspace(-5, 5, 200)
# 计算对应的 Softmax 输出值
y_values = softmax(x_values)
# 绘制 Softmax 函数的图像
plt.plot(x_values, y_values)
plt.title('Softmax Function')
plt.xlabel('Input')
plt.ylabel('Output Probability')
plt.axhline(0, color='black', linewidth=0.5)
plt.axvline(0, color='black', linewidth=0.5)
plt.grid(color='gray', linestyle='--', linewidth=0.5)
plt.show()
生成图像如下:
渗漏整流线性单元(Leaky ReLU),为了彻底避免 dead ReLU 现象。用一个类似 0.01 的小值来初始化神经元,从而使得 ReLU 在负数区域更偏向于激活而不是死掉。这里的斜率都是确定的,当然,这里的参数是可以调整的。
代码:
import numpy as np
import matplotlib.pyplot as plt
# 定义 Leaky ReLU 函数
def leaky_relu(x, alpha=0.01):
return np.maximum(alpha * x, x)
# 生成一些输入值
x_values = np.linspace(-5, 5, 200)
# 计算对应的 Leaky ReLU 输出值
y_values = leaky_relu(x_values)
# 绘制 Leaky ReLU 函数的图像
plt.plot(x_values, y_values, label='Leaky ReLU Function')
plt.title('Leaky ReLU Activation Function')
plt.xlabel('Input')
plt.ylabel('Output')
plt.axhline(0, color='black', linewidth=0.5)
plt.axvline(0, color='black', linewidth=0.5)
plt.grid(color='gray', linestyle='--', linewidth=0.5)
plt.legend()
plt.show()
参数整流线性单元(Parametric Rectified linear unit,PReLU),用来解决 ReLU 带来的神经元坏死的问题。公式如下:
其中,α 不是固定的超参数,通常初始化为一个小的正数,通过反向传播学习。它在输入小于零时允许一个小的斜率,而不是将其置零。
代码:
import numpy as np
import matplotlib.pyplot as plt
# 定义 PReLU 函数
def prelu(x, alpha=0.01):
return np.where(x > 0, x, alpha * x)
# 生成一些输入值
x_values = np.linspace(-5, 5, 200)
# 计算 PReLU 函数的输出值
y_values = prelu(x_values)
# 绘制 PReLU 函数的图像
plt.plot(x_values, y_values, label='PReLU Function')
plt.title('PReLU Activation Function')
plt.xlabel('Input')
plt.ylabel('Output')
plt.axhline(0, color='black',linewidth=0.5)
plt.axvline(0, color='black',linewidth=0.5)
plt.grid(color='gray', linestyle='--', linewidth=0.5)
plt.legend()
plt.show()
区别:Leaky ReLU 和 PReLU 在解决激活函数中的问题(如死亡神经元)上有一些相似之处,但 PReLU 提供了更多的灵活性。
指数线性单元(ELU):具有 ReLU 的优势,没有 Dead ReLU 问题,输出均值接近0,实际上 PReLU 和 Leaky ReLU 都有这一优点。有负数饱和区域,从而对噪声有一些鲁棒性。可以看做是介于 ReLU 和 Leaky ReLU 之间的一个函数。当然,这个函数也需要计算 exp,从而计算量上更大一些。公式如下:
代码:
import numpy as np
import matplotlib.pyplot as plt
# 定义 ELU 函数
def elu(x, alpha=1.0):
return np.where(x > 0, x, alpha * (np.exp(x) - 1))
# 生成一些输入值
x_values = np.linspace(-5, 5, 200)
# 计算 ELU 函数的输出值
y_values = elu(x_values)
# 绘制 ELU 函数的图像
plt.plot(x_values, y_values, label='ELU Function')
plt.title('ELU Activation Function')
plt.xlabel('Input')
plt.ylabel('Output')
plt.axhline(0, color='black', linewidth=0.5)
plt.axvline(0, color='black', linewidth=0.5)
plt.grid(color='gray', linestyle='--', linewidth=0.5)
plt.legend()
plt.show()
ReLU(Rectified Linear Unit):
优势: 计算简单,且在许多情况下表现良好。它将负数部分置为零,有助于网络稀疏性,有利于反向传播。
注意事项: 对于一些极端情况,可能存在“死神经元”问题,即某些神经元在训练过程中永远不会被激活,导致无法更新权重。
Sigmoid 函数:
优势: 将输出限制在 (0, 1) 范围内,适用于二元分类问题。
注意事项: 容易发生梯度消失的问题,尤其是在深层网络中,导致梯度较小的权重无法有效地更新。
Tanh 函数:
优势: 类似于 Sigmoid,但输出范围在 (-1, 1)。对于中心化的数据,Tanh 可能更适合。
注意事项: 仍然存在梯度消失的问题。
Softmax 函数:
优势: 用于多类别分类问题,将输出转化为概率分布。
注意事项: 对于二元分类问题,通常使用 Sigmoid 而不是 Softmax。
Leaky ReLU:
优势: 在 ReLU 的基础上解决了死神经元问题,允许小于零的斜率。
注意事项: 仍然可能存在一些负数输出。
Parametric ReLU (PReLU):
优势: 允许负数部分有可学习的参数。
注意事项: 需要更多的计算资源。