1. 程式人生 > 實用技巧 >【501】pytorch教程之nn.Module類詳解

【501】pytorch教程之nn.Module類詳解

參考:pytorch教程之nn.Module類詳解——使用Module類來自定義模型

  pytorch中對於一般的序列模型,直接使用torch.nn.Sequential類及可以實現,這點類似於keras,但是更多的時候面對複雜的模型,比如:多輸入多輸出、多分支模型、跨層連線模型、帶有自定義層的模型等,就需要自己來定義一個模型了。本文將詳細說明如何讓使用Mudule類來自定義一個模型。

  pytorch裡面一切自定義操作基本上都是繼承nn.Module類來實現的。

  我們在定義自已的網路的時候,需要繼承nn.Module類,並重新實現建構函式__init__建構函式和forward這兩個方法。但有一些注意技巧:

  • 一般把網路中具有可學習引數的層(如全連線層、卷積層等)放在建構函式__init__()中,當然我也可以吧不具有引數的層也放在裡面;
  • 一般把不具有可學習引數的層(如ReLU、dropout、BatchNormanation層)可放在建構函式中,也可不放在建構函式中,如果不放在建構函式__init__裡面,則在forward方法裡面可以使用nn.functional來代替
  • forward方法是必須要重寫的,它是實現模型的功能,實現各個層之間的連線關係的核心。

  所有放在建構函式__init__裡面的層的都是這個模型的“固有屬性”。

  官方例子

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

class Model(nn.Module):
    def __init__(self):
        # 固定內容
        super(Model, self).__init__()

        # 定義相關的函式
        self.conv1 = nn.Conv2d(1, 20, 5)
        self.conv2 = nn.Conv2d(20, 20, 5)

    def forward(self, x):
        # 構建模型結構,可以使用F函式內容,其他呼叫__init__裡面的函式
        x = F.relu(self.conv1(x))

        # 返回最終的結果
        return F.relu(self.conv2(x))

☀☀☀<< 舉例 >>☀☀☀

  程式碼一:

import torch

N, D_in, H, D_out = 64, 1000, 100, 10
 
torch.manual_seed(1)
x = torch.randn(N, D_in)
y = torch.randn(N, D_out)
 
#-----changed part-----#
model = torch.nn.Sequential(
    torch.nn.Linear(D_in, H),
    torch.nn.ReLU(),
    torch.nn.Linear(H, D_out),
)
#-----changed part-----#

loss_fn = torch.nn.MSELoss(reduction='sum')
learning_rate = 1e-4
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
for t in range(500):
    y_pred = model(x)
    loss = loss_fn(y_pred, y)
    if t % 100 == 99:
        print(t, loss.item())
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

  程式碼二:

import torch

N, D_in, H, D_out = 64, 1000, 100, 10

torch.manual_seed(1)
x = torch.randn(N, D_in)
y = torch.randn(N, D_out)

#-----changed part-----#
class Alex_nn(nn.Module):
    def __init__(self):
        super(Alex_nn, self).__init__()
        self.h1 = torch.nn.Linear(D_in, H)
        self.h1_relu = torch.nn.ReLU()
        self.output = torch.nn.Linear(H, D_out)
        
    def forward(self, x):
        h1 = self.h1(x)
        h1_relu = self.h1_relu(h1)
        output = self.output(h1_relu)
        return output
        
model = Alex_nn()
#-----changed part-----#

loss_fn = torch.nn.MSELoss(reduction='sum')
learning_rate = 1e-4
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
for t in range(500):
    y_pred = model(x)
    loss = loss_fn(y_pred, y)
    if t % 100 == 99:
        print(t, loss.item())
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

  程式碼三:

import torch

N, D_in, H, D_out = 64, 1000, 100, 10

torch.manual_seed(1)
x = torch.randn(N, D_in)
y = torch.randn(N, D_out)

#-----changed part-----#
class Alex_nn(nn.Module):
    def __init__(self, D_in_, H_, D_out_):
        super(Alex_nn, self).__init__()
        self.D_in = D_in_
        self.H = H_
        self.D_out = D_out_
        
        self.h1 = torch.nn.Linear(self.D_in, self.H)
        self.h1_relu = torch.nn.ReLU()
        self.output = torch.nn.Linear(self.H, self.D_out)
        
    def forward(self, x):
        h1 = self.h1(x)
        h1_relu = self.h1_relu(h1)
        output = self.output(h1_relu)
        return output
        
model = Alex_nn(D_in, H, D_out)
#-----changed part-----#

loss_fn = torch.nn.MSELoss(reduction='sum')
learning_rate = 1e-4
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
for t in range(500):
    y_pred = model(x)
    loss = loss_fn(y_pred, y)
    if t % 100 == 99:
        print(t, loss.item())
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()