一、使用Numpy初始化:【直接對Tensor操作】
-
對Sequential模型的參數進行修改:
1 import numpy as np 2 import torch 3 from torch import nn 4 5 # 定義一個 Sequential 模型 6 net1 = nn.Sequential( 7 nn.Linear(30, 40), 8 nn.ReLU(), 9 nn.Linear(40, 50), 10 nn.ReLU(), 11 nn.Linear(50, 10) 12 ) 13 14 # 訪問第一層的參數 15 w1 = net1[0].weight 16 b1 = net1[0].bias 17 print(w1) 18 19 #對第一層Linear的參數進行修改: 20 # 定義第一層的參數 Tensor 直接對其進行替換 21 net1[0].weight.data = torch.from_numpy(np.random.uniform(3, 5, size=(40, 30))) 22 print(net1[0].weight)
23
24 #若模型中相同類型的層都需要初始化成相同的方式,一種更高效的方式:使用循環去訪問:
25 for layer in net1:
26 if isinstance(layer, nn.Linear): # 判斷是否是線性層
27 param_shape = layer.weight.shape
28 layer.weight.data = torch.from_numpy(np.random.normal(0, 0.5, size=param_shape))
29 # 定義為均值為 0,方差為 0.5 的正態分布
-
對Module模型 的參數初始化:
對於 Module 的參數初始化,其實也非常簡單,如果想對其中的某層進行初始化,可以直接像 Sequential 一樣對其 Tensor 進行重新定義,其唯一不同的地方在於,如果要用循環的方式訪問,需要介紹兩個屬性,children 和 modules,下面我們舉例來說明:
1、創建Module模型類:

1 class sim_net(nn.Module): 2 def __init__(self): 3 super(sim_net, self).__init__() 4 self.l1 = nn.Sequential( 5 nn.Linear(30, 40), 6 nn.ReLU() 7 ) 8 9 self.l1[0].weight.data = torch.randn(40, 30) # 直接對某一層初始化 10 11 self.l2 = nn.Sequential( 12 nn.Linear(40, 50), 13 nn.ReLU() 14 ) 15 16 self.l3 = nn.Sequential( 17 nn.Linear(50, 10), 18 nn.ReLU() 19 ) 20 21 def forward(self, x): 22 x = self.l1(x) 23 x =self.l2(x) 24 x = self.l3(x) 25 return x
2、創建模型對象:
net2 = sim_net()
3、訪問children:
# 訪問 children for i in net2.children(): print(i)
#打印的結果:
4、訪問modules:
# 訪問 modules for i in net2.modules(): print(i) #打印的結果 sim_net( (l1): Sequential( (0): Linear(in_features=30, out_features=40) (1): ReLU() ) (l2): Sequential( (0): Linear(in_features=40, out_features=50) (1): ReLU() ) (l3): Sequential( (0): Linear(in_features=50, out_features=10) (1): ReLU() ) ) Sequential( (0): Linear(in_features=30, out_features=40) (1): ReLU() ) Linear(in_features=30, out_features=40) ReLU() Sequential( (0): Linear(in_features=40, out_features=50) (1): ReLU() ) Linear(in_features=40, out_features=50) ReLU() Sequential( (0): Linear(in_features=50, out_features=10) (1): ReLU() ) Linear(in_features=50, out_features=10) ReLU()
通過上面的例子,可以看到:
children 只會訪問到模型定義中的第一層,因為上面的模型中定義了三個 Sequential,所以只會訪問到三個 Sequential,而 modules 會訪問到最后的結構,比如上面的例子,modules 不僅訪問到了 Sequential,也訪問到了 Sequential 里面,這就對我們做初始化非常方便。
5、采用循環初始化:
for layer in net2.modules(): if isinstance(layer, nn.Linear): param_shape = layer.weight.shape layer.weight.data = torch.from_numpy(np.random.normal(0, 0.5, size=param_shape))
二、torch.nn.init初始化
PyTorch 還提供了初始化的函數幫助我們快速初始化,就是 torch.nn.init
,其操作層面仍然在 Tensor 上。先介紹一種初始化方法:
Xavier 初始化方法:
其中 和
表示該層的輸入和輸出數目。
這種非常流行的初始化方式叫 Xavier,方法來源於 2010 年的一篇論文 Understanding the difficulty of training deep feedforward neural networks,其通過數學的推到,證明了這種初始化方式可以使得每一層的輸出方差是盡可能相等的。
torch.nn.init:
from torch.nn import init init.xavier_uniform(net1[0].weight) # 這就是上面我們講過的 Xavier 初始化方法,PyTorch 直接內置了其實現 #這就直接修改了net1[0].weight的值