本文主要爲深度之眼pytorch訓練營二期學習筆記,詳細課程內容移步:深度之眼 https://ai.deepshare.net/index
目錄
背景知識
神經網絡的訓練過程中的參數學習是基於梯度下降法進行優化的。梯度下降法需要在開始訓練時給每一個參數賦一個初始值,因此權重初始化的選取十分的關鍵,設定什麼樣的初始化方法關係到模型能否成功學習。那麼如果我們把權重初始值全部設置爲0,會怎樣???通常來說,把權值初始值設置成0,不是一個理性的選擇,因爲實際上如果初始化爲0的話,模型將無法學習。因爲如果參數都爲0,在第一遍前向計算時,所有的隱層神經元的激活值都相同。這樣會導致深層神經元沒有區分性。這種現象也稱爲對稱權重現象。因此爲了打破這個現象,比較好的方式就是給每個參數隨機初始化一個值。
但是初始化的值太小,那麼導致神經元的輸入過小,經過多層之後信號就消失了,設置的過大導致數據狀態過大,對於sigmoid類型的激活函數來說,激活值就一下子飽和了,梯度接近於0,也是不好訓練的。
因此一般而言,參數初始化的區間應該根據神經元的性質進行差異化的設置。
Pytorch常見的幾種初始化方法。
高斯分佈初始化是最簡單的初始化方法,參數從一個固定均值(比如0)和固定方差(比如0.01)的Gaussian分佈進行隨機初始化。均勻分佈初始化是在一個給定的區間[−r,r]內採用均勻分佈來初始化參數
Xavier初始化
適合飽和的激活函數:Sigmoid、Tanh類型
1.Xavier均勻分佈初始化
2.Xavier正態分佈初始化
Kaiming初始化
適合非飽和的激活函數:Rulu及其變種類型
1.Kaiming正態分佈初始化
2.Kaiming均勻分佈初始化
Pytorch實現
"""
代碼來自深度之眼
"""
import os
import torch
import random
import numpy as np
import torch.nn as nn
class MLP(nn.Module):
def __init__(self, neural_num, layers):
super(MLP, self).__init__()
self.linears = nn.ModuleList([nn.Linear(neural_num, neural_num, bias=False) for i in range(layers)])
self.neural_num = neural_num
def forward(self, x):
for (i, linear) in enumerate(self.linears):
x = linear(x)
x = torch.relu(x)
print("layer:{}, std:{}".format(i, x.std()))
if torch.isnan(x.std()):
print("output is nan in {} layers".format(i))
break
return x
def initialize(self):
for m in self.modules():
if isinstance(m, nn.Linear):
# nn.init.normal_(m.weight.data, std=np.sqrt(1/self.neural_num)) # normal: mean=0, std=1
# a = np.sqrt(6 / (self.neural_num + self.neural_num))
#
# tanh_gain = nn.init.calculate_gain('tanh')
# a *= tanh_gain
#
# nn.init.uniform_(m.weight.data, -a, a)
# nn.init.xavier_uniform_(m.weight.data, gain=tanh_gain)
# nn.init.normal_(m.weight.data, std=np.sqrt(2 / self.neural_num))
nn.init.kaiming_normal_(m.weight.data)
Keras實現
keras的初始化十分簡單,在每添加一個層(Dense、Conv2D、LSTM等)的時候進行初始化的配置。