深度学习丨多层感知机
多层感知机概念
多层感知机为最简单的神经网络,由多层神经元构成,每一层的输出成为下一层的输入。
加入隐藏层
单层线性模型所能拟合的情况十分有限,比如无法解决xor问题。为了拟合更复杂的情况,可以将多个全连接层堆叠到一起,每一层的输出成为下一层的输入,直到生成最终的输出,最后一层为输出层,中间层为隐藏层,这种架构即为多层感知机。
激活函数
两个线性层的堆叠形成的仍然是线性层,例如有以下多层感知机,其中X为输入,H为隐藏层变量,O为输出
ReLU函数
ReLU函数实现简单且实际表现良好,因此得以广泛应用。
sigmoid函数
sigmoid函数将输入变换为区间(0,1)上的输出,因此也被成为挤压函数。
- 由于涉及指数运算,需要消耗大量的资源;
- sigmoid的导数值域为(0,0.25],因此在进行反向传播时经过连乘容易发生下溢,造成梯度消失。
在隐藏层中,sigmoid一般被更简单、更容易训练的ReLU所取代。
tanh函数
与sigmoid函数类似,tanh函数将输入压缩到区间(-1,1)上。
多层感知机的手动实现
下面使用Fashion-MNIST数据集尝试实现一个多层感知机,以便更好地理解其原理。Fashion-MNIST数据集中每张图像由28X28=784个灰度像素值组成,所有图像分为10个类别。因此忽略空间结构可以将每张图像视为具有784个输入特征和10个类别的简单分类数据集。本例将实现一个具有单隐藏层的多层感知机,其中包含256个隐藏单元。
1 | batch_size = 256 |
初始化模型参数
在多层感知机中,每一层都需要一个权重矩阵和一个偏置向量。
1 | num_inputs, num_outputs, num_hiddens = 784, 10, 256 |
定义激活函数
采用最常使用的ReLU函数。
1 | def relu(X): |
定义模型
如前所述,我们将输入视为一个长度为784的向量,可以简单定义模型如下:
1 | def net(X): |
训练
多层感知机的训练过程和softmax相同,这里直接调用d2l包中的train_ch3函数,不再手动实现。
1 | num_epochs, lr = 10, 0.1 |
可以看到具有较好的拟合效果。
![epoch][epoch.png]
过拟合
机器学习的目的是发现泛化的模式,也就是模型捕获了总体规律,能适用于没有见过的个体。模型在训练数据上的拟合比在潜在分布的拟合更接近的现象称为过拟合,用于对抗过拟合的技术称为正则化。
模型泛化
出自于训练数据的误差称为训练误差,将模型应用于新数据时的误差称为泛化误差,在实际中,使用测试集来估计泛化误差。(测试集指在确定了所有超参数之后使用的一次性测试数据,在实际应用中,为了在模型选择的过程中判断过拟合,引入验证集来对每轮实验进行测试。)
影响模型泛化的因素有:
- 可调整参数的数量
- 参数的取值范围
- 训练样本的数量
这也是对抗过拟合的几个思路。
K折交叉验证
当训练数据稀缺时,可以采用K折交叉验证的方法:
- 将原始数据划分为K个部分
- 对于i = 1, 2, ..., K
- 使用第i个部分作为验证集,其余部分用于训练
- 报告K个部分在验证时的平均错误
权重衰减
通过收集更多训练数据可以缓解过拟合,但这并不总是容易做到,因此我们需要正则化技术来对抗过拟合。
权重衰减是使用最广泛的正则化技术之一,这项技术通过函数与零的距离来度量函数的复杂度。
一种简单的方法是通过权重向量的某个范数来度量复杂度。要保证权重向量较小,最常用的方法是将其范数作为惩罚项添加到最小化损失中:
权重更新的递推式就变为:
丢弃法
丢弃法又称暂退法,是一种通过在网络各层加入噪声提高函数平滑性,以对抗过拟合的方法。
通常以无偏的方式注入噪声,即:
$$ 期望值保持不变,即E[h']=h。
通俗地理解,即在前向传播的过程中以概率p丢弃一些神经元,并放大未被丢弃的输出来保持无偏。
丢弃法仅在训练期间使用。
数值稳定性
求梯度使用链式求导法则,需要大量的偏导数进行连乘。从而产生梯度爆炸和梯度消失的问题。一个直观的例子:
梯度爆炸
假设现有一个MLP(为简单没有bias):
使用ReLU作为激活函数时,当x>0导数为1,当x<0导数为0。递推可得到其对W_i求导结果为W_i的部分元素和。若选中的是很大的元素,则会导致梯度很大,从而导致模型参数更新过大,破坏了模型的稳定收敛。
梯度消失
深度学习通常使用16位浮点数,多个小于1的偏导数连乘很容易发生数值下溢。例如sigmoid函数的导数上限为0.25,随着网络层数的增长梯度很容易就会消失。
梯度消失面临的问题是:梯度为0或几乎为0,导致参数更新过小,模型无法学习。
稳定性训练
权重初始化
使用适当范围内的随机值初始化权重
训练的开始容易受到数值不稳定的影响
- 远离最优点的表面可能很复杂
- 接近最优点的表面可能更平坦
批量归一化
损失发生在最后一层
- 后面的层可以快速学习
数据插入在第一层
- 底层的变化会向上传递
- 上层需要经过重新学习
- 导致收敛缓慢
因此要想办法避免在学习第一层时改变最后一层。
批量归一化步骤:
- 固定小批量里面的均值和方差(引入噪声避免方差为0)
- 然后再做额外的调整:
批量归一化首先进行标准化,使变量均值趋向于0、方差趋向于1。为保持无偏性,在变化中引入参数γ和β,其中γ用来控制方差,β用来控制均值,这两个参数通过学习得到。
通过挑战,分布变得更加规范,从而防止因分布过散而导致梯度爆炸和梯度消失。(批量归一化发生于激活函数前)