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,权重的更新多了,那么每次更新权重都会衰减
问题(详解):
- 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的更新
- 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中,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的方式不一样
而对于卷积层,需要对通道的输出分别做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),即内部协变量偏移的问题:深度神经网络每一层的参数更新会导致输入数据分布发生变化。通过层层叠加,高层的输入分布变化会非常剧烈,这就使得高层需要不断去重新适应底层的参数更新。从以下公式可以看出,每一隐藏层神经单元的数据分布标准差增加,所以,保持方差一致性,需要的对权重数据标准差缩放。
它们之间的计算差异体现在计算均值和方差上,例如:
- BN:保留通道维度,在batch上计算,就是把第1个样本的第1个通道,加上第2个样本第1个通道 … 加上第 N个样本第1个通道,然后除以 N×H×W ,得到通道 1 的均值和方差,其他通道类似。
- LN:针对深度不固定的网络,在通道上计算,所有通道求和,然后除以C×H×W计算均值和方差,RNN效果明显。
- IN:针对图像像素对H,W归一化,每一对应通道求均值和方差,用在风格化迁移
- GN:通道分组再归一化,