神经网络(二)——多层感知机(Multilayer Perceptron)
在现实世界中有很多数据无法通过线性变换来表示,可以通过在网络中加入一个或多个隐藏层来克服线性模型的限制,
使其能处理更普遍的函数关系类型。最简单的方法是将许多全连接层堆叠在一起,每一层都输出到上面的层,直到生成最后的输出。可以把前
这个多层感知机有4个输入,3个输出,其隐藏层包含5个隐藏单元。 输入层不涉及任何计算,因此使用此网络产生输出只需要实现隐藏层和输出层的计算。 因此,这个多层感知机中的层数为2。多层感知机在输出层和输入层之间增加一个或多个全连接隐藏层,并通过激活函数转换隐藏层的输出。
一、激活函数
激活函数(activation function)通过计算加权和,并加上偏置来确定神经元是否应该被激活,它们将输入信号转换为输出的可微运算。大多数激活函数都是非线性的。
1.1 ReLU函数
最受欢迎的激活函数是修正线性单元(Rectified linear
unit,ReLU),因为它实现简单,同时在各种预测任务中表现良好。[ReLU提供了一种非常简单的非线性变换]。给定元素
ReLU函数通过将相应的活性值设为0,仅保留正元素并丢弃所有负元素。
当输入为负时,ReLU函数的导数为0,而当输入为正时,ReLU函数的导数为1。 当输入值精确等于0时,ReLU函数不可导。 在此时,默认使用左侧的导数,即当输入为0时导数为0。
使用ReLU的原因是,它求导表现得特别好:要么让参数消失,要么让参数通过。这使得优化表现得更好,并且ReLU减轻了困扰以往神经网络的梯度消失问题。
ReLU函数有许多变体,包括参数化ReLU(Parameterized ReLU,pReLU)该变体为ReLU添加了一个线性项,因此即使参数是负的,某些信息仍然可以通过:

- 优点:
- 计算简单,收敛速度快。
- 有效缓解梯度消失问题。
- 缺点:
- 梯度为0的死区(如果输入为负,则梯度为0,导致神经元“死亡”)。
1.2 sigmoid函数
对于一个定义域在
sigmoid函数是一个平滑的、可微的阈值单元近似。当想要将输出视作二元分类问题的概率时,sigmoid仍然被广泛用作输出单元上的激活函数(sigmoid可以视为softmax的特例)。然而,sigmoid在隐藏层中已经较少使用,它在大部分时候被更简单、更容易训练的ReLU所取代。当输入接近0时,sigmoid函数接近线性变换。
sigmoid函数的导数为下面的公式:
sigmoid函数以及导数图像如下所示。

当输入为0时,sigmoid函数的导数达到最大值0.25;而输入在任一方向上越远离0点时,导数越接近0。
- 优点:
- 将输入值映射到 (0, 1) 区间,适合用于输出概率。
- 缺点:
- 梯度消失问题(梯度在极端值时非常小,导致训练速度变慢)。
- 输出不以0为中心(可能导致收敛速度慢)。
1.3 tanh函数
与sigmoid函数类似,tanh(双曲正切)函数也能将其输入压缩转换到区间(-1, 1)上。tanh函数的公式如下:
当输入在0附近时,tanh函数接近线性变换。函数的形状类似于sigmoid函数,不同的是tanh函数关于坐标系原点中心对称。
tanh函数的导数是:
tanh函数以及导数图像如下所示。

当输入接近0时,tanh函数的导数接近最大值1。与sigmoid函数图像类似,输入在任一方向上越远离0点,导数越接近0。
- 优点:
- 输出以0为中心,比Sigmoid更适合用于隐藏层。
- 缺点:
- 仍然存在梯度消失问题。
1.4 Softmax函数
Softmax函数是用于多类分类问题的激活函数,在多类分类问题中,超过两个类标签则需要类成员关系。对于长度为
Softmax函数与正常的max函数不同:max函数仅输出最大值,但Softmax函数确保较小的值具有较小的概率,并且不会直接丢弃。Softmax函数的分母结合了原始输出值的所有因子,这意味着Softmax函数获得的各种概率彼此相关。
Softmax函数以及导数图像如下所示。

