nn.Module 函式詳解
nn.Module是所有網路模型結構的基類,無論是pytorch自帶的模型,還是要自定義模型,都需要繼承這個類。這個模組包含了很多子模組,如下所示,_parameters存放的是模型的引數,_buffers也存放的是模型的引數,但是是那些不需要更新的引數。帶hook的都是鉤子函式,詳見鉤子函式部分。
self._parameters = OrderedDict()
self._buffers = OrderedDict()
self._non_persistent_buffers_set = set()
self._backward_hooks = OrderedDict()
self._is_full_backward_hook = None
self._forward_hooks = OrderedDict()
self._forward_pre_hooks = OrderedDict()
self._state_dict_hooks = OrderedDict()
self._load_state_dict_pre_hooks = OrderedDict()
self._modules = OrderedDict()
此外,每一個模組還內建了一些常用的方法來幫助訪問和操作網路。
load_state_dict() #載入模型權重引數
parameters() #讀取所有引數
named_parameters() #讀取引數名稱和引數
buffers() #讀取self.named_buffers中的引數
named_buffers() #讀取self.named_buffers中的引數名稱和引數
children() #讀取模型中,所有的子模型
named_children() #讀取子模型名稱和子模型
requires_grad_() #設定模型是否開啟梯度反向傳播
Parameter類
Parameter是Tensor子類,所以繼承了Tensor類的屬性。例如data和grad屬性,可以根據data來訪問引數數值,用grad來訪問引數梯度。
weight_0 = nn.Parameters(torch.randn(10,10))
print(weight_0.data)
print(weight_0.grad)
定義變數的時候,nn.Parameter會被自動加入到引數列表中去
class MyModel(nn.Module):
def __init__(self):
super(MyModel,self).__init__()
self.weight1 = nn.Parameter(torch.randn(10,10))
self.weight2 = torch.randn(10,10)
def forward(self,x):
pass
model = MyModel()
for name,param in model.named_parameters():
print(name)
output: weight1
ParameterList
接定義成Parameter類外,還可以使用ParameterList和ParameterDict分別定義引數的列表和字典。ParameterList接收一個Parameter例項的列表作為輸入然後得到一個引數列表,使用的時候可以用索引來訪問某個引數,另外也可以使用append和extend在列表後面新增引數。
params = nn.ParameterList(
[nn.Parameter(torch.randn(10,10)) for i in range(5)]
)
params.append(nn.Parameter(torch.randn(3,3)))
ParameterDict
可以像新增字典資料那樣新增引數
params = nn.ParameterDict({
'linear1':nn.Parameter(torch.randn(10,5)),
'linear2':nn.Parameter(torch.randn(5,2))
})
模型構建
使用Sequential構建模型
# 寫法一
net = nn.Sequential(
nn.Linear(num_inputs, 1)
# 此處還可以傳入其他層
)
# 寫法二
net = nn.Sequential()
net.add_module('linear', nn.Linear(num_inputs, 1))
# net.add_module ......
# 寫法三
from collections import OrderedDict
net = nn.Sequential(OrderedDict([
('linear', nn.Linear(num_inputs, 1))
# ......
]))
print(net)
自定義模型
- 無引數模型
下面是一個展開操作,比如將2維影像展開成一維
class Flatten(nn.Module):
def __init__(self):
super(Flatten,self).__init__()
def forward(self,input):
return input.view(input.size(0),-1)
- 有引數模型
自定義一個Linear層
class MLinear(nn.Module):
def __init__(self,input,output):
super(MyLinear,self).__init__()
self.w = nn.Parameter(torch.randn(input,output))
self.b = nn.Parameter(torch.randn(output))
def foward(self,x):
x = self.w @ x + self.b
return x
- 組合模型
class Model(nn.Module):
def __init__(self):
super(Model,self).__init__()
self.l1 = nn.Linear(10,20)
self.l2 = nn.Linear(20,5)
def forward(self,x):
x = self.l1(x)
x = self.l2(x)
return x
ModuleList & ModuleDict
ModuleList 和 ModuleDict都是繼承與nn.Module, 與Seuqential不同的是,ModuleList 和 ModuleDict沒有自帶forward方法,所以只能作為一個模組和其他自定義方法進行組合。下面是使用示例:
class MyModuleList(nn.Module):
def __init__(self):
super(MyModuleList, self).__init__()
self.linears = nn.ModuleList(
[nn.Linear(10, 10) for i in range(3)]
)
def forward(self, x):
for linear in self.linears:
x = linear(x)
return x
class MyModuleDict(nn.Module):
def __init__(self):
super(MyModuleDict, self).__init__()
self.linears = nn.ModuleDict({
"linear1":nn.Linear(10,10),
"linear2":nn.Linear(10,10)
})
def forward(self, x):
x = self.linears["linear1"](x)
x = self.linears["linear2"](x)
return x