动手学深度学习-权重衰减到底是怎么回事

一、为什么要对权重进行正则化

为了防止过拟合的发生,因为过拟合学习到了训练数据中的噪声,而没有较好的学习到普遍规律,所以泛化误差较大。

二、权重正则化的作用

正则化的目的是通过引入惩罚项来限制模型的复杂度,从而避免过拟合。在权重正则化中,对模型的权重(即连接神经元的参数)施加限制,防止它们变得过大或者过于复杂。

三、正则化是怎么实现权重衰减的

损失函数的定义:\mathrm{Loss}=\frac{1}{N}\sum_{i=1}^N(y_i-\hat{y}_i)^2+\lambda\sum_{j=1}^Mw_j^2

又因为\hat{y}_i=w\cdot x_i+b,所以对wj求导后,结果是

\frac{\partial}{\partial w_j}\left(\frac{1}{N}\sum_{i=1}^N(y_i-\hat{y}_i)^2\right)=\frac{1}{N}\sum_{i=1}^N2x_i\cdot(y_i-\hat{y}_i)

加入惩罚项后:

\frac{\partial\mathrm{Loss}}{\partial w_j}=\frac{1}{N}\sum_{i=1}^N2x_i\cdot(y_i-\hat{y}_i)+2\lambda w_j

权重更新:

w_j^\mathrm{new}=w_j^\mathrm{old}-\eta\left(\frac{1}{N}\sum_{i=1}^N2x_i\cdot(y_i-\hat{y}_i)+2\lambda w_j\right)

这里xi是指的x=[x1,x2...xn]中的样本,j表示xi样本中第j个特征,wj就是第j个特征的权重。从上式也可以看出来加入惩罚项后,越大的权重,衰减的越多,进一步说损失函数是向着w权重下降的方向移动。

权重衰减的公式如下:

对权重w的L2正则项的计算如下

代码实现如下

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

完整的代码

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

n_train,n_test,num_inputs,batch_size =  20,100,200,5
# n_train表示训练集中的样本数量为20个
# n_test表示测试集中的样本数量为100个
# num_inputs 表示每个样本中的特征数量为200
true_w,true_b = torch.ones((num_inputs,1)) * 0.01,0.05

# 下一行代码是生成训练数据,即通过给定的真实权重 true_w 和真实偏置 true_b,以及样本数量 n_train,合成一个训练集
train_data = d2l.synthetic_data(true_w, true_b, n_train)

# 下一行代码的作用是 将训练数据train_data加载为一个数据迭代器train_iter,
# 使得模型可以按照指定的批量大小(batch_size)来从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)
    b = torch.zeros(1,requires_grad=True)
    return [w,b]

def l2_penalty(w): #l2惩罚项
    return torch.sum(w.pow(2))/2

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:# 这里是通过数据加载器每次取出5个样本
            with autograd.record():
                # 增加了L2范数惩罚项,
                # 广播机制使l2_penalty(w)成为一个长度为batch_size的向量
                l = loss(net(X), y) + lambd * l2_penalty(w)
            l.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范数是:', np.linalg.norm(w))

train(lambd=3)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值