day06

🛴【任务1】

1、正则化的概念,作用
2、L1和L2正则化
2、weight decay的pytorch实现
3、正则化方法——Dropout
5、pytorch中Dropout的实现细节

笔记:

  • 正则化方法是机器学习(深度学习)中重要的方法,它目的在于减小方差。常用的正则化方法有L1正则,L2正则以及Dropout。
    如图所示:
    方差:刻画了训练集和验证集之间的性能差异
    偏差:度量了期望预测和真实之间的偏离程度
    噪声:表达期望泛化误差的下界,一般不会去考虑
  • 解释下L1和L2正则化,为什么L2正则化又称为weight decay?

      如图所示,假设目标函数只包含两个参数w1和w2,在等高线上(同一条曲线,取不同参数,得到的Loss相同),若要object 满足Loss约束和RL约束,则最优解为图上交点,即L1正则使w1为0,推广到更高维空间,则有更多稀疏解。同理L2正则使得w1和w2权重收缩到更小的范围内. object = Loss + RL
      如公式所示,相比于未加RL,权重的更新多了pytorch引入正则化 pytorch加入l2正则化_pytorch引入正则化,那么每次更新权重都会衰减
    问题(详解):
  1. weight decay在pytorch的SGD中实现代码是哪一行?它对应的数学公式为?
optim_wdecay = torch.optim.SGD(net_weight_decay.parameters(), lr=lr_init,
										 momentum=0.9, weight_decay=1e-2)
optim_wdecay.step()	
步入step()后									
d_p.add_(weight_decay, p.data) #对应上面公式 (d_p + weight_decay*p.data )
p.data.add_(-group['lr'], d_p)  #对应上面公式对w的更新
  1. pytorch的优化器中weight decay的实现?
    以网上代码感性了解下权重衰减,降低过拟合
import torch
import torch.nn as nn
import matplotlib.pyplot as plt
from tools import set_seed
from torch.utils.tensorboard import SummaryWriter

set_seed(1)  # 设置随机种子
n_hidden = 200
max_iter = 2000
disp_interval = 200
lr_init = 0.01


def gen_data(num_data=10, x_range=(-1, 1)):
    w = 1.5
    train_x = torch.linspace(*x_range, num_data).unsqueeze_(1)
    train_y = w*train_x + torch.normal(0, 0.5, size=train_x.size())
    test_x = torch.linspace(*x_range, num_data).unsqueeze_(1)
    test_y = w*test_x + torch.normal(0, 0.3, size=test_x.size())
    return train_x, train_y, test_x, test_y
train_x, train_y, test_x, test_y = gen_data(num_data=10, x_range=(-1, 1))

class MLP(nn.Module):
    def __init__(self, neural_num):
        super(MLP, self).__init__()
        self.linears = nn.Sequential(
            nn.Linear(1, neural_num),
            nn.ReLU(inplace=True),
            nn.Linear(neural_num, neural_num),
            nn.ReLU(inplace=True),
            nn.Linear(neural_num, neural_num),
            nn.ReLU(inplace=True),
            nn.Linear(neural_num, 1),
        )

    def forward(self, x):
        return self.linears(x)

net_n = MLP(neural_num=n_hidden)
net_weight_decay = MLP(neural_num=n_hidden)

optim_n = torch.optim.SGD(net_n.parameters(), lr=lr_init, momentum=0.9)
optim_wdecay = torch.optim.SGD(net_weight_decay.parameters(), lr=lr_init, momentum=0.9, weight_decay=1e-2)
loss_fun = torch.nn.MSELoss() #均方损失
writer = SummaryWriter(comment='test', filename_suffix='test')
for epoch in range(max_iter):
    pred_normal, pred_wdecay = net_n(train_x), net_weight_decay(train_x)
    loss_n, loss_wdecay = loss_fun(pred_normal, train_y), loss_fun(pred_wdecay, train_y)
    optim_n.zero_grad()
    optim_wdecay.zero_grad()
    loss_n.backward()
    loss_wdecay.backward()
    optim_n.step() #参数更新
    optim_wdecay.step()
    if (epoch + 1) % disp_interval == 0:
        for name, layer in net_n.named_parameters(): ##
            writer.add_histogram(name + '_grad_normal', layer.grad, epoch)
            writer.add_histogram(name + '_data_normal', layer, epoch)
        for name, layer in net_weight_decay.named_parameters():
            writer.add_histogram(name + '_grad_weight_decay', layer.grad, epoch)
            writer.add_histogram(name + '_data_weight_decay', layer, epoch)
        test_pred_normal, test_pred_wdecay = net_n(test_x), net_weight_decay(test_x)
        plt.scatter(train_x.data.numpy(), train_y.data.numpy(), c='blue', s=50, alpha=0.3, label='trainc')
        plt.scatter(test_x.data.numpy(), test_y.data.numpy(), c='red', s=50, alpha=0.3, label='test')
        plt.plot(test_x.data.numpy(), test_pred_normal.data.numpy(), 'r-', lw=3, label='no weight decay')
        plt.plot(test_x.data.numpy(), test_pred_wdecay.data.numpy(), 'b--', lw=3, label='weight decay')
        plt.text(-0.25, -1.5, 'no weight decay loss={:.6f}'.format(loss_n.item()),
                 fontdict={'size': 15, 'color': 'red'})
        plt.text(-0.25, -2, 'weight decay loss={:.6f}'.format(loss_wdecay.item()),
                 fontdict={'size': 15, 'color': 'red'})
        plt.ylim(-2.5, 2.5)
        plt.legend()
        plt.title('Epoch: {}'.format(epoch +  1))
        plt.show()
        plt.close()

