前言
在前文中笔者为大家讲解了一下还算较为常见(但不是常用哈)的Tanh激活函数和常见且常用的Sigmoid激活函数,那么今天笔者就带大家来了解学习一下在深度学习中经常被用来替代Sigmoid激活函数的Relu激活函数 。
一、定义和简介
ReLU(Rectified Linear Unit,修正线性单元)激活函数是深度学习中最常用的激活函数之一。它的简单形式和有效性使其在许多神经网络结构中都得到了广泛的应用,特别是在卷积神经网络(CNN)中。
1. 数学表达式
ReLU函数的数学表达式为:
<math xmlns="http://www.w3.org/1998/Math/MathML"> ReLU ( x ) = max ( 0 , x ) \text{ReLU}(x) = \max(0, x) </math>ReLU(x)=max(0,x)
其中该公式可以分解为下面这两部分来理解(可以结合下文函数图像理解分析):
-
当 <math xmlns="http://www.w3.org/1998/Math/MathML"> x ≥ 0 x \geq 0 </math>x≥0 时 :函数的输出等于输入 <math xmlns="http://www.w3.org/1998/Math/MathML"> x x </math>x 本身,即 <math xmlns="http://www.w3.org/1998/Math/MathML"> f ( x ) = x f(x) = x </math>f(x)=x。这意味着如果输入值是非负的,ReLU函数不会对输入值进行任何修改,直接将其传递到下一层。
-
当 <math xmlns="http://www.w3.org/1998/Math/MathML"> x < 0 x < 0 </math>x<0 时 :函数的输出为0,即 <math xmlns="http://www.w3.org/1998/Math/MathML"> f ( x ) = 0 f(x) = 0 </math>f(x)=0。这意味着如果输入值是负的,ReLU函数会将输出置为0。
这种设计使得ReLU函数具有很好的特性,如计算效率高、能够缓解梯度消失问题等。同时,ReLU函数的输出是非负的,这有助于网络学习到更加稀疏的特征表示。(之所以能缓解梯度消失的问题,是因为该函数在趋近于正无穷和负无穷时函数的斜率,也就是梯度,不会像Sigmoid一样一直为0进而导致梯度消失问题)
2. 函数图像
那么既然都已经提到这个图像了,顺带就把这个函数的导数(梯度)也一起讲了吧
ReLU函数的导数(用于反向传播算法中计算梯度)非常直观:
<math xmlns="http://www.w3.org/1998/Math/MathML"> ReLU ′ ( x ) = { 1 if x > 0 0 if x ≤ 0 \text{ReLU}'(x) = \begin{cases} 1 & \text{if } x > 0 \\ 0 & \text{if } x \leq 0 \end{cases} </math>ReLU′(x)={10if x>0if x≤0
- 当 <math xmlns="http://www.w3.org/1998/Math/MathML"> x > 0 x > 0 </math>x>0 时, <math xmlns="http://www.w3.org/1998/Math/MathML"> f ′ ( x ) = 1 f'(x) = 1 </math>f′(x)=1,因为函数在这一点上的斜率是1。
- 当 <math xmlns="http://www.w3.org/1998/Math/MathML"> x < 0 x < 0 </math>x<0 时, <math xmlns="http://www.w3.org/1998/Math/MathML"> f ′ ( x ) = 0 f'(x) = 0 </math>f′(x)=0,因为函数在这一点上的斜率是0(函数是水平的)。
- 当 <math xmlns="http://www.w3.org/1998/Math/MathML"> x = 0 x = 0 </math>x=0 时,导数可以是0或1,这取决于是否考虑函数在这一点的可微性。在实际应用中,通常将 <math xmlns="http://www.w3.org/1998/Math/MathML"> f ′ ( 0 ) f'(0) </math>f′(0) 设为1,以保持梯度的连续性。
这种分段线性的特性使得了ReLU函数在深度学习中非常受欢迎,尤其是在处理大规模数据集的时候。 在实际应用中,ReLU函数通常用于隐藏层,以引入非线性,使得神经网络能够学习复杂的函数映射。此外,由于其简单的数学形式,ReLU函数在计算上非常高效,有助于加速神经网络的训练过程。
3. ReLU函数的特性
-
输出范围:ReLU函数将输入值映射到 [ 0 , ∞ ) 之间。对于负值输入,输出为0;对于正值输入,输出等于输入值本身。
-
非线性:尽管ReLU函数在正半轴上是线性的,但由于其在负半轴上的截断特性,使其整体上是非线性的。这种非线性有助于神经网络捕捉复杂的模式和特征。(所谓非线性就是两个未知数之间的关系不能用一条直线来表示)
-
计算简单:与Sigmoid和Tanh函数相比,ReLU函数的计算非常简单,只需取输入值和0的最大值,不涉及复杂的指数运算。
-
稀疏激活:ReLU函数会导致部分神经元输出为0,这意味着在某些情况下,网络中的一些神经元不会被激活。这种稀疏激活特性有助于减少模型的复杂度,提高训练效率。
-
缓解梯度消失问题:相比于Sigmoid和Tanh函数,ReLU函数在正值区域的梯度为1,有效地缓解了梯度消失问题,使得深层神经网络更容易训练。
二、 应用场景
1. 卷积神经网络(CNN) :
- 增加非线性: CNN是一种专门用于处理具有网格结构的数据(如图像)的神经网络。在CNN中,ReLU激活函数广泛用于卷积 层和全连接层之后,以增加模型的非线性特性。
- 图像分类:CNN结合ReLU在图像分类任务中非常成功,如识别图像中的对象。
简例 : 使用ReLU的简单CNN模型(图像分类)
python
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense, ReLU, Dropout
# 构建一个简单的CNN模型
model = Sequential([
Conv2D(32, kernel_size=(3, 3), activation='relu', input_shape=(28, 28, 1)),
MaxPooling2D(pool_size=(2, 2)),
Conv2D(64, kernel_size=(3, 3), activation='relu'),
MaxPooling2D(pool_size=(2, 2)),
Flatten(),
Dense(128, activation='relu'),
Dropout(0.5),
Dense(10, activation='softmax') # 假设有10个类别
])
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
model.summary()
在这个例子中,我们构建了一个简单的CNN模型,用于处理28x28像素的单通道图像(如MNIST数据集)。模型包括两个卷积层,每个卷积层后面都跟着一个ReLU激活函数和一个最大池化层。最后是一个全连接层,其中也使用了ReLU激活函数。
2. 全连接层:ReLU函数也常用于全连接层,以提高模型的非线性表示能力。
3. 生成对抗网络(GAN):在一些生成对抗网络中,ReLU函数也被用作激活函数。
简例 : 使用ReLU的GAN模型
python
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, ReLU
# 定义生成器
generator = Sequential([
Dense(256, input_dim=100),
ReLU(),
Dense(512),
ReLU(),
Dense(1024),
ReLU(),
Dense(28*28, activation='tanh') # 假设生成28x28像素的图像
])
# 定义判别器
discriminator = Sequential([
Dense(1024, input_dim=28*28),
ReLU(),
Dense(512),
ReLU(),
Dense(256),
ReLU(),
Dense(1, activation='sigmoid') # 二分类问题
])
# 编译判别器
discriminator.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
# 编译生成器
z = tf.keras.Input(shape=(100,))
img = generator(z)
valid = discriminator(img)
generator.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
# 定义和编译GAN
# ...
在这个例子中,我们定义了一个简单的生成器和一个判别器。生成器使用ReLU激活函数生成新的图像,判别器也使用ReLU激活函数来判断图像是否真实。在实际应用中,GAN的训练会涉及到同时训练生成器和判别器,这通常通过交替优化两个网络来实现。
这些示例充分展示了ReLU激活函数在不同类型的神经网络中的应用。ReLU因其简单和有效而被广泛使用,是深度学习中的重要组件。
三、函数其他属性与变种
1.不足之处
- 死神经元问题:在训练过程中,如果某个神经元的输入值总是小于或等于0,那么该神经元的输出将始终为0,并且其梯度也为0,这会导致该神经元永远不会被更新。这种现象被称为"死神经元"问题。也就说可能会影响部分神经网络的正常运行。
- 输出非零中心:ReLU函数的输出不是零中心的,这可能导致梯度下降时的收敛速度变慢。
2.变种
为了克服ReLU函数的一些缺点,研究人员提出了多种ReLU的变种:
-
Leaky ReLU:引入一个小的负斜率,使得在负值区域也有一个小的梯度,从而缓解死神经元问题。其数学表达式为:
<math xmlns="http://www.w3.org/1998/Math/MathML"> Leaky ReLU ( x ) = { x if x > 0 α x if x ≤ 0 \text{Leaky ReLU}(x) = \begin{cases} x & \text{if } x > 0 \\ \alpha x & \text{if } x \leq 0 \end{cases} </math>Leaky ReLU(x)={xαxif x>0if x≤0
其中, <math xmlns="http://www.w3.org/1998/Math/MathML"> α \alpha </math>α 是一个小的常数,一般取值为0.01。
-
Exponential Linear Unit (ELU):在负值区域使用指数函数,使得输出更接近零均值,从而提高训练速度。其数学表达式为:
<math xmlns="http://www.w3.org/1998/Math/MathML"> ELU ( x ) = { x if x > 0 α ( e x − 1 ) if x ≤ 0 \text{ELU}(x) = \begin{cases} x & \text{if } x > 0 \\ \alpha (e^x - 1) & \text{if } x \leq 0 \end{cases} </math>ELU(x)={xα(ex−1)if x>0if x≤0
其中, <math xmlns="http://www.w3.org/1998/Math/MathML"> α \alpha </math>α 是一个超参数。
四、总结
ReLU激活函数因其计算简单、高效,以及在缓解梯度消失问题上的优势,成为了我们深度学习中最常用的激活函数之一。尽管存在一些缺点,如死神经元问题,但通过引入各种变种(如Leaky ReLU、PReLU、ELU),我们还是可以有效地克服这些问题的。并且,理解ReLU函数及其变种对于掌握神经网络的设计和优化是至关重要!
五、Reference
以上就是笔者关于人工智能深度学习Relu激活函数的讲解,欢迎大家点赞,收藏,交流和关注,O(∩_∩)O谢谢!