【动手学深度学习v2李沐】学习笔记06:模型选择、欠拟合和过拟合、代码实现

前文回顾:多层感知机、详细代码实现

一、模型选择

首先,我们学习模型选择,如何选择超参数。

1.1 两种误差

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

例子: 根据模考成绩来预测未来考试分数。

  • 在过去的考试中表现很好(训练误差),不代表未来考试一定会好(泛化误差)。

1.2 两种数据集

  • 验证数据集: 一个用来评估模型好坏的数据集。
    • 例如,拿出50%的训练数据集。我们可以用一半的数据集来训练模型,然后在另一半的数据集(验证数据集)上评估误差。如果我们觉得这个超参数的效果不好,我们可以更换超参数,然后再次在验证数据集上评估精度,从而比较两次超参数的好坏。
    • 验证数据集不要和训练数据集混在一起(很重要)。
  • 测试数据集: 只用一次的数据集。
    • 例如,未来的考试。

1.3 K-折交叉验证

  • 在没有足够多的数据使用时,我们可以采用K-折交叉验证。
  • 算法:
    • 将训练数据分割成K块。
    • f o r    i = 1 , ⋯   , K for \; i = 1, \cdots ,K fori=1,,K
      • 使用第 i 块作为验证数据集,其余数据库作为训练数据集。
      • 因此,我们可以分别使用K个不同的数据库作为验证集,进行K次训练和验证。
    • 我们对K次验证得到的误差求平均值,就得到了K-折交叉验证的误差。
  • 常用: K = 5 或 10

1.4 总结

  • 训练数据集: 训练模型参数。
  • 验证数据集: 选择模型超参数。
  • 非大数据集上通常使用K-折交叉验证。

二、过拟合和欠拟合

2.1 过拟合和欠拟合

过拟合和欠拟合的一个简单例子如下:

欠拟合正常过拟合
欠拟合正常过拟合

我们需要根据数据的简单和复杂程度来选择模型容量
通常,处理简单的数据需要比较低的模型容量,来获得一个比较正常的结果。如果在简单的数据上使用了较高的模型容量,就容易产生过拟合。
而对于复杂的数据,我们需要使用较高的模型容量。过低的模型容量可能会导致无法很好地拟合复杂数据,从而导致欠拟合。

模型容量和数据

2.2 模型容量

2.2.1 模型容量定义

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

2.2.2 模型容量的影响

随着模型容量的增加,模型的训练误差逐渐下降,模型会记住更多数据中的信息。但数据中存在噪音,因此泛化误差一开始随模型容量的增加而下降,但到一定程度会反而会上升。因此,模型容量存在一个最优值。
影响

2.3 估计模型容量

我们难以在不同种类的算法之间比较模型容量,例如:树模型和神经网络。
对于一个给定的模型种类,有两个主要因素影响他的模型容量:参数的个数参数值的选择范围

2.3.1 VC维

  • VC维是统计学习理论的一个核心思想。
  • 对于一个分类模型,VC维等价于一个最大的数据集的大小,不管如何给定标号,都存在一个模型来对他进行完美分类。
  • 例如二维输入的单层感知机,它的VC维 = 3。
    • 即能够分类任意三个点,但存在不能分类的四个点。
      二维
  • 支持 N 维输入的感知机的VC维是 N+1
  • 一些多层感知机的VC维是 O ( N log ⁡ 2 N ) O(N \log_2N) O(Nlog2N)

2.3.2 VC维的用处

  • 提供了为什么一个模型好的理论依据。
    • 它可以衡量训练误差和泛化误差之间的间隔。
  • 但是在深度学习中很少使用。
    • 对模型容量的衡量不是很准确。
    • 计算深度学习模型的VC维很困难。

2.4 数据复杂度

  • 对于一个数据,我们可以通过多个因素来衡量其复杂度:
    • 样本个数
    • 每个样本的元素个数
    • 时间、空间结构
    • 多样性

2.5 总结

  • 模型容量需要匹配数据复杂度,否则可能导致欠拟合和过拟合。
  • 统计机器学习提供数学工具来衡量模型复杂度。
  • 实际中一般靠观察训练误差和验证误差。

三、代码实现

我们通过代码来研究一下模型选择和欠拟合、过拟合之间的关系。

import math
import numpy as np
import torch
from torch import nn
from d2l import torch as d2l

3.1 人工数据集

我们通过多项式拟合来探索这些概念,使用一下三阶多项式来生成训练和测试数据的标签:
y = 5 + 1.2 x − 3.4 x 2 2 ! + 5.6 x 3 3 ! + ϵ    w h e r e    ϵ ∼ N ( 0 , 0. 1 2 ) y=5+1.2x-3.4\frac{x^2}{2!}+5.6\frac{x^3}{3!}+ \epsilon \; \mathop{where} \; \epsilon \sim N(0, 0.1^2) y=5+1.2x3.42!x2+5.63!x3+ϵwhereϵN(0,0.12)

# 使用三阶多项式来生成训练和测试数据的标签
max_degree = 40
n_train, n_test = 100, 100
true_w = np.zeros(max_degree)
true_w[0:4] = np.array([5, 1.2, -3.4, 5.6])

features = np.random.normal(size=(n_train + n_test, 1))
np.random.shuffle(features)
poly_features = np.power(features, np.arange(max_degree).reshape(1, -1))
for i in range(max_degree):
    poly_features[:, i] /= math.gamma(i + 1)
labels = np.dot(poly_features, true_w)
labels += np.random.normal(scale=0.1, size=labels.shape)

这里的 n_test 是验证集的数量

