PyTorch常用引數初始化方法詳解

發表於2022-03-08

1、均勻分佈初始化

   torch.nn.init.uniform_(tensor, a=0, b=1)

  從均勻分佈U(a, b)中取樣,初始化張量。
  引數:

    • tensor - 需要填充的張量  
    • a - 均勻分佈的下界  
    • b - 均勻分佈的上界  

  例子

w = torch.empty(3, 5)
nn.init.uniform_(w)
"""
tensor([[0.2116, 0.3085, 0.5448, 0.6113, 0.7697],
        [0.8300, 0.2938, 0.4597, 0.4698, 0.0624],
        [0.5034, 0.1166, 0.3133, 0.3615, 0.3757]])
"""

  均勻分佈詳解

  若 $x$ 服從均勻分佈,即 $x~U(a,b)$,其概率密度函式(表徵隨機變數每個取值有多大的可能性)為,

    $f(x)=\left\{\begin{array}{l}\frac{1}{b-a}, \quad a<x<b \\ 0, \quad else \end{array}\right.$

  則有期望和方差,

    $\begin{array}{c}E(x)=\int_{-\infty}^{\infty} x f(x) d x=\frac{1}{2}(a+b) \\D(x)=E\left(x^{2}\right)-[E(x)]^{2}=\frac{(b-a)^{2}}{12}\end{array}$

2、正態(高斯)分佈初始化

      torch.nn.init.normal_(tensor, mean=0.0, std=1.0)

  從給定的均值和標準差的正態分佈 $N\left(\right. mean, \left.s t d^{2}\right)$ 中生成值,初始化張量。

  引數:

    • tensor - 需要填充的張量  
    • mean - 正態分佈的均值  
    • std - 正態分佈的標準偏差  

  例子

w = torch.Tensor(3, 5)
torch.nn.init.normal_(w, mean=0, std=1)
"""
tensor([[-1.3903,  0.4045,  0.3048,  0.7537, -0.5189],
        [-0.7672,  0.1891, -0.2226,  0.2913,  0.1295],
        [ 1.4719, -0.3049,  0.3144, -1.0047, -0.5424]])
"""

  正態分佈詳解:

  若隨機變數 $x$ 服從正態分佈,即 $x \sim N\left(\mu, \sigma^{2}\right) $, 其概率密度函式為,

    $f(x)=\frac{1}{\sigma \sqrt{2 \pi}} \exp \left(-\frac{\left(x-\mu^{2}\right)}{2 \sigma^{2}}\right)$

  正態分佈概率密度函式中一些特殊的概率值:  

    • 68.268949% 的面積在平均值左右的一個標準差 $\sigma$ 範圍內 ($\mu \pm \sigma$)  
    • 95.449974% 的面積在平均值左右兩個標準差 $2 \sigma$ 的範圍內 ($\mu \pm 2 \sigma$)  
    • 99.730020% 的面積在平均值左右三個標準差 $3 \sigma$ 的範圍內 ($\mu \pm 3 \sigma$)  
    • 99.993666% 的面積在平均值左右四個標準差 $4 \sigma$ 的範圍內 ($\mu \pm 4 \sigma$)  

  $\mu=0$, $\sigma=1$ 時的正態分佈是標準正態分佈。

3. Xavier初始化

3.1 Xavier均勻分佈初始化

     torch.nn.init.xavier_uniform_(tensor, gain=1.0)

  又稱 Glorot 初始化,按照 Glorot, X. & Bengio, Y.(2010)在論文Understanding the difficulty of training deep feedforward neural networks 中描述的方法,從均勻分佈 $U(−a, a)$ 中取樣,初始化輸入張量 $tensor$,其中 $a $ 值由下式確定:

    $a=\text { gain } \times \sqrt{\frac{6}{\text { fan_in }+\text { fan_out }}}$

  例子

w = torch.Tensor(3, 5)
nn.init.xavier_uniform_(w, gain=torch.nn.init.calculate_gain('relu'))
"""
tensor([[ 0.7695, -0.7687, -0.2561, -0.5307,  0.5195],
        [-0.6187,  0.4913,  0.3037, -0.6374,  0.9725],
        [-0.2658, -0.4051, -1.1006, -1.1264, -0.1310]])
"""

3.2 Xavier正態分佈初始化

     torch.nn.init.xavier_normal_(tensor, gain=1.0)

  又稱 Glorot 初始化,按照 Glorot, X. & Bengio, Y.(2010)在論文Understanding the difficulty of training deep feedforward neural networks 中描述的方法,從均勻分佈 $N\left(0, s t d^{2}\right)$ 中取樣,初始化輸入張量 $tensor$,其中 $std$ 值由下式確定:

    $\operatorname{std}=\text { gain } \times \sqrt{\frac{2}{\text { fan_in }+\text { fan_out }}}$

  引數:

    • tensor - 需要初始化的張量  
    • gain - 可選的放縮因子  

  例子

w = torch.arange(10).view(2,-1).type(torch.float32)
torch.nn.init.xavier_normal_(w)
"""
tensor([[-0.3139, -0.3557,  0.1285, -0.9556,  0.3255],
        [-0.6212,  0.3405, -0.4150, -1.3227, -0.0069]])
"""

4. kaiming初始化

4.1 kaiming均勻分佈初始化

     torch.nn.init.kaiming_uniform_(tensor, a=0, mode='fan_in', nonlinearity='leaky_relu')

  又稱 He 初始化,按照He, K. et al. (2015)在論文Delving deep into rectifiers: Surpassing human-level performance on ImageNet classification中描述的方法,從均勻分佈$U(−bound, bound)$ 中取樣,初始化輸入張量 tensor,其中 bound 值由下式確定:

    $\text { bound }=\text { gain } \times \sqrt{\frac{3}{\text { fan_mode }}}$

  引數:

    • tensor - 需要初始化的張量;
    • $\mathrm{a}$- 這層之後使用的 rectifier的斜率係數,用來計算gain =\sqrt{\frac{2}{1+\mathrm{a}^{2}}} (此引數僅在引數nonlinea rity為'leaky_relu'時生效);
    • mode - 可以為“fan_in”(預設)或“fan_out”。“fan_in”維持前向傳播時權值方差,“fan_out”維持反向傳播時的方差;
    • nonlinearity - 非線性函式(nn.functional中的函式名),pytorch建議僅與“relu”或“leaky_relu”(預設)一起使用;

  例子

w = torch.Tensor(3, 5)
torch.nn.init.kaiming_uniform_(w, mode='fan_in', nonlinearity='relu')
"""
tensor([[-0.4362, -0.8177, -0.7034,  0.7306, -0.6457],
        [-0.5749, -0.6480, -0.8016, -0.1434,  0.0785],
        [ 1.0369, -0.0676,  0.7430, -0.2484, -0.0895]])
"""

4.2 kaiming正態分佈初始化

     torch.nn.init.kaiming_normal_(tensor, a=0, mode='fan_in', nonlinearity='leaky_relu')

  又稱He初始化,按照He, K. et al. (2015)在論文Delving deep into rectifiers: Surpassing human-level performance on ImageNet classification中描述的方法,從正態分佈 $N\left(0, s t d^{2}\right)$ 中取樣,初始化輸入張量tensor,其中std值由下式確定:

  引數:

    • tensor - 需要初始化的張量;
    • $\mathrm{a} $ - 這層之後使用的 rectifier 的斜率係數,用來計算 $gain =\sqrt{\frac{2}{1+\mathrm{a}^{2}}} $ (此引數僅在引數nonlinea rity為'leaky_relu'時生效);
    • mode - 可以為"fan_in" (預設) 或“fan_out"。"fan_in"維持前向傳播時權值方差,"fan_out"維持反 向傳播時的方差;
    • nonlinearity - 非線性函式 (nn.functional中的函式名),pytorch建議僅與“relu”或"leaky_relu”(默 認)一起使用;

5、正交矩陣初始化

     torch.nn.init.orthogonal_(tensor, gain=1)

  用一個(半)正交矩陣初始化輸入張量,參考Saxe, A. et al. (2013) - Exact solutions to the nonlinear dynamics of learning in deep linear neural networks。輸入張量必須至少有 2 維,對於大於 2 維的張量,超出的維度將被flatten化。

  正交初始化可以使得卷積核更加緊湊,可以去除相關性,使模型更容易學到有效的引數。

  引數:

    • tensor - 需要初始化的張量  
    • gain - 可選的放縮因子  

  例子:

w = torch.Tensor(3, 5)
torch.nn.init.orthogonal_(w)
"""
tensor([[ 0.7395, -0.1503,  0.4474,  0.4321, -0.2090],
        [-0.2625,  0.0112,  0.6515, -0.4770, -0.5282],
        [ 0.4554,  0.6548,  0.0970, -0.4851,  0.3453]])
"""

6、稀疏矩陣初始化

     torch.nn.init.sparse_(tensor, sparsity, std=0.01)

  將2維的輸入張量作為稀疏矩陣填充,其中非零元素由正態分佈 $N\left(0,0.01^{2}\right)$ 生成。 參考Martens, J.(2010)的 Deep learning via Hessian-free optimization。

  引數:

    • tensor - 需要填充的張量  
    • sparsity - 每列中需要被設定成零的元素比例  
    • std - 用於生成非零元素的正態分佈的標準偏差  

  例子:

w = torch.Tensor(3, 5)
torch.nn.init.sparse_(w, sparsity=0.1)
"""
tensor([[-0.0026,  0.0000,  0.0100,  0.0046,  0.0048],
        [ 0.0106, -0.0046,  0.0000,  0.0000,  0.0000],
        [ 0.0000, -0.0005,  0.0150, -0.0097, -0.0100]])
"""

7、常數初始化

     torch.nn.init.constant_(tensor, val)

  使值為常數 val 。

  例子:

w=torch.Tensor(3,5)
nn.init.constant_(w,1.2)
"""
tensor([[1.2000, 1.2000, 1.2000, 1.2000, 1.2000],
        [1.2000, 1.2000, 1.2000, 1.2000, 1.2000],
        [1.2000, 1.2000, 1.2000, 1.2000, 1.2000]])
"""

8、單位矩陣初始化

     torch.nn.init.eye_(tensor)

  將二維 tensor 初始化為單位矩陣(the identity matrix)

  例子:

w=torch.Tensor(3,5)
nn.init.eye_(w)
"""
tensor([[1., 0., 0., 0., 0.],
        [0., 1., 0., 0., 0.],
        [0., 0., 1., 0., 0.]])
"""

9、零填充初始化

     torch.nn.init.zeros_(tensor)

  例子:

w = torch.empty(3, 5)
nn.init.zeros_(w)
"""
tensor([[0., 0., 0., 0., 0.],
        [0., 0., 0., 0., 0.],
        [0., 0., 0., 0., 0.]])
"""

10、應用

  例子:

print('module-----------')
print(model)
print('setup-----------')
for m in model.modules():
    if isinstance(m,nn.Linear):
        nn.init.xavier_uniform_(m.weight, gain=nn.init.calculate_gain('relu'))
"""
module-----------
Sequential(
  (flatten): FlattenLayer()
  (linear1): Linear(in_features=784, out_features=512, bias=True)
  (activation): ReLU()
  (linear2): Linear(in_features=512, out_features=256, bias=True)
  (linear3): Linear(in_features=256, out_features=10, bias=True)
)
setup-----------
"""

  例子:  

for param in model.parameters():
    nn.init.uniform_(param)

  例子: 

def weights_init(m):
    classname = m.__class__.__name__
    if classname.find('Conv2d') != -1:
        nn.init.xavier_normal_(m.weight.data)
        nn.init.constant_(m.bias.data, 0.0)
    elif classname.find('Linear') != -1:
        nn.init.xavier_normal_(m.weight)
        nn.init.constant_(m.bias, 0.0)
model.apply(weights_init) #apply函式會遞迴地搜尋網路內的所有module並把參數列示的函式應用到所有的module上。

 

相關文章