iT邦幫忙

2022 iThome 鐵人賽

DAY 14
0

Part0:前言

開始看Pytorch關於神經網路的code後,發現同一個模型有多種搭建方法,整個頭腦很錯亂(資質平凡XD,就把一些專有名詞google一遍,才了解原來大有學問!! 也因此有了寫這篇文章的動機囉~~


Part1:今日目標

1.Pytorch常見搭建神經網路方法
2.模型容器(container)
3.官方文件定義&舉例說明


Part2:內容

1.Pytorch常見搭建神經網路方法

一個完整模型將堆疊多個模組(神經層),堆疊方式又有兩種:
(1)自建nn.Module子類別
(2)nn.Sequential(類似操作: nn.ModuleList、nn.ModuleDict)

兩種方法簡要比較如下:

模型搭建方式 (1)nn.Module (2)nn.Sequential
定義 base class for all neural network modules a direct subclass of nn.Module (Ref)
特點 能自行設定傳播過程(forward function) 快速搭建「一層連接一層」的模型建構
補充 在大型模型結構中,可用nn.Sequential建立一個個分塊(sequential submodules),在組裝成整個模型

2.模型容器(container)

其中nn.Sequential又可視為一個容器(container),為nn.Module的子類別(subclass),類似的容器還有nn.ModuleListnn.ModuleDict,比較如下

nn.Sequential nn.ModuleList nn.ModuleDict
定義 A sequential container. Holds submodules in a list and also a container. 同左,但有索引(index)可指定
特點 按照順序來排列,須確定上一層輸出和下一層輸入大小一致 儲存不同模組(modules,又稱為神經層layers)並將每個module的參數(parameters),可把任意nn.Module加入該串列(list),加入後會自動將這些module&它們的參數添加到整個神經網路,在forward可任意調動順序做組合 同左,同樣自動將每個module和參數添加到網路
差別_1 內建forward函數,不用另外寫 沒有forward函數,需自行設定 同左
影響_1 無法自訂forward函數,缺乏彈性。一般是用此來建立卷積塊(block),再將一個個block組成一個神經網路 具備彈性,能自行設定forward函數 同左
差別_2 可搭配OrderedDict對每一層神經層命名 無相關設定 通過鍵值對(key,value)方式為每個神經層指定命名
差別_3 模型按此順序排列運行,須確定上一層輸出和下一層輸入大小一致 只是定義所有模塊,執行順序由foward函數設定(但層與層之間輸出輸入還是要一致) 同左
差別_4 可搭配迴圈(for-loop)方便建類似或相似的神經層
常見方法 append(), extend(), insert() clear(), items(), pop()等等

3.官方文件定義&舉例說明

以上四個類別(nn.Module, nn.Sequential, nn.ModuleList, nn.ModuleDict)介紹如下:

(1)CLASS torch.nn.Module

  • Definition(Def): Base class for all neural network modules. Your models should also subclass this class. nn.Module為Pytorch中專門為神經網路開發的類別(class),其中包含建立各種神經網路架構所需的單元,這些建構單元稱為模組(modules),或又稱為層、神經層(layers),藉由建立nn.Module的子類別(subclass),能定義自己的神經網路。

  • 一個Pytorch模組即是繼承nn.Module基本類別的Pytorch類別(class),能以屬性的方式接受一個或多個參數張量Parameter物件,這些參數數值將會在模型訓練過程中進行優化。

  • 一個模組還能以屬性方式加入一個或多個子模組(submodules,nn.Module的子類別),用以追蹤參數數值,範例如下圖:

import torch.nn as nn
import torch.nn.functional as F

class Model(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(1, 20, 5)  # 屬性
        self.conv2 = nn.Conv2d(20, 20, 5)  # 屬性

    def forward(self, x):
        x = F.relu(self.conv1(x))
        return F.relu(self.conv2(x))

(1-1-1)CLASS torch.nn.Sequential(*args)

  • Def: A sequential container. Modules will be added to it in the order they are passed in the constructor. Alternatively, an ordered dict of modules can also be passed in. Pytorch提供的一種簡單連接模組(modules)的類別,有兩種操作方法: 直接操作Sequential或是搭配字典(OrderedDict)建立。
# 法一: Using Sequential to create a small model.
model = nn.Sequential(
          nn.Conv2d(1,20,5),
          nn.ReLU(),
          nn.Conv2d(20,64,5),
          nn.ReLU()
        )

# 法二: Using Sequential with OrderedDict.
model = nn.Sequential(OrderedDict([
          ('conv1', nn.Conv2d(1,20,5)),
          ('relu1', nn.ReLU()),
          ('conv2', nn.Conv2d(20,64,5)),
          ('relu2', nn.ReLU())
        ]))

子模組必須為最高屬性(top-level attributes),若直接放在串列(list)或字典(dict)中做為屬性,優化器會無法找到子模組與它們的參數,能將無法優化和更新結果。若想將一系列模組包裹成串列或字典,則要使用Pytorch提供的nn.ModuleList或nn.ModuleDict。

(1-1-2)CLASS torch.nn.ModuleList(modules=None)

  • Def: Holds submodules in a list. ModuleList can be indexed like a regular Python list, but modules it contains are properly registered, and will be visible by all Module methods. 將一系列子模組(submodules)包裹在串列中。
class MyModule(nn.Module):
    def __init__(self):
        super(MyModule, self).__init__()
        self.linears = nn.ModuleList([nn.Linear(10, 10) for i in range(10)])  # an iterable of modules to add

    def forward(self, x):
        # ModuleList can act as an iterable, or be indexed using ints
        for i, l in enumerate(self.linears):
            x = self.linears[i // 2](x) + l(x)
        return x

(1-1-3)CLASStorch.nn.ModuleDict(modules=None)

  • Def: Holds submodules in a list. ModuleDict can be indexed like a regular Python dictionary, but modules it contains are properly registered, and will be visible by all Module methods.
class MyModule(nn.Module):
    def __init__(self):
        super(MyModule, self).__init__()
        self.choices = nn.ModuleDict({  # a mapping (dictionary) of (string: module) or an iterable of key-value pairs of type (string, module)
                'conv': nn.Conv2d(10, 10, 3),
                'pool': nn.MaxPool2d(3)
        })
        self.activations = nn.ModuleDict([
                ['lrelu', nn.LeakyReLU()],
                ['prelu', nn.PReLU()]
        ])

    def forward(self, x, choice, act):
        x = self.choices[choice](x)
        x = self.activations[act](x)
        return x

Part3:專案進度

透過今日統整學習,更了解在Pytorch有哪些方式能建立神經網路架構。

Part4:下一步

明後天比較一些常見的影像分類模型,例如:ALXnet、ResNet等,學習原始論文的模型架構和相關Pytorch程式碼。


參考:

心得小語:
今天練完中提琴中指指腹敲鍵盤都會痛,但練許多天的小步舞曲(Minuet No.3)終於有點起色啦(開心灑花~~~ 因為鐵人賽讓生活好像過得異常規律,吃晚餐、練琴、散步、寫鐵人文章,這麼規律充實peace的生活步調,也是挺不錯的呢~~ 期待明天的學習分享囉,See you TMR!
今日工時: 50mins*5 (周末小小偷跑XD

任何值得做的事就值得把它做好
Whatever is worth doing is worth doing well.


上一篇
D13-Lenet模型_模型架構學習2nd
下一篇
D15-影像識別經典模型簡介1st_AlexNet
系列文
菜鳥工程師第一個電腦視覺(CV)專案-農作物影像辨識競賽32
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

1
AndrewYEE
iT邦新手 3 級 ‧ 2023-08-22 19:08:25

謝謝

我要留言

立即登入留言