李沐12权重衰退——自学笔记

权重衰退

常用的处理过拟合的方法

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

通过限制参数值的选择范围来控制模型容量
通常不限制偏移b
小的θ意味着更强的正则项

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

总结

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

代码实现

import torch
from torch import nn
from d2l import torch as d2l

生成人工数据集

在这里插入图片描述

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) # 具体来说,d2l.synthetic_data函数通常接受几个参数,如权重(weights)、偏置(bias)和样本数量,然后基于这些参数生成特征和标签的数据集。这些参数可以帮助你控制生成数据的分布和复杂性。
train_iter=d2l.load_array(train_data,batch_size)   # 用于从文件中加载数据并将其转换为NumPy数组。它的功能是读取文件中的数据,并将其转换为指定的数据类型和形状。
test_data=d2l.synthetic_data(true_w,true_b,n_test)
test_iter=d2l.load_array(test_data,batch_size,is_train=False)
# 此处插入d2l.synthetic_data()函数的使用功能
import torch  
from d2l import torch as d2l  
  
# 定义权重和偏置  
true_w1 = torch.tensor([2, -3.4])  
true_b1 = 4.2  
  
# 生成合成数据集  
features1, labels1 = d2l.synthetic_data(true_w1, true_b1, 10)
features1,labels1

# 在这个例子中,true_w1和true_b1定义了生成数据的线性方程的参数
# 而10指定了要生成的样本数量。
# 函数返回两个张量:features和labels,它们分别包含生成的特征和对应的标签。
(tensor([[-0.7090, -2.2213],
         [-0.2302, -0.2752],
         [-0.2158, -0.1926],
         [-0.3529, -0.1453],
         [-0.9229,  0.2693],
         [ 0.8251,  0.5114],
         [ 0.4833,  0.9003],
         [-1.1898,  2.1717],
         [ 0.3343,  1.3417],
         [ 0.1269, -1.2196]]),
 tensor([[10.3366],
         [ 4.6631],
         [ 4.4256],
         [ 4.0140],
         [ 1.4457],
         [ 4.1345],
         [ 2.1194],
         [-5.5593],
         [ 0.3102],
         [ 8.5957]]))

初始化模型参数

def init_params():  # w和b的初始化函数
    w=torch.normal(0,1,size=(num_inputs,1),requires_grad=True) # w均值为0,方差为1
    b=torch.zeros(1,requires_grad=True) # b则是全0标量
    return [w,b]

定义L2范数惩罚

def l2_penalty(w):
    return torch.sum(w.pow(2))/2

定义训练代码

def train(lambd):  # lambd: 超参数
    w,b=init_params() # 初始化权重wb
    net, loss=lambda X:d2l.linreg(X,w,b), d2l.squared_loss # 线性回归,平方损失函数
    num_epochs,lr=100,0.003 # 迭代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: # 每个迭代器拿出X和y
            # with torch.enable_grad():
                l=loss(net(X),y)+lambd* l2_penalty(w) # 超参数是传进来的lambd
                # 原始的神经网络损失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())

忽略正则化直接训练

train(lambd=0)
w的L2范数是: 13.919422149658203

在这里插入图片描述

使用权重衰退

train(lambd=3)  # 数值可自选调节
w的L2范数是: 0.35291415452957153

在这里插入图片描述

权重衰退简洁实现

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())
train_concise(0)
w的L2范数: 13.60023021697998

在这里插入图片描述

train_concise(3)
w的L2范数: 0.35634884238243103

在这里插入图片描述

  • 14
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值