chap4 多层感知机(2)

模型选择、欠拟合和过拟合

作为机器学习科学家,我们的目标是发现模式(pattern)。但是,我们如何才能确定模型是真正发现了一种泛化的模式,而不是简单地记住了数据呢?例如,我们想要在患者的基因数据与痴呆状态之间寻找模式,其中标签是从集合 { 痴呆,轻度认知障碍,健康 } 中提取的。因为基因可以唯一确定每个个体(不考虑双胞胎),所以在这个任务中是有可能记住整个数据集的。

将模型在训练数据上拟合得比在潜在分布中更接近的现象称为过拟合(overfitting),用于对抗过拟合的技术称为正则化(regularization)。

训练/泛化误差

  • 训练误差:模型在训练数据上的误差

  • 泛化误差:模型在新数据上的误差

数据集

  • 训练数据集:训练模型参数

  • 验证数据集:一个用来评估模型好坏的数据集。

    • 例如拿出 50% 的训练数据
    • 不要和训练数据混在一起
    • 用来不断调整超参数。验证集上的精度不能准确代表模型在新数据上的泛化能力。
  • 测试数据集:只用一次的数据集。

K-则交叉验证

  • 背景:没有足够多的数据使用

  • 算法:

    • 将训练数据分割成 k 块

    • for i=1,…,k

      • 使用第 i 块作为验证数据集,其余作为训练数据集
    • 报告 k 个验证集误差的平均

  • 常用 k=5 或 10

过/欠拟合

模型容量\数据 简单 复杂
正常 欠拟合
过拟合 正常

模型容量

  • 拟合各种函数的能力
  • 低容量的模型难以拟合训练数据
  • 高容量的模型可以记住所有的训练数据

模型复杂度对欠拟合和过拟合的影响

估计模型的容量

  • 难以在不同的种类算法之间比较

    • 例如树模型和神经网络
  • 给定一个模型种类,将有两个主要因素

    • 参数的个数:例如,单层感知机和多层感知机
    • 参数值的选择范围
  • VC 维

    • 统计学习理论的一个核心思想
    • 对于一个分类模型,VC 等于一个最大的数据集的大小,不管如何给定标号,都存在一个模型来对它进行完美分类。换句话说,模型的容量等于它能完美学习(记住)的最大的数据集
    • 例如,二维输入的感知机,VC 维 = 3(能支持分类任意三个点,但不支持 4 个(XOR));支持 N 维输入的感知机的 VC 维 = N+1;一些多层感知机的 VC 维 = O(Nlog2N)O(Nlog_2N)
    • 用处:
      • 提供一个评价模型好坏的理论依据:可以衡量训练误差和泛化误差之间的间隔。
      • 在深度学习中很少使用:衡量不准确,计算困难

数据复杂度

  • 样本个数
  • 每个样本的元素个数
  • 时间/空间结构
  • 多样性
  • … 多个重要因素

权重衰退

是一种常见的处理过拟合的方法。

使用均方范数作为硬性限制

  • 通过限制参数值的选择范围来控制模型容量

    min l(w,b) subject to w2θmin~l(\mathbf{w},b) \space subject \space to ~ ||\mathbf{w}||^2\le\theta

  • 通常不限制偏移 b(限制与否都差不多)

  • 小的 θ\theta 意味着更强的正则项

使用均方范数作为柔性限制

  • 对每个 $\theta $,都可以找到 λ\lambda 使得之前的目标函数等价于下面:

    min l(w,b)+λ2w2min~l(\mathbf{w},b)+\frac{\lambda}{2}||\mathbf{w}||^2

  • 超参数 $\lambda $ 控制了正则项的重要程度

    = 0:无作用

    趋于无穷大,w* -> 0

参数更新法则

wt+1=(1ηλ)wtηl(wt,bt)wt\mathbf{w_{t+1}}=(1-\eta\lambda)\mathbf{w_t}-\eta\frac{\partial l(\mathbf{w_t},b_t)}{\partial \mathbf{w_t}}

  • 通常 ηλ<1\eta\lambda <1,在深度学习中通常叫做权重衰退。

总结

  • 权重衰退通过 L2 正则项使得模型参数不会过大,从而控制模型复杂度
  • 正则项权重是控制模型复杂度的超参数

丢弃法

是一种常见的处理过拟合的方法。

动机:

  • 一个好的模型需要对输入数据的扰动鲁棒
  • 使用有噪音的数据等价于 Tikhonov 正则
  • 丢弃法:在层之间加入噪音

那么关键的挑战就是如何注入这种噪声。一种想法是以一种无偏的方式注入噪声。这样在固定住其他层时,每一层的期望值等于没有噪音时的值。

即,预期是 E[x]=xE[\mathbf{x}'] = \mathbf{x}

定义

在标准dropout正则化中,通过按保留(未丢弃)的节点的分数进行归一化来消除每一层的偏差。换言之,每个中间激活值hh丢弃概率pp由随机变量hh'替换,如下所示:

h={0 概率为 ph1p 其他情况\begin{aligned} h' = \begin{cases} 0 & \text{ 概率为 } p \\ \frac{h}{1-p} & \text{ 其他情况} \end{cases} \end{aligned}

根据设计,期望值保持不变,即E[h]=hE[h'] = h

使用丢弃法

通常作用在隐藏全连接层的输出上

h=σ(W1x+b1)h=dropout(h)o=W2h+b2y=softmax(o)\bf{h}=\sigma(W_1x+b_1)\\ \bf{h'}=dropout(h)\\ \bf{o}=W_2h'+b_2\\ \bf{y}=softmax(o)

正则项只在训练过程中使用:他们影响模型参数的更新

在测试(推理)过程中,丢弃法直接返回输入,保证确定性的输出。

总结

  • 丢弃法将一些输出项随机置零来控制模型复杂度
  • 常作用在多层感知机的隐藏层输出上
  • 丢弃概率是控制模型复杂度的超参数

简洁实现

对于高级API,我们所需要做的就是在每个全连接层之后添加一个Dropout层,将丢弃概率作为唯一的参数传递给它的构造函数。

在训练过程中,Dropout层将根据指定的丢弃概率随机丢弃上一层的输出(相当于下一层的输入)。当不处于训练模式时,Dropout层仅在测试时传递数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
net = nn.Sequential(nn.Flatten(),
nn.Linear(784, 256),
nn.ReLU(),
# 在第一个全连接层之后添加一个dropout层
nn.Dropout(dropout1),
nn.Linear(256, 256),
nn.ReLU(),
# 在第二个全连接层之后添加一个dropout层
nn.Dropout(dropout2),
nn.Linear(256, 10))

def init_weights(m):
if type(m) == nn.Linear:
nn.init.normal_(m.weight, std=0.01)

net.apply(init_weights);

模型训练和测试

1
2
trainer = torch.optim.SGD(net.parameters(), lr=lr)
d2l.train_ch3(net, train_iter, test_iter, loss, num_epochs, trainer)

Q&A

  1. 神经网络的优点?

    神经网络的本质是一种简洁高效的编程语言,可以解决大规模数据的训练,可以通过卷积提取大量特征。