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

权重衰退

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

    如下所示,其中l是我们要优化的损失函数,w和b是两个参数。w为权重,b为偏移,但这个优化函数并不常用,多使用下面的柔性限制。


    image-20210902210126877.png
  1. 使用均方范数作为柔性限制


    image-20210902211206725.png

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


    image-20210902211415694.png

    其中,表示的最优解。

  • 无作用,即不会影响w的取值,等价于之前的
  • ,等价于之前的,所以,那么最优解
  • 如果我们想让模型复杂度低一些,那我们将增加些以满足要求。
  1. 参数更新法则
    如下所示,将画黄线部分代入红色表达式并进行化简,即可得到时间t更新参数对应的表达式。

    image-20210903091928614.png

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

  2. 总结
    image-20210903093033301.png

    5.代码实现

    # 权重衰减是最广泛使用的正则化的技术之一
    %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)
    
  3. 对应运行结果

    20210903103448.png

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

你可能感兴趣的:(跟着李沐大神动手深度学习笔记——权重衰退)