Pytorch系列:(三)模型構建

Q發表於2021-04-26

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)

自定義模型

  1. 無引數模型

下面是一個展開操作,比如將2維影像展開成一維

class Flatten(nn.Module):
    def __init__(self):
        super(Flatten,self).__init__()
      
    def forward(self,input):
        return input.view(input.size(0),-1) 
  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  
  1. 組合模型
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

相關文章