跟着李沐大神动手深度学习笔记——权重衰退

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

    如下所示,其中l是我们要优化的损失函数,w和b是两个参数。w为权重,b为偏移,

请添加图片描述

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

请添加图片描述

以上可以通过拉格朗日乘子来证明,超参数 λ \lambda λ控制了正则项的重要程度。

请添加图片描述

其中, w ∗ w^* w表示 w w w的最优解。

  • λ = 0 : \lambda=0: λ=0:无作用,即不会影响w的取值,等价于之前的 θ − > ∞ \theta->\infty θ>
  • λ − > ∞ \lambda->\infty λ>,等价于之前的 θ − > 0 \theta->0 θ>0,所以 w − > 0 w->0 w>0,那么最优解 w ∗ − > 0 w^*->0 w>0
  • 如果我们想让模型复杂度低一些,那我们将 λ \lambda λ增加些以满足要求。
  1. 参数更新法则
    如下所示,将画黄线部分代入红色表达式并进行化简,即可得到时间t更新参数对应的表达式。
    请添加图片描述

    其中 η \eta η表示学习率,在上图中的第二个公式,后面部分(减去学习率*梯度)与我们之前讲的梯度下降是一样的,只是我们现在在每次更新前,在前面那里多减了一个 η λ \eta\lambda ηλ,进行权重的缩小。

  2. 总结
    请添加图片描述

  3. 代码实现

    # 权重衰减是最广泛使用的正则化的技术之一
    %matplotlib inline
    import math
    import torch
    from torch import nn
    from d2l import torch as d2l
    # 1. 生成一些数据
    n_train, n_test, num_inputs, batch_size = 20, 100, 200, 5
    # 随机生成权重,以及将偏差设成为0.05
    true_w, true_b = torch.ones((num_inputs, 1)) * 0.01, 0.05
    # 使用synthetic_data生成人工数据集,以及使用load_array加载内存数据
    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.初始化模型参数
    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]
    # 3. 定义L2范数惩罚(对照公式),也是本次的核心,注意我们在该函数中没有将lambda放在里面
    def L2_penalty(w):
        return torch.sum(w.pow(2)) / 2
    # 拓展:我们也可以用L1 penalty(w)
    def L1_penalty(w):
        return torch.sum(torch.abs(w))
    
    # 4. 定义训练代码实现
    # lambda为超级参数
    def train(lambd):
        w, b = init_params()
        net, loss = lambda X: d2l.linreg(X, w, b), d2l.squared_loss
        num_epochs, lr = 100, 0.03
        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:
    #             with torch.enable_grad():
                # 增加L2范数惩罚项,广播机制使l2_penalty(w)成为一个长度为`batch_size`的向量。
                # 以下表达式对应柔性限制的核心
                l = loss(net(X), y) + lambd * L1_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())
    # 忽略正则化直接训练
    train(lambd=0) # 出现严重的过拟合
    # 尝试改变lambda的值
    train(lambd=3)
    
  4. 结果如下所示
    在这里插入图片描述

    当我们将 λ \lambda λ设为0时,得到的结果,如第1张图所示,很明显发生了严重的过滤盒,当我们将 λ \lambda λ设为3时,得到的效果还不错,具体哪个参数最优,则需要自己去调参。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值