动手学深度学习(pytorch版):第四章节—多层感知机(5)权重衰减

前一节描述了过拟合的问题,本节将介绍一些正则化模型的技术。 可以通过去收集更多的训练数据来缓解过拟合。 但这可能成本很高,耗时颇多,或者完全超出控制,因而在短期内不可能做到。 假设已经拥有尽可能多的高质量数据,便可以将重点放在正则化技术上。

回想一下,在多项式回归的例子中, 可以通过调整拟合多项式的阶数来限制模型的容量。 实际上,限制特征的数量是缓解过拟合的一种常用技术。 然而,简单地丢弃特征对这项工作来说可能过于生硬。 继续思考多项式回归的例子,考虑高维输入可能发生的情况。 多项式对多变量数据的自然扩展称为单项式(monomials), 也可以说是变量幂的乘积。 单项式的阶数是幂的和。

注意,随着阶数的增长,带有阶数的项数迅速增加。 因此即使是阶数上的微小变化,比如从到,也会显著增加模型的复杂性。 仅仅通过简单的限制特征数量(在多项式回归中体现为限制阶数),可能仍然使模型在过简单和过复杂中徘徊, 需要一个更细粒度的工具来调整函数的复杂性,使其达到一个合适的平衡位置。

已经描述了范数和范数, 它们是更为一般的范数的特殊情况。

在训练参数化机器学习模型时, 权重衰减 (weight decay)是最广泛使用的正则化的技术之一, 它通常也被称为正则化。 这项技术通过函数与零的距离来衡量函数的复杂度, 因为在所有函数中,函数(所有输入都得到值) 在某种意义上是最简单的。 但是应该如何精确地测量一个函数和零之间的距离呢? 没有一个正确的答案。 事实上,函数分析和巴拿赫空间理论的研究,都在致力于回答这个问题。

一种简单的方法是通过线性函数中的权重向量的某个范数来度量其复杂性,

回想一下,是样本的特征, 是样本的标签, 是权重和偏置参数。 为了惩罚权重向量的大小, 必须以某种方式在损失函数中添加, 但是模型应该如何平衡这个新的额外惩罚的损失?

1. 高维线性回归

通过一个简单的例子来演示权重衰减。

python 复制代码
%matplotlib inline
import torch
from torch import nn
from d2l import torch as d2l

首先,像以前一样生成一些数据,生成公式如下:

选择标签是关于输入的线性函数。 标签同时被均值为0,标准差为0.01高斯噪声破坏。 为了使过拟合的效果更加明显,可以将问题的维数增加到, 并使用一个只包含20个样本的小训练集。

python 复制代码
n_train, n_test, num_inputs, batch_size = 20, 100, 200, 5
true_w, true_b = torch.ones((num_inputs, 1)) * 0.01, 0.05
train_data = d2l.synthetic_data(true_w, true_b, n_train)
train_iter = d2l.load_array(train_data, batch_size)
test_data = d2l.synthetic_data(true_w, true_b, n_test)
test_iter = d2l.load_array(test_data, batch_size, is_train=False)

2. 从零开始实现

下面将从头开始实现权重衰减,只需将的平方惩罚添加到原始目标函数中。

2.1. 初始化模型参数

首先,定义一个函数来随机初始化模型参数。

python 复制代码
def init_params():
    w = torch.normal(0, 1, size=(num_inputs, 1), requires_grad=True)
    b = torch.zeros(1, requires_grad=True)
    return [w, b]

2.2. 定义范数惩罚

实现这一惩罚最方便的方法是对所有项求平方后并将它们求和。

python 复制代码
def l2_penalty(w):
    return torch.sum(w.pow(2)) / 2

2.3. 定义训练代码实现

下面的代码将模型拟合训练数据集,并在测试数据集上进行评估。