- 优点:
- 将输入值映射为概率分布,适合多分类任务的输出层。
- 缺点:
- 不适合作为隐藏层的激活函数。
1.5 Swish函数
Swish 的设计受到了 LSTM 和高速网络中gating的sigmoid函数使用的启发。使用相同的gating值来简化gating机制,这称为self-gating。
self-gating的优点在于它只需要简单的标量输入,而普通的gating则需要多个标量输入。这使得诸如Swish之类的self-gated激活函数能够轻松替换以单个标量为输入的激活函数(如:ReLU),而无需更改隐藏容量或参数数量。
Swish函数以及导数图像如下所示。

- 输出范围:负无穷到正无穷
- 优点:
- 在许多任务中表现优于ReLU。
- 具有平滑的非线性特性。
- 缺点:
- 计算复杂度比ReLU高。
1.6 Exponential Linear Unit(ELU)
ELU 的提出也解决了ReLU 的问题。与ReLU相比,ELU有负值,这会使激活的平均值接近零。均值激活接近于零可以使学习更快,因为它们使梯度更接近自然梯度。

- 优点:
- 缓解梯度消失问题。
- 输出均值接近0,有助于加快学习。
- 缺点:
- 计算量比ReLU稍大。
1.7 GAUSSIAN ERROR LINEAR UNIT(GELU)
GELU 是在这篇论文中提出的,它定义函数为:
其中
近似计算公式
计算 GELU 对输入的导数:
其中
GELU 可以使用高斯误差函数计算
1 | |

GELU、ReLU、ELU对比

GELU的优点
GELU的优点是,它在处理负数时不会像ReLU一样将输入裁剪到0,这可能导致梯度消失的问题。
- 具有更光滑的导数:
- GELU函数的导数是连续的,这使得在训练深度神经网络时可以更容易地传播梯度,避免了ReLU函数在 处的导数不连续的问题,从而减少了训练过程中出现的梯度消失问题
- 可以加速收敛:
- GELU函数在激活函数的非线性变换中引入了类似于sigmoid函数的变换,这使得GELU函数的输出可以落在一个更广的范围内,有助于加速模型的收敛速度。
1.7.1 GELU详解
ReLU
激活对于正输入是恒等映射,对于其他输入是零映射(零或恒等映射)。现在,描述一个可以导出
GELU的随机零或恒等映射。假设输入
其中

现在想要以随机(随机)的方式对
上述公式代表特定的输入值
其中


计算
高斯误差函数(erf)是在概率、统计和偏微分方程中出现的一个特殊函数。erf 定义为
使用 erf 来计算
设
通过改变积分的极限来将这个积分分成两部分,像这样:
代入
由上面可视化
想要以
创建一个确定性函数
上述定义了一个随机正则器,它以
这正是 GELU 激活函数。
计算导数
其中
1.8 总结
基于ReLU的激活函数(包括ReLU本身),它们在几乎所有任务中都经过了实证,证明非常有效。之后,尝试为隐藏层选择其他激活函数,可能是多层的不同激活函数,以观察性能的变化。
神经网络架构、机器学习任务等都会影响激活函数的选择。例如,如果任务是二元分类,则sigmoid激活函数是一个很好的选择,但对于多类分类,softmax函数更好,因为它将输出每个类别的概率表示。
在卷积神经网络中,可以使用基于ReLU的激活函数来提高收敛速度。然而,一些架构需要特定的激活函数。例如,循环神经网络架构和长短期记忆网络架构使用sigmoid函数和tanh函数,它们的逻辑门式架构如果使用ReLU则无法工作。
实际应用中,可以通过实验和调参来确定最适合的激活函数。
1.9 pytorch实现MLP
1 | |

