L1 & L2
L1正則
L1正則算法如下:
其中\(|x_i|\)表示絕對值。
在Pytorch 中,沒有自帶L1正則方法,所以需要手動寫
reg_loss = 0
for param in model.parameters():
reg_loss += torch.sum(torch.abs(param))
loss = criteon(logits,target)
loss = loss + 0.01 * reg_loss
optimizer.zero_grad()
loss.backward()
optimizer.step()
L2正則
L2正則計算方法如下:
在pytorch中,優化器中再帶L2正則,使用方法如下:直接設定weight_decay
參數即可。
optim = torch.optim.SGD(net.parameters(), lr = 0.0001, momentum = 0.8, weight_decay=1e-2)
模型中常用四種歸一化
在前向傳播過程中,模型的數據會出現分布偏移,使用歸一化可以將偏移進行校正,對中間輸出的值進行歸一化。好處是可以加速模型收斂,而且不用精心設計權重初始化。
BatchNorm
BatchNorm 計算法方法如下:
在pytorch中,Batch Normalization 模塊一般放置在激活函數前面。其函數如下:
nn.BatchNorm1d()
nn.BatchNorm2d()
nn.BatchNorm3d()
參數:
num_feature
: 樣本的特征數量
eps
: 分母修正項
momentum
: 指數加權平均,用於計算均值方差
affine
: 是否要進行affine transform ,意思是是否計算 \(y_i = \gamma \hat x_i + \beta\)
track_running_stats
: 表示是否估計新的均值和方差,如果是訓練階段,會計算每一個batch的的均值和方差,如果是測試階段,均值和方差是固定的。
Batch中的主要屬性:
running_mean
:均值
running_var
:方差
weight
: affine transform 中的 gamma, 既\(\gamma\)
bias
: affine transform中的beta, 既\(\beta\)
需要注意的是,如果設置了momentum,那么均值的計算會考慮上次的均值
BatchNorm 的核心是,對於每一個batch的數據,假設有N個特征,這個N個特征中,對應位置的特征,會被BatchNorm放到一起計算,對於1D,2D,和3D ,唯一的區別就是計算的時候,特征的維度。具體來說:
# 這里每一個特征維度是1維,尺寸為N
input(BatchNorm1D) : ( batch , num_features, 1*N)
# 這里每一個特征的維度是2維度,常用於圖像,對應featrue map的長和寬
input(BatchNorm2D) : ( batch , num_features, width, height)
# 這里每一個特征的維度是3維度,常用語3位數據,可以理解為多個圖像,
# 既num_of_wh個圖像
input: (batch, num_features, width, height, num_of_wh)
Layer Normalization
Layer Normalization 主要是針對於1維變長序列數據,例如,在自然語言處理中,每一個batch中,句子的長度不一樣,這個時候,Layer Normalization就可以用於這種情況,LayerNorm主要計算的是一個batch中,每一個句子自己去做計算,也就是說,每一個樣本中,N個特征自己去計算均值和方差,而不是batch之間去計算。 對應於CNN的話,假設每個batch,有N個feature map,然后LayerNorm就是計算每個Batch里面,這個N個feature_map的均值和方差。
Pytorch中對應得LayerNorm函數如下:
nn.LayerNorm()
參數:
normalized_shape
: 每一層的形狀,也就是長度
eps
: 分母修正項
elementwise_affine
: 是否需要affine transform
LayerNorm 計算和BatchNorm計算基本一樣,區別是,LayerNorm 不是跨batch進行計算的,因此,也就不再有running_mean 和 runing_var了。
在使用的時候,Layer需要注意的是,設置normalized_shape, 其實就是設置特征的尺寸,這個和BatchNorm不同,BatchNorm主要設置的是特征的個數。另外,這里的LayerNorm也可以處理不同維度特征,只需要設置特征的尺寸就可以了。具體使用方式如下:
# input 1D : (batch, seq_len, N) 主要針對序列數據,每句話長度為seq_len,維度為N,這個時候
# LayerNorm需要將normalized_shape設置成N
layer_norm = nn.LayerNorm((N),eps=0.0001,elementwise_affine=True)
# input2D : (batch, num, width, height) 主要針對圖像數據,有num個feature map,
# 尺寸為(width, height)
layer_norm = nn.LayerNorm((width,height),eps=0.0001,elementwise_affine=True)
# input3D : (batch, num, width, height, num_of_wh)
layer_norm = nn.LayerNorm((width,height,num_of_wh),eps=0.0001,elementwise_affine=True)
Group Normalization
第三個是Group Normalization,這里的batch是2,所以估計的均值方差都很小,所以就可以考慮用特征來求均值方差,這個的gamma和beta還是對應於特征數
Group Normalization和LayerNorm比較相似,只不過,LayerNrom使用所有特征進行計算的,而Group是對特征進行分組計算。
pytorch中對應的函數,這里的num_channels對應的是特征數
nn.GroupNorm()
參數:
num_groups
: 分組的個數
num_channels
: 通道數,也可以理解為特征的個數
eps
: 分母修正項
affine
: 是否需要計算affine transform
需要注意的是,這里也不會計算running_mean 和 running_var.
Instance Normalization
Instance Normalization計算方式如下所示,每一個樣本有三個特征,每一個特征自己去計算一個均值方差,所以稱為instance Normalization,這個主要用於風格遷移任務中。從卷積網絡的角度來理解,就是每一個feature map 自己單獨計算均值和方差,這里需要注意的是,輸入的參數和BatchNorm一樣,也是輸入特征數量,每一個特征單獨計算的時候,也會加權之前對應位置特征的均值和方差。具體的用法和BatchNorm 一樣。
nn.InstanceNorm()
參數:這和上面的BatchNorm參數是一樣的
num_features
: 樣本中有多少特征
eps
: 分母修正項
momentum
: 指數加權計算均值方差
affine
: 是否進行affine transofrm
track_running_stats
: 是否重新計算均值方差。