上述代码中,我们创建了一个长为 40 的向量 true_w,它只有前4个值为有意义的数值,后36位全为0(噪音)。此外,我们使用 np.random.normal() 方法添加噪音。

我们可以观察一些前2个样本:

# 看一下前两个样本
true_w, features, poly_features, labels = [
    torch.tensor(x, dtype=torch.float32)
    for x in [true_w, features, poly_features, labels]
]

3.2 损失函数

实现一个函数来评估模型在给定数据集上的损失。

def evaluate_loss(net, data_iter, loss):
    """ 评估给定数据集上模型的损失 """
    metric = d2l.Accumulator(2)
    for X, y in data_iter:
        out = net(X)
        y = y.reshape(out.shape)
        l = loss(out, y)
        metric.add(l.sum(), l.numel())
    return metric[0] / metric[1]

3.3 训练函数

接下来,我们定义一个训练函数。

# 定义训练函数
def train(train_features, test_features, train_labels, test_labels, num_epochs=400):
    loss = nn.MSELoss(reduction='none')
    input_shape = train_features.shape[-1]
    net = nn.Sequential(nn.Linear(input_shape, 1, bias=False))
    batch_size = min(10, train_labels.shape[0])
    train_iter = d2l.load_array((train_features, train_labels.reshape(-1, 1)), batch_size)
    test_iter = d2l.load_array((test_features, test_labels.reshape(-1, 1)),
                               batch_size, is_train=False)
    trainer = torch.optim.SGD(net.parameters(), lr=0.01)
    animator = d2l.Animator(xlabel='epoch', ylabel='loss', yscale='log',
                            xlim=[1, num_epochs], ylim=[1e-3, 1e2],
                            legend=['train', 'test'])
    for epoch in range(num_epochs):
        d2l.train_epoch_ch3(net, train_iter, loss, trainer)
        if epoch == 0 or (epoch + 1) % 20 == 0:
            animator.add(epoch+1, (evaluate_loss(net, train_iter, loss),
                                   evaluate_loss(net, test_iter, loss))) 
    d2l.plt.show()
    print('weight: ', net[0].weight.data.numpy())

3.4 拟合

我们在训练模型的过程中,使用验证集进行三阶多项式函数拟合。
正态: 我们使用前4位有效信息训练模型,可以得到比较好的拟合效果。因为我们之前构造人工数据集的时候只有前4位是有效的数据,所以数据与模型是匹配的。

# 拟合 正态
train(poly_features[:n_train, :4], poly_features[n_train:, :4],
      labels[:n_train], labels[n_train:])

正态

线性函数拟合(欠拟合): 我们只使用前两位有效信息进行拟合,由于少使用了一半的有效数据,所以产生了比较严重的欠拟合。

# 拟合 欠拟合
train(poly_features[:n_train, :2], poly_features[n_train:, :2],
      labels[:n_train], labels[n_train:])

欠拟合

高阶多项式函数拟合(过拟合): 我们使用全部的40维数据训练模型,由于后36维饱含噪音,所以产生过拟合。我们可以观察到在 epoch = 300 左右的地方,损失值略有增加。

# 拟合 过拟合
train(poly_features[:n_train, :], poly_features[n_train:, :],
      labels[:n_train], labels[n_train:], num_epochs=1500)

过拟合
下一篇:【动手学深度学习v2李沐】学习笔记07:权重衰退、正则化

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 《动手深度学习 v2》是一本介绍深度学习的教材,通过动手实践的方式帮助读者深入理解深度学习的理论和实践。这本书由李沐等人共同编写,内容包含了深度学习的基本概念、算法原理以及实际应用等方面。 这本书的优点之一是注重实践,通过大量的案例和代码实现,读者可以亲自动手搭建深度学习模型,并通过实际操作来理解算法的工作原理。此外,书中还涵盖了一些最新的深度学习技术和应用,帮助读者跟上深度学习领域的最新发展。 《动手深度学习 v2》也具有一定的难度,对于初者来说需要一定的数和编程基础才能更好地理解和实践。但是,书中的难点都有详细的解答和说明,读者可以在遇到困难时查看相关解析,提升学习效果。 总的来说,《动手深度学习 v2》是一本非常实用的深度学习教材,适合有一定基础的读者学习和实践。通过阅读这本书,读者可以系统地学习深度学习的基本概念和算法,掌握如何应用深度学习解决实际问题,进而在深度学习领域有更深入的理解和应用。 ### 回答2: 《动手深度学习 v2》pdf是一本深度学习入门的教程,适合初学习深度学习的理论和实践。这本教程由作者李沐、阿斯顿·张剑锋等人合作撰写,涵盖了深度学习的基本概念、神经网络的构建、常见深度学习模型、计算机视觉、自然语言处理等领域的应用。 这本教程的特点是注重实践,每个章节都提供了大量的代码示例和实验指导,让读者可以动手实践,巩固所知识。同时,教程还配有相应的代码库和数据集,读者可以下载使用。 教程通过深度学习的基本概念和原理,帮助读者建立起对深度学习的整体认识。然后,通过实例演示和实践,教会读者如何使用深度学习框架搭建神经网络,并进行训练和优化。 另外,这本教程也介绍了一些常见的应用领域,如计算机视觉和自然语言处理。读者可以学习到如何使用深度学习来解决图像分类、目标检测、文本生成等问题。 最后,这本教程还提供了一些深度学习的进阶内容,如深度生成模型和强化学习等,供读者深入学习和拓展。 总的来说,《动手深度学习 v2》pdf是一本很好的深度学习入门教程,通过动手实践和实例演示,帮助读者快速入门和掌握深度学习的基本知识和应用技巧。对于想要学习深度学习的初者来说,是一本非常有价值的教材。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鱼儿听雨眠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值