python - 激活没有变量分配的pytorch网络节点?
问题描述
在 PyTorch 网络的教程中,我们通常会看到如下实现:
from torch.nn.functional import hardtanh, sigmoid
import torch.nn as nn
class great_network(nn.Module):
def __init__(self):
super(great_network, self).__init__()
self.layer1 = nn.Conv2d(2, 2, 3)
self.pool_1 = nn.MaxPool2d(1, 1)
self.layer3 = nn.ConvTranspose2d(2, 2, 3)
self.out_layer = nn.Conv2d(1, 1, 3)
def forward(self, x):
x = hardtanh(self.layer1(x))
x = self.pool_1(x)
x = hardtanh(self.layer3(x))
x = sigmoid(self.out_layer(x))
return x
net = great_network()
print(net)
great_network(
(layer1): Conv2d(2, 2, kernel_size=(3, 3), stride=(1, 1))
(pool_1): MaxPool2d(kernel_size=1, stride=1, padding=0, dilation=1, ceil_mode=False)
(layer3): ConvTranspose2d(2, 2, kernel_size=(3, 3), stride=(1, 1))
(out_layer): Conv2d(1, 1, kernel_size=(3, 3), stride=(1, 1))
)
如果我要动态更改此网络的大小以运行多个实验,我必须在没有多个分配的情况下模拟上述代码(类似于数据块代码膨胀)。
这样的事情可能会做:
from torch.nn.functional import hardtanh, sigmoid
import torch.nn as nn
import numpy as np
class not_so_great_network(nn.Module):
def __init__(self, n):
super(not_so_great_network, self).__init__()
self.pre_layers = self.generate_pre_layers(n)
self.post_layers = self.generate_post_layers(n)
self.pool = nn.MaxPool2d(1, 1)
self.out = nn.Conv2d(1, 1, 3)
def generate_pre_layers(self, layer_num):
layers = np.empty(layer_num, dtype = object)
for lay in range(0, len(layers)):
layers[lay] = nn.Conv2d(2, 2, 3)
return layers
def generate_post_layers(self, layer_num):
layers = np.empty(layer_num, dtype = object)
for lay in range(0, len(layers)):
layers[lay] = nn.Conv2d(2, 2, 3)
return layers
def forward(self, x):
for pre in self.pre_layers:
x = hardtanh(pre(x))
x = self.pool(x)
for post in self.post_layers:
x = hardtanh(post(x))
x = sigmoid(self.out(x))
return x
但是,并非所有层都存在:
if __name__ == '__main__':
layer_num = 5
net = not_so_great_network(layer_num)
print(net)
not_so_great_network(
(pool): MaxPool2d(kernel_size=1, stride=1, padding=0, dilation=1, ceil_mode=False)
(out): Conv2d(1, 1, kernel_size=(3, 3), stride=(1, 1))
)
我没有分配变量,因为如果我可以在不复制和粘贴的情况下生成不同大小的网络,这可能会更强大。如何模拟输出,以便以后可以使用激活函数激活节点?
解决方案
另一种方法是使用ModuleList
:
from torch import nn
from torch.nn.functional import hardtanh, sigmoid
class maybe_great_network(nn.Module):
def __init__(self, n):
super().__init__()
self.pre_layers = self.generate_pre_layers(n)
self.post_layers = self.generate_post_layers(n)
self.pool = nn.MaxPool2d(1, 1)
self.out = nn.Conv2d(1, 1, 3)
def generate_pre_layers(self, layer_num):
return nn.ModuleList([
nn.Conv2d(2, 2, 3)
for l in range(0, layer_num)
])
def generate_post_layers(self, layer_num):
return nn.ModuleList([
nn.Conv2d(2, 2, 3)
for l in range(0, layer_num)
])
def forward(self, x):
for pre in self.pre_layers:
x = hardtanh(pre(x))
x = self.pool(x)
for post in self.post_layers:
x = hardtanh(post(x))
x = sigmoid(self.out(x))
return x
然后:
>>> m = maybe_great_network(3)
>>> m
maybe_great_network(
(pre_layers): ModuleList(
(0): Conv2d(2, 2, kernel_size=(3, 3), stride=(1, 1))
(1): Conv2d(2, 2, kernel_size=(3, 3), stride=(1, 1))
(2): Conv2d(2, 2, kernel_size=(3, 3), stride=(1, 1))
)
(post_layers): ModuleList(
(0): Conv2d(2, 2, kernel_size=(3, 3), stride=(1, 1))
(1): Conv2d(2, 2, kernel_size=(3, 3), stride=(1, 1))
(2): Conv2d(2, 2, kernel_size=(3, 3), stride=(1, 1))
)
(pool): MaxPool2d(kernel_size=1, stride=1, padding=0, dilation=1, ceil_mode=False)
(out): Conv2d(1, 1, kernel_size=(3, 3), stride=(1, 1))
)
推荐阅读
- vb.net - 无法向 tableadapter 添加查询
- c# - 单一仓库中软件包的独立版本控制
- javascript - 如何为所有选项卡设置相同的背景图像?(反应原生)
- svgpanzoom - 将绘图居中到特定视图框中的点
- shell - 脚本手动运行,在 Cron 中不起作用
- sql - 如何将数据从一个表插入另一个表并用所需数据填充其他列
- c# - ASP MVC 中的 Jquery dataTables serverSide
- python - 如何集成两个独立的 Flask 应用程序
- ios - 在 SPA 中导航时,iOS Webview 不会更改 url
- javascript - 如何使用jquery将特定类添加到锚标记的href等于URL?