pytorch教程之nn.Sequential類詳解——使用Sequential類來自定義順序連接模型


前言:類似於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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM