1. 程式人生 > 其它 >引數初始化

引數初始化

一、前言

1、深度學習框架提供預設隨機初始化

2、深度學習框架提供了最常用的規則,也允許建立自定義初始化方法

3、預設情況下,Pytorch會根據一個範圍均勻地初始化權重和偏置矩陣,這個範圍是根據輸入和輸出維度計算出來的

二、內建初始化

1、下面程式碼將所有權重引數初始化為標準差為0.01的正態分佈,且將偏置引數設定為0

# 內建的初始化器
# m就是一個module
def init_normal(m):
    if type(m) == nn.Linear:
        # 給權重賦值-將所有權重引數初始化為標準差為0.01的正態分佈
        nn.init.normal_(m.weight, mean=0, std=0.01)
        # 給偏置賦值-將偏置設為0
        nn.init.zeros_(m.bias)

# 將net裡面所以層遍歷一遍
net.apply(init_normal)
net[0].weight.data[0], net[0].bias.data[0]

# 輸出結果

(tensor([-0.0210, -0.0141, -0.0058,  0.0037]), tensor(0.))

2、將所有引數初始化為給定的常數

# 將引數初始化為給定的常數
def init_constant(m):
    if type(m) == nn.Linear:
        '''
        torch.nn.init.constant_(tensor, val)[source]
        用值val填充向量tensor
        
        '''
        nn.init.constant_(m.weight, 1)
        nn.init.zeros_(m.bias)

net.apply(init_constant)
net[0].weight.data[0], net[0].bias.data[0]

#輸出結果

(tensor([1., 1., 1., 1.]), tensor(0.))

3、對不同的塊應用不同的初始化方法

# 對不同的塊用不同的初始化方法

def xavier(m):
    if type(m) == nn.Linear:
        # 均勻分佈
        nn.init.xavier_uniform_(m.weight)

def init_42(m):
    if type(m) == nn.Linear:
        # 常數賦值
        nn.init.constant_(m.weight, 42)

net[0].apply(xavier)
net[2].apply(init_42)
print(net[0].weight.data[0])
print(net[2].weight.data)

#輸出結果

tensor([ 0.1352, -0.2794,  0.1592,  0.3462])
tensor([[42., 42., 42., 42., 42., 42., 42., 42.]])

  

三、自定義初始化

def my_init(m):
    if type(m) == nn.Linear:
        print(
            "Init",
            *[(name, param.shape) for name, param in m.named_parameters()][0])
        
        # 對權重使用均勻分佈
        nn.init.uniform_(m.weight, -10, 10)
        
        m.weight.data *= m.weight.data.abs() >= 5

net.apply(my_init)
net[0].weight[:2]

#輸出結果

Init weight torch.Size([8, 4])
Init weight torch.Size([1, 8])
tensor([[ 0.0000,  5.1760,  0.0000, -7.1530],
        [ 0.0000,  0.0000,  0.0000, -0.0000]], grad_fn=<SliceBackward>)

我們可以直接設定引數,先直接定位到引數再給其賦值

net[0].weight.data[:] += 1
net[0].weight.data[0, 0] = 42
net[0].weight.data[0]

#輸出結果

tensor([42.0000,  6.1760,  1.0000, -6.1530])

  

四、引數繫結

1、在多個層間共享引數。我們可以定義一個稠密層,然後使用他的引數來設定另一個層的引數

2、列子表明,第二層和第三層是繫結的。他們不僅值相等,而且由相同的張量表示。因此,如果改變其中一個引數,另一個引數也會相應改變

# 在多個層間共享引數
# 我們需要給共享層一個名稱,以便可以引用它的引數。
shared = nn.Linear(8, 8)
net = nn.Sequential(nn.Linear(4, 8), nn.ReLU(), shared, nn.ReLU(), shared,
                    nn.ReLU(), nn.Linear(8, 1))
net(X)

# 檢查引數是否相同
print(net[2].weight.data[0] == net[4].weight.data[0])

# 改變net[2]中的值,net[4]也會改變。說明使用的其實是一個物件
net[2].weight.data[0, 0] = 100
print(net[2].weight.data[0,0])
print(net[4].weight.data[0,0])

# 確保它們實際上是同一個物件,而不只是有相同的值。
print(net[2].weight.data[0] == net[4].weight.data[0])

# 輸出結果

tensor([True, True, True, True, True, True, True, True])
tensor(100.)
tensor(100.)
tensor([True, True, True, True, True, True, True, True])