权重衰退python

权重衰退

动手学深度学习12/76

(1)使用均方范数L2作为硬性限制:通过限制参数值的选择范围来控制模型容量,只限制W平方
(2)使用均方范数作为柔性限制:带约束,loss+WWλ/2,超参数λ控制了正则化的重要程度。λ=0无作用,λ无穷大,W趋向于0.
(3)参数更新法则:其实就是把上一个epoch的W缩小一点,再沿着负梯度方向更新,会稳定一些。(权重衰退)
(4)权重衰退通过L2正则化是的模型参数不会过大,从而控制模型负责度,正则项权重是控制模型负责度的超参数。
(5)权重衰退值最广泛使用的正则化的技术之一。
(6)训练数据越小越容易过拟合。
(7)简洁实现:1、建立网络。2、损失函数。3、优化器(根据反向传播求得梯度,用优化器更新参数)。4、从训练集去除数据,进行训练,先梯度清0,算损失,反向传播,然后优化。
(8)复杂模型,权重衰退效果不一定很好。
(9)weight_decay可以取0.01,0.0001等等
(10)函数: m i n l ( W , b ) + λ 2 ∣ ∣ W ∣ ∣ 2 min \quad l(W,b) + \frac \lambda 2 ||W||^2 minl(W,b)+2λ∣∣W2

ps:markdowm第一次打公式,真难受啊。

代码

import torch
from torch import nn
import matplotlib.pyplot as plt
from d2l import torch as d2l
#函数 y=0.05+sum(0.01*x1+0.01*x2+0.01*x3........)+噪音(均值为0,方差为0.01)
n_train, n_test, num_inputs, batch_size = 20, 100, 200, 5 # 数据越简单,模型越复杂,越容易过拟合。num_inputs为特征维度
true_w, true_b = torch.ones((num_inputs,1)) * 0.01, 0.05
train_data = d2l.synthetic_data(true_w, true_b, n_train) # 生成人工数据集,Ctrl+函数,可以跳进去看函数具体干啥,这就是生成真实的y
#print(train_data)

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)

# 初始化模型参数
def init_params():
    w = torch.normal(0,1,size=(num_inputs,1),requires_grad=True)#函数torch.normal(mean=1,std=2,size=(3,4))
    b = torch.zeros(1,requires_grad=True)
    return [w,b]

# 定义L2范数惩罚,就是把W平方除以2
def l2_penalty(w):
    return torch.sum(w.pow(2)) / 2
#return torch.sum(torch.abs(w)) L1范数

# 定义训练函数
def train(lambd):
    w, b = init_params()
    net, loss = lambda X: d2l.linreg(X, w, b), d2l.squared_loss#lambda,相当于定义了一个函数
    num_epochs, lr = 100, 0.003
    animator = d2l.Animator(xlabel='epoch',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():
            l = loss(net(X),y) + lambd * l2_penalty(w)#区别,加上超参数*L2
            l.sum().backward()
            d2l.sgd([w,b],lr,batch_size)
        if(epoch+1) % 5 == 0:
            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())

'''
简洁实现:1、建立网络。2、损失函数。3、优化器(根据反向传播求得梯度,用优化器更新参数)。4、从训练集去除数据,进行训练,

def train_concise(wd):
    net=nn.Sequential(nn.Linear(num_inputs,1))
    for param in net.parameters():
        param.data.normal_()
    loss=nn.MSELoss()
    num_epochs,lr=100,0.003
    trainer=torch.optim.SGD([{
        "params":net[0].weight,
        "weight_decay":wd,},{#就是lambd
        "params":net[0].bias}],lr=lr)
    animator=d2l.Animator(xlabel='epoch',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():
                trainer.zero_grad()
                l=loss(net(X),y)
            l.backward()
            trainer.step()
'''

# 无正则化直接训练
#train(lambd=0)  #训练集小,过拟合,测试集损失不下降,test一条直线了,w的L2范数是13.392132759094238,两条线差距越来越大
# 使用权重衰退
#train(lambd=3)# 0.3826645016670227,还是偏大,可以调大lamda
train(lambd=10)# 0.02332453615963459
train(5)# 0.04332248866558075
plt.show()

运行结果

分别是lambd为3,10,0

lambd=3
lambd=10
lambd=0

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值