pytorch引入正则化 pytorch加入l2正则化_pytorch_02

  • PyTorch中,Dropout在训练的时候权值尺度会进行什么操作?
      Dropout随机失活,隐藏单元以一定概率被丢弃,以1-p的概率除以1-p做拉伸,即输出单元的计算不依赖与丢弃的隐藏层单元
  • PyTorch中,Dropout实现细节?
修改上面代码
class MLP(nn.Module):
    def __init__(self, neural_num, p=0.5):
        super(MLP, self).__init__()
        self.linears = nn.Sequential(
            nn.Linear(1, neural_num),
            nn.ReLU(inplace=True),

            nn.Dropout(p), #在线性层之前
            nn.Linear(neural_num, neural_num),
            nn.ReLU(inplace=True),

            nn.Dropout(p),  # 在线性层之前
            nn.Linear(neural_num, neural_num),
            nn.ReLU(inplace=True),

            nn.Dropout(p),  # 在线性层之前
            nn.Linear(neural_num, 1),
        )
 if (epoch + 1) % disp_interval == 0:
        net_n.eval() #在测试模式,会关闭dropout
        net_weight_decay.eval()
        ...........
		net_n.train()#改回训练模式
        net_weight_decay.train()
#手动实现
def dropout(X, drop_prob):
    X = X.float()
    assert 0 <= drop_prob <= 1
    keep_prob = 1 - drop_prob
    if keep_prob == 0:    # 这种情况下把全部元素都丢弃
    	return torch.zeros_like(X)
    mask = (torch.randn(X.shape) < keep_prob).float()
    return mask * X / keep_prob  #以1-p的概率X除以1-p做拉伸,其中mask表示有p的概率,隐藏层单元X清0

🛴【任务2】

问题(详解):

1、Batch Normalization概念

  目的是使网络层的输出数据分布更加相近,数值更加稳定,起到的作用包括:使得梯度变平缓,可以用更大学习率,加速模型收敛;使模型正则化具有正则化效果,可以不用精心设计权值初始化,dropout或权重衰减。

2、全连接层和卷积层做BN的方式不一样

pytorch引入正则化 pytorch加入l2正则化_pytorch_03


而对于卷积层,需要对通道的输出分别做BN,每个通道都有独立的拉伸和偏移参数。

  • Batch Normalization;Layer Normalizatoin、Instance Normalizatoin和Group Normalizatoin,分析各Normalization的由来与应用场景,同时对比分析BN,LN,IN和GN之间的计算差异
      (BN,2015年)、(LN,2016年)、(IN,2017年)、(GN,2018年),这里先介绍下Internal Covariate Shift (ICS),即内部协变量偏移的问题:深度神经网络每一层的参数更新会导致输入数据分布发生变化。通过层层叠加,高层的输入分布变化会非常剧烈,这就使得高层需要不断去重新适应底层的参数更新。从以下公式可以看出,每一隐藏层神经单元的数据分布标准差增加pytorch引入正则化 pytorch加入l2正则化_pytorch_04,所以,保持方差一致性,需要的对权重数据标准差缩放pytorch引入正则化 pytorch加入l2正则化_权重_05

pytorch引入正则化 pytorch加入l2正则化_方差_06


  它们之间的计算差异体现在计算均值和方差上,例如:

  • BN:保留通道维度,在batch上计算,就是把第1个样本的第1个通道,加上第2个样本第1个通道 … 加上第 N个样本第1个通道,然后除以 N×H×W ,得到通道 1 的均值和方差,其他通道类似。
  • LN:针对深度不固定的网络,在通道上计算,所有通道求和,然后除以C×H×W计算均值和方差,RNN效果明显。
  • IN:针对图像像素对H,W归一化,每一对应通道求均值和方差,用在风格化迁移
  • GN:通道分组再归一化,