pytorch基础(九)-正则化

本文详细解释了过拟合及其与正则化的关系,重点介绍了L1和L2正则化的方法,以及如何在PyTorch中通过SGD优化器应用权重衰减来防止过拟合,包括反向传播过程中的权重更新策略。
摘要由CSDN通过智能技术生成

背景

使用正则化的前提是过拟合

过拟合即训练后的权重为高方差,正则化的目的就是减小权重的方差

通过损失函数+正则项的方式减小方差:

obj=loss+Regularization

Regularization 

 L1正则化

Regularization=\sum|w_{i}|

 obj=loss+\sum|w_{i}|

梯度下降时使loss值和正则项的值最小

loss的等高线为圆环所示
L1正则项的等高线为菱形:w_1+w_2等于常数c,w_1,w_2之间肯定是线性的

w_1+w_2=c\\w_2=c-w_1

loss值在a,b,c三点都为最小值,计算正则项的最小值:

a\_reg=1+4=5\\b\_reg=0+2=2\\c\_reg=4+1=5

 正则项在坐标轴上存在最小值,在坐标轴上w_1=0,所以经过L1正则化后使得权重稀疏

L2正则化

L2 Regularization又叫做weight decay(权值衰减)

Regularization=\sum w_i^2

 obj=loss+\frac{\lambda }{2}\sum w_i^2

在进行权重更新时:

w_i=w_i-\eta( \frac{\partial loss}{\partial w_i}+\lambda w_i)\\w_i=w_i(1-\lambda )-\eta \frac{\partial loss}{\partial w_i}

\lambda取(0,1),经过L2正则化后权重减小

L1使得权重稀疏,L2使权重减小 

net_weight_decay

torch.optim.SGD(net_weight_decay.parameters(), lr=lr_init, momentum=0.9, weight_decay=1e-2)

 没有经过L2正则化的网络权重一直都很大,含有大量网络参数

  经过L2正则化的网络权重不断减小,防止过拟合

对反向传播过程进行debug: 

    for i, param in enumerate(params):
        d_p = d_p_list[i] if not maximize else -d_p_list[i]

        if weight_decay != 0:
            d_p = d_p.add(param, alpha=weight_decay)  # p=p+w*p

        if momentum != 0:
            buf = momentum_buffer_list[i]

            if buf is None:
                buf = torch.clone(d_p).detach()
                momentum_buffer_list[i] = buf
            else:
                buf.mul_(momentum).add_(d_p, alpha=1 - dampening)

            if nesterov:
                d_p = d_p.add(buf, alpha=momentum)
            else:
                d_p = buf

        param.add_(d_p, alpha=-lr)

 

下面是一个使用PyTorch实现CNN L1正则化的示例代码: ```python import torch import torch.nn as nn import torch.nn.functional as F class CNN(nn.Module): def __init__(self): super(CNN, self).__init__() self.conv1 = nn.Conv2d(in_channels=3, out_channels=16, kernel_size=5) self.conv2 = nn.Conv2d(in_channels=16, out_channels=32, kernel_size=5) self.fc1 = nn.Linear(32 * 5 * 5, 120) self.fc2 = nn.Linear(120, 84) self.fc3 = nn.Linear(84, 10) def forward(self, x): x = F.relu(self.conv1(x)) x = F.max_pool2d(x, 2) x = F.relu(self.conv2(x)) x = F.max_pool2d(x, 2) x = x.view(-1, 32 * 5 * 5) x = F.relu(self.fc1(x)) x = F.relu(self.fc2(x)) x = self.fc3(x) return x model = CNN() criterion = nn.CrossEntropyLoss() optimizer = torch.optim.SGD(model.parameters(), lr=0.01) for epoch in range(10): running_loss = 0.0 for i, data in enumerate(trainloader, 0): inputs, labels = data # 设置L1正则化项 l1_regularization = torch.tensor(0) for param in model.parameters(): l1_regularization += torch.norm(param, 1) l1_regularization *= 0.001 optimizer.zero_grad() outputs = model(inputs) loss = criterion(outputs, labels) + l1_regularization loss.backward() optimizer.step() running_loss += loss.item() if i % 2000 == 1999: print('[%d, %5d] loss: %.3f' % (epoch + 1, i + 1, running_loss / 2000)) running_loss = 0.0 print('Finished Training') ``` 在上述代码中,我们使用了`torch.norm`函数来计算参数的L1范数,并将其乘以一个较小的系数作为L1正则化项,加入到损失函数中。通过调整这个系数的大小,我们可以控制正则化的强度。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值