二、欠拟合和过拟合
训练误差和验证误差都很严重, 但它们之间仅有一点差距。 如果模型不能降低训练误差,这可能意味着模型过于简单(即表达能力不足), 无法捕获试图学习的模式。 此外,由于训练和验证误差之间的泛化误差很小, 有理由相信可以用一个更复杂的模型降低训练误差。 这种现象被称为欠拟合(underfitting)。训练误差明显低于验证误差时要小心, 这表明严重的过拟合(overfitting)。
- 在跨层连接上,不同于ResNet中将输入与输出相加,稠密连接网络(DenseNet)在通道维上连结输入与输出。
- DenseNet的主要构建模块是稠密块和过渡层。
- 在构建DenseNet时,我们需要通过添加过渡层来控制网络的维数,从而再次减少通道的数量。
线性代数中最有用的一些运算符是范数(norm)。非正式地说,向量的范数是表示一个向量有多大。这里考虑的大小(size)概念不涉及维度,而是分量的大小。
在线性代数中,向量范数是将向量映射到标量的函数
第二个性质是熟悉的三角不等式:
第三个性质简单地说范数必须是非负的:
这是有道理的。因为在大多数情况下,任何东西的最小的大小是0。最后一个性质要求范数最小为0,当且仅当向量全由0组成。
范数听起来很像距离的度量。欧几里得距离和毕达哥拉斯定理中的非负性概念和三角不等式可能会给出一些启发。事实上,欧几里得距离是一个
其中,在
在代码中,我们可以按如下方式计算向量的
1 | |
深度学习中更经常地使用
与
类似于向量的
Frobenius范数满足向量范数的所有性质,它就像是矩阵形向量的
1 | |
2.2 权重衰减
在训练参数化机器学习模型时,权重衰减(weight
decay)是最广泛使用的正则化的技术之一,它通常也被称为
通过线性函数
损失:
加入正则化的损失:
除以
为什么首先使用
根据估计值与观测值之间的差异来更新
2.3 pytorch代码示例
用如下公式生成数据:
1 | |
定义训练过程
1 | |
忽略正则化
1 | |

使用权重衰减
1 | |

三、Dropout
在训练过程中,在计算后续层之前向网络的每一层注入噪声。因为当训练一个有多层的深层网络时,注入噪声只会在输入-输出映射上增强平滑性。这个想法被称为暂退法(dropout)。暂退法在前向传播过程中,计算每一内部层的同时注入噪声,这已经成为训练神经网络的常用技术。这种方法之所以被称为暂退法,因为从表面上看是在训练过程中丢弃(drop out)一些神经元。在整个训练过程的每一次迭代中,标准暂退法包括在计算下一层之前将当前层中的一些节点置零。
将Dropout应用到隐藏层,以
3.1 代码示例
加载数据
1 | |
定义模型
1 | |
训练
1 | |

Dropout在前向传播过程中,计算每一内部层的同时丢弃一些神经元。Dropout可以避免过拟合,它通常与控制权重向量的维数和大小结合使用的。Dropout仅在训练期间使用。
四、前向传播和反向传播
4.1 前向传播
前向传播(forward propagation或forward pass)指的是:按顺序(从输入层到输出层)计算和存储神经网络中每层的结果。
为了简单起见,假设输入样本是
其中
隐藏变量
假设损失函数为
根据
其中矩阵的Frobenius范数是将矩阵展平为向量后应用的
将
计算图有助于我们可视化计算中操作符和变量的依赖关系。下图与上述简单网络相对应的计算图,其中正方形表示变量,圆圈表示操作符。左下角表示输入,右上角表示输出。注意显示数据流的箭头方向主要是向右和向上的。
4.2 反向传播
反向传播(backward
propagation或backpropagation)指的是计算神经网络参数梯度的方法。简言之,该方法根据微积分中的链式规则,按相反的顺序从输出层到输入层遍历网络。该算法存储了计算某些参数梯度时所需的任何中间变量(偏导数)。假设函数
在这里,使用
回想一下,在前向传播计算图中的单隐藏层简单网络的参数是
接下来,根据链式法则计算目标函数关于输出层变量
接下来,计算正则化项相对于两个参数的梯度:
现在可以计算最接近输出层的模型参数的梯度
为了获得关于
由于激活函数
最后,可以得到最接近输入层的模型参数的梯度
4.3 训练神经网络
在训练神经网络时,前向传播和反向传播相互依赖。对于前向传播,沿着依赖的方向遍历计算图并计算其路径上的所有变量。然后将这些用于反向传播,其中计算顺序与计算图的相反。

