欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

[深度学习 pytorch] 正则化

最编程 2024-03-02 09:35:48
...

正则化的基本概念之前博客已有记录, 这里仅对正则化的实现做一点介绍

权重衰减(weight decay)

模型的复杂性——如何衡量函数与0的距离——Lp范数

L2正则化线性模型构成经典的岭回归(ridge regression)算法, L1正则化线性回归通常被称为套索回归(lasso regression)。实践中多使用L2范数。

使用L2范数的一个原因是它对权重向量的大分量施加了巨大的惩罚, 这使得学习算法偏向于在大量特征上均匀分布权重的模型。

在实践中,这可能使它们对单个变量中的观测误差更为稳定。 相比之下,L1惩罚会导致模型将权重集中在一小部分特征上, 而将其他权重清除为零。 

L2正则化线性模型,使用验证数据拟合:

                                                

L2正则化回归的小批量随机梯度下降更新如下式:

         

从零实现

将线性模型从零实现的损失函数做一些修改即可

简洁实现

线性模型从零实现的优化算法需要修改:

trainer = torch.optim.SGD([
    {"params":net[0].weight,'weight_decay': wd},
    {"params":net[0].bias}], lr=lr)

在实例化优化器时直接通过weight_decay指定weight decay超参数。

默认情况下,PyTorch同时衰减权重和偏移。 这里只为权重设置了weight_decay,所以偏置参数b不会衰减。

暂退法(dropout)

模型简单性的另一个角度是平滑性,即函数不应该对其输入的微小变化敏感。

在训练过程中,在计算后续层之前向网络的每一层注入噪声。 当训练一个有多层的深层网络时,注入噪声只会在输入-输出映射上增强平滑性。 这个想法被称为暂退法(dropout)。

暂退法在前向传播过程中,计算每一内部层的同时注入噪声,这已经成为训练神经网络的常用技术。 这种方法之所以被称为暂退法,因为我们从表面上看是在训练过程中丢弃(drop out)一些神经元。 在整个训练过程的每一次迭代中,标准暂退法包括在计算下一层之前将当前层中的一些节点置零。

                   

 从零实现

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


def dropout_layer(X, dropout):
    assert 0 <= dropout <= 1
    if dropout == 1:
        return torch.zeros_like(X)
    if dropout == 0:
        return X
    mask = (torch.rand(X.shape) > dropout).float()
    return mask * X / (1.0 - dropout)

num_inputs, num_outputs, num_hiddens1, num_hiddens2 = 784, 10, 256, 256
dropout1, dropout2 = 0.2, 0.5
class Net(nn.Module): def __init__(self, num_inputs, num_outputs, num_hiddens1, num_hiddens2, is_training = True): super(Net, self).__init__() self.num_inputs = num_inputs self.training = is_training self.lin1 = nn.Linear(num_inputs, num_hiddens1) self.lin2 = nn.Linear(num_hiddens1, num_hiddens2) self.lin3 = nn.Linear(num_hiddens2, num_outputs) self.relu = nn.ReLU() def forward(self, X): H1 = self.relu(self.lin1(X.reshape((-1, self.num_inputs)))) if self.training == True: H1 = dropout_layer(H1, dropout1) H2 = self.relu(self.lin2(H1)) if self.training == True: H2 = dropout_layer(H2, dropout2) out = self.lin3(H2) return out net = Net(num_inputs, num_outputs, num_hiddens1, num_hiddens2)
num_epochs, lr, batch_size = 10, 0.5, 256
loss = nn.CrossEntropyLoss(reduction='none')
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size)
trainer = torch.optim.SGD(net.parameters(), lr=lr)
d2l.train_ch3(net, train_iter, test_iter, loss, num_epochs, trainer)

简洁实现

net = nn.Sequential(nn.Flatten(),
        nn.Linear(784, 256),
        nn.ReLU(),
        nn.Dropout(dropout1),
        nn.Linear(256, 256),
        nn.ReLU(),
        nn.Dropout(dropout2),
        nn.Linear(256, 10))

def init_weights(m):
    if type(m) == nn.Linear:
        nn.init.normal_(m.weight, std=0.01)

net.apply(init_weights)

trainer = torch.optim.SGD(net.parameters(), lr=lr)
d2l.train_ch3(net, train_iter, test_iter, loss, num_epochs, trainer)