python 复制代码
def train(lambd):
    w, b = init_params()
    net, loss = lambda X: d2l.linreg(X, w, b), d2l.squared_loss
    num_epochs, lr = 100, 0.003
    animator = d2l.Animator(xlabel='epochs', ylabel='loss', yscale='log',
                            xlim=[5, num_epochs], legend=['train', 'test'])
    for epoch in range(num_epochs):
        for X, y in train_iter:
            # 增加了L2范数惩罚项,
            # 广播机制使l2_penalty(w)成为一个长度为batch_size的向量
            l = loss(net(X), y) + lambd * l2_penalty(w)
            l.sum().backward()
            d2l.sgd([w, b], lr, batch_size)
        if (epoch + 1) % 5 == 0:
            animator.add(epoch + 1, (d2l.evaluate_loss(net, train_iter, loss),
                                     d2l.evaluate_loss(net, test_iter, loss)))
    print('w的L2范数是:', torch.norm(w).item())

2.4. 忽略正则化直接训练

lambd=0禁用权重衰减后运行这个代码。 注意,这里训练误差有了减少,但测试误差没有减少, 这意味着出现了严重的过拟合。

python 复制代码
train(lambd=0)

2.5. 使用权重衰减

下面使用权重衰减来运行代码。 注意,在这里训练误差增大,但测试误差减小。 这正是我们期望从正则化中得到的效果。

python 复制代码
train(lambd=3)

3. 简洁实现

在下面的代码中,我们在实例化优化器时直接通过weight_decay指定weight decay超参数。 默认情况下,PyTorch同时衰减权重和偏移。 这里我们只为权重设置了weight_decay,所以偏置参数不会衰减。

python 复制代码
def train_concise(wd):
    net = nn.Sequential(nn.Linear(num_inputs, 1))
    for param in net.parameters():
        param.data.normal_()
    loss = nn.MSELoss(reduction='none')
    num_epochs, lr = 100, 0.003
    # 偏置参数没有衰减
    trainer = torch.optim.SGD([
        {"params":net[0].weight,'weight_decay': wd},
        {"params":net[0].bias}], lr=lr)
    animator = d2l.Animator(xlabel='epochs', ylabel='loss', yscale='log',
                            xlim=[5, num_epochs], legend=['train', 'test'])
    for epoch in range(num_epochs):
        for X, y in train_iter:
            trainer.zero_grad()
            l = loss(net(X), y)
            l.mean().backward()
            trainer.step()
        if (epoch + 1) % 5 == 0:
            animator.add(epoch + 1,
                         (d2l.evaluate_loss(net, train_iter, loss),
                          d2l.evaluate_loss(net, test_iter, loss)))
    print('w的L2范数:', net[0].weight.norm().item())

然而,它们运行得更快,更容易实现。 对于更复杂的问题,这一好处将变得更加明显。

python 复制代码
train_concise(0)
python 复制代码
train_concise(3)
复制代码
相关推荐
萧鼎2 分钟前
Python pyzmq 库详解:从入门到高性能分布式通信
开发语言·分布式·python
媒体人88818 分钟前
GEO 优化专家孟庆涛:技术破壁者重构 AI 时代搜索逻辑
大数据·人工智能
小菜AI科技30 分钟前
Windsurf 评测:这款 人工智能 IDE 是你需要的颠覆性工具吗?
人工智能
RaymondZhao3433 分钟前
【全面推导】策略梯度算法:公式、偏差方差与进化
人工智能·深度学习·算法·机器学习·chatgpt
yujkss1 小时前
Python脚本每天爬取微博热搜-终版
开发语言·python
yzx9910131 小时前
小程序开发APP
开发语言·人工智能·python·yolo
AKAMAI1 小时前
通过自动化本地计算磁盘与块存储卷加密保护数据安全
人工智能·云计算
飞翔的佩奇1 小时前
【完整源码+数据集+部署教程】二维码与查找模式检测系统源码和数据集:改进yolo11-CSwinTransformer
python·yolo·计算机视觉·数据集·yolo11·二维码与查找模式检测
大霞上仙1 小时前
实现自学习系统,输入excel文件,能学习后进行相应回答
python·学习·excel
Caven772 小时前
【pytorch】reshape的使用
pytorch·python