蓝色的过程叫 Forward Pass,红色的过程叫 Backward Pass,整个过程叫 Backpropagation
以上述简单网络为例:一方面,在前向传播期间计算正则项取决于模型参数
因此,在训练神经网络时,在初始化模型参数后,交替使用前向传播和反向传播,利用反向传播给出的梯度来更新模型参数。反向传播重复利用前向传播中存储的中间值,以避免重复计算。带来的影响之一是需要保留中间值,直到反向传播完成。这也是训练比单纯的预测需要更多的内存(显存)的原因之一。此外,这些中间值的大小与网络层的数量和批量的大小大致成正比。因此,使用更大的批量来训练更深层次的网络更容易导致内存不足(out of memory)错误。
五、梯度消失和梯度爆炸
考虑一个具有
网络可以表示为:
如果所有隐藏变量和输入都是向量,可以将
换言之,该梯度是
不稳定梯度带来的风险不止在于数值表示;不稳定梯度也威胁到优化算法的稳定性。可能面临一些问题。要么是梯度爆炸(gradient exploding)问题:参数更新过大,破坏了模型的稳定收敛;要么是梯度消失(gradient vanishing)问题:参数更新过小,在每次更新时几乎不会移动,导致模型无法学习。
5.1 梯度消失
sigmoid是导致梯度消失问题的一个常见的原因

正如上图,当sigmoid函数的输入很大或是很小时,它的梯度都会消失。此外,当反向传播通过许多层时,整个乘积的梯度可能会消失。当网络有很多层时,除非很小心,否则在某一层可能会切断梯度。事实上,这个问题曾经困扰着深度网络的训练。因此,更稳定的ReLU系列函数已经成为从业者的默认选择。
5.2 梯度爆炸
相反,梯度爆炸可能同样令人烦恼。为了更好地说明这一点,生成100个高斯随机矩阵,并将它们与某个初始矩阵相乘。对于选择的尺度(方差
1 | |
1 | |
解决(或至少减轻)上述问题的一种方法是进行参数初始化,优化期间的注意和适当的正则化也可以进一步提高稳定性。框架默认使用随机初始化方法,对于中等难度的问题,这种方法通常很有效。Xavier初始化方法在实践中被证明是有效的。
六、前馈神经网络(Feedforward Neural Network, FNN)
多层感知器(MLP, Multi-Layer Perceptron)和前馈神经网络(Feedforward Neural Network, FNN)是深度学习中两个经常被使用的术语,它们经常被互换使用。
多层感知器 (MLP):
MLP
是一个由三种类型的层组成的神经网络:输入层、一个或多个隐藏层和输出层。
每一层都由多个神经元组成,这些神经元与前一层的所有神经元全连接。
MLP 使用非线性激活函数,例如 sigmoid、tanh 或
ReLU,否则多个线性层的组合仍然会是线性的。
MLP 主要用于结构化数据的分类和回归任务。
前馈神经网络 (FNN):
FNN
是一种更为泛化的术语,用于描述数据在网络中单向传播的网络,从输入层到输出层,没有反馈或循环。
MLP 实际上是FNN的一个特例。这意味着所有的 MLP 都是 FNN,但并不是所有的
FNN 都是
MLP。例如,有些前馈神经网络可能包括卷积层或其他特殊类型的层。
FNN的主要特点是它们没有循环或记忆元素,因此与循环神经网络(RNN)和其他包含反馈机制的网络不同。
总结一下,MLP 和 FNN 在许多上下文中可以互换使用,尤其是当我们谈论只有全连接层的网络时。但技术上,MLP 是 FNN 的一个子集,因为FFNN可以包括除全连接层之外的其他类型的层。