Datawhale_Task5 PyTorch实现L1,L2正则化以及Dropout
1.Dropout原理
(1)Dropout
实际是在前向传播的时候,让某个神经元的激活值以一定的概率P停止工作,这样可以使模型泛化性更强,一定程度上起到正则化的作用,可以防止网络拟合。P一般取0.5。
对于某层的每个神经元,
在训练阶段,每个神经元以概率P,随机将该神经元权重置0;
在测试阶段,所有神经元均呈现激活状态,但所有权重要乘以(1-P);
以保证训练和测试阶段各自权重有相同的期望。
(2)Dropout为什么能防止过拟合?
2.用代码实现正则化(L1、L2、Dropout)
正则化:在原来的loss function的基础上,加上了一些正则化项或者称为模型复杂度惩罚项
(1)L1正则化
L1,又称为LASSO。L1范数,是参数矩阵W中元素的绝对值之和。
regularization_loss1 = 0
for param in model.parameters():
regularization_loss1 += torch.sum(abs(param))
(2)L2正则化
L2,又称为Rigde。L2范数,是参数矩阵W中元素的平方之和。
regularization_loss2 = 0
for param in model.parameters():
regularization_loss2 += torch.norm(param,2)
以线性回归为例,
加入L1和L2正则的等高线
L1:我们经过观察可以看到,几乎对于很多原函数等高曲线,和某个菱形相交的时候及其容易相交在坐标轴(比如上图),也就是说最终的结果,解的某些维度及其容易是0,这也就是我们所说的L1更容易得到稀疏解(解向量中0比较多)的原因。
L2:从图上来看,不容易交在坐标轴上,但是仍然比较靠近坐标轴。因此这也就是我们老说的,L2范数能让解比较小(靠近0),但是比较平滑(不等于0)。
3.Dropout的numpy实现
import numpy as np
def dropout(X, keep_prob = 0.5):
"""
:param X: input
:param keep_prob:
:return:
"""
D = np.random.rand(X.shape[0], X.shape[1]) # step1: initialize matrix d
D = D < keep_prob # step2: convert entries of d
X = X * D # step3: shut down some neuron
X = X/keep_prob #step4: scale the value of neuron
return X
4.PyTorch中实现dropout
import torch
import torch.nn.functional as F
import torch.nn as nn
class Model1(nn.Module):
# Model 1 using functional dropout
def __init__(self, p=0.0):
super(Model1,self).__init__()
self.p = p
def forward(self, inputs):
return F.dropout(inputs, p=self.p, training=True)
#建议选择这种,因为dropout在训练和测试阶段使用不同
class Model2(nn.Module):
# Model 2 using dropout module
def __init__(self, p=0.0):
super(Model2,self).__init__()
self.drop_layer = nn.Dropout(p=p)
def forward(self, inputs):
return self.drop_layer(inputs)
model1 = Model1(p=0.5) # functional dropout
model2 = Model2(p=0.5) # dropout module
# creating inputs
inputs = torch.rand(10)
print("inputs", inputs)
# forwarding inputs in train mode
print('Normal (train) model:')
print('Model 1', model1(inputs))
print('Model 2', model2(inputs))
print()
# switching to eval mode
model1.eval()
model2.eval()
# forwarding inputs in evaluation mode
print('Evaluation mode:')
print('Model 1', model1(inputs))
print('Model 2', model2(inputs))
# show model summary
print('Print summary:')
print(model1)
print(model2)
可以看到,如果使用的是F.dropout,那么在model.eval的时候,测试时如果没有对dropout函数进行调整的话,还是会对输入进行dropout的操作,但是nn.dropout就不存在这样的问题。修改F.dropout,就跟nn.dropout效果一样
F.dropout(inputs, p=self.p, training=self.training)
参考:PyTorch的dropout设置训练和测试模式
pytorch中torch.nn.dropout和torch.nn.F.dropout区别
L2正则化(L2 Regularization)、Dropout原理及其python实现
L1正则化与L2正则化