參考: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()
