前言:類似於keras中的序貫模型,當一個模型較簡單的時候,我們可以使用torch.nn.Sequential類來實現簡單的順序連接模型。這個模型也是繼承自Module類的,關於這個類,后面的文章會詳細介紹。
一、關於Sequential類的簡介
先來看一下它的定義吧,在之前,我們首先需要明確一個特別重要的觀念,那就是——torch的核心是Module類,
Module類在下面這個模塊中:
D:\ProgramData\Anaconda3\envs\pytorch1.1.0\Lib\site-packages\torch\nn\modules\module.py
Sequential繼承自Module,在下面這個模塊里面:
D:\ProgramData\Anaconda3\envs\pytorch1.1.0\Lib\site-packages\torch\nn\modules\container.py
這樣看起來,Sequential似乎是一個容器,的確,他確確實實是可以作為一個容器包裝機各層,我在下一篇文章會說到,這里還是先簡單看一下它的定義:
class Sequential(Module): # 繼承Module def __init__(self, *args): # 重寫了構造函數 def _get_item_by_idx(self, iterator, idx): def __getitem__(self, idx): def __setitem__(self, idx, module): def __delitem__(self, idx): def __len__(self): def __dir__(self): def forward(self, input): # 重寫關鍵方法forward
這里還看一下這個所謂的container.py里面還有哪些“容器”存在:
class Container(Module): class Sequential(Module): class ModuleList(Module): class ModuleDict(Module): class ParameterList(Module): class ParameterDict(Module):
二、Sequential類不同的實現(3種實現)
2.1 最簡單的序貫模型(直接堆疊)
import torch.nn as nn model = nn.Sequential( nn.Conv2d(1,20,5), nn.ReLU(), nn.Conv2d(20,64,5), nn.ReLU() ) print(model) print(model[2]) # 通過索引獲取第幾個層 '''運行結果為: Sequential( (0): Conv2d(1, 20, kernel_size=(5, 5), stride=(1, 1)) (1): ReLU() (2): Conv2d(20, 64, kernel_size=(5, 5), stride=(1, 1)) (3): ReLU() ) Conv2d(20, 64, kernel_size=(5, 5), stride=(1, 1)) '''
注意:這樣做有一個問題,每一個層是沒有名稱,默認的是以0、1、2、3來命名,從上面的運行結果也可以看出。
2.2 給每一個層添加名稱(傳入OrderDict())
import torch.nn as nn from collections import OrderedDict model = nn.Sequential(OrderedDict([ ('conv1', nn.Conv2d(1,20,5)), ('relu1', nn.ReLU()), ('conv2', nn.Conv2d(20,64,5)), ('relu2', nn.ReLU()) ])) print(model) print(model[2]) # 通過索引獲取第幾個層 '''運行結果為: Sequential( (conv1): Conv2d(1, 20, kernel_size=(5, 5), stride=(1, 1)) (relu1): ReLU() (conv2): Conv2d(20, 64, kernel_size=(5, 5), stride=(1, 1)) (relu2): ReLU() ) Conv2d(20, 64, kernel_size=(5, 5), stride=(1, 1)) '''
注意:從上面的結果中可以看出,這個時候每一個層都有了自己的名稱,但是此時需要注意,我並不能夠通過名稱直接獲取層,依然只能通過索引index,即
model[2] 是正確的
model["conv2"] 是錯誤的
這其實是由它的定義實現的,看上面的Sequenrial類的定義可知,只支持index訪問(getitem_by_index)。
2.3 Sequential的第三種實現(通過.add_module()逐個添加)
import torch.nn as nn from collections import OrderedDict model = nn.Sequential() model.add_module("conv1",nn.Conv2d(1,20,5)) model.add_module('relu1', nn.ReLU()) model.add_module('conv2', nn.Conv2d(20,64,5)) model.add_module('relu2', nn.ReLU()) print(model) print(model[2]) # 通過索引獲取第幾個層
熟悉keras的小伙伴在這里一定特別熟悉,這不就是keras的做法嘛,的確是的,但是Sequential里面好像並沒有定義
add_module()方法啊,實際上,這個方法是定義在它的父類Module里面的,Sequential繼承了而已,它的定義如下:
def add_module(self, name, module):
總結:上面的3種定義順序模型的方法是較為常見的,但是我們說了Sequential除了本身可以用來定義模型之外,它還可以包裝層,把幾個層包裝起來像一個塊一樣,這在后面會說到。
原文鏈接:https://blog.csdn.net/qq_27825451/java/article/details/90551513