赞
踩
目录
先通过图片总结了解三个容器方法的主要区别:
可以直接添加网络层、也可以先声明后利用add_module(name:str,module)方法添加网络层,还可以使用OrderDict([*(name:str,module)])函数添加。
- net1 = nn.Sequential(
- nn.Conv2d(3,6,kernel_size=5),
- nn.Conv2d(6,10,kernel_size=3),
- nn.BatchNorm2d(10),
- nn.ReLU(),
- )
-
- net2 = nn.Sequential()
- net2.add_module('conv1',nn.Conv2d(3,6,kernel_size=5))
- net2.add_module('conv2',nn.Conv2d(6,10,kernel_size=3))
- net2.add_module('bn',nn.BatchNorm2d(10))
- net2.add_module('relu',nn.ReLU())
-
- net3 = nn.Sequential(OrderedDict([
- ['conv1',nn.Conv2d(3,6,kernel_size=5)],
- ('conv2',nn.Conv2d(6,10,kernel_size=3))
- ]))
-
- print('#####################')
- print(net1)
- print('#####################')
- print(net2)
- print('#####################')
- print(net3)
输出结果为
- #####################
- Sequential(
- (0): Conv2d(3, 6, kernel_size=(5, 5), stride=(1, 1))
- (1): Conv2d(6, 10, kernel_size=(3, 3), stride=(1, 1))
- (2): BatchNorm2d(10, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
- (3): ReLU()
- )
- #####################
- Sequential(
- (conv1): Conv2d(3, 6, kernel_size=(5, 5), stride=(1, 1))
- (conv2): Conv2d(6, 10, kernel_size=(3, 3), stride=(1, 1))
- (bn): BatchNorm2d(10, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
- (relu): ReLU()
- )
- #####################
- Sequential(
- (conv1): Conv2d(3, 6, kernel_size=(5, 5), stride=(1, 1))
- (conv2): Conv2d(6, 10, kernel_size=(3, 3), stride=(1, 1))
- )
nn.ModuleList里面储存了不同 module,并自动将每个 module 的 parameters 添加到网络容器内容(注册),里面的module是按照List的形式顺序存储的,但是在forward中调用的时候可以随意组合。可以任意将 nn.Module 的子类 (比如 nn.Conv2d, nn.Linear 之类的) 加到这个 list 里面,方法和 Python 自带的 list 一样,也就是说它可以使用 extend,append 等操作。
- model = nn.ModuleList([
- nn.Conv2d(3, 6, kernel_size=5),
- nn.Conv2d(6, 10, kernel_size=3),
- nn.BatchNorm2d(10),
- nn.ReLU(),
- ])
- model.extend([nn.Linear(10,10) for i in range(5)])
- print(model)
输出结果为:
- ModuleList(
- (0): Conv2d(3, 6, kernel_size=(5, 5), stride=(1, 1))
- (1): Conv2d(6, 10, kernel_size=(3, 3), stride=(1, 1))
- (2): BatchNorm2d(10, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
- (3): ReLU()
- (4): Linear(in_features=10, out_features=10, bias=True)
- (5): Linear(in_features=10, out_features=10, bias=True)
- (6): Linear(in_features=10, out_features=10, bias=True)
- (7): Linear(in_features=10, out_features=10, bias=True)
- (8): Linear(in_features=10, out_features=10, bias=True)
- )
运行模块可以直接使用列表索引方式或者利用for循环调用,但是顺序不固定
- input = torch.randn(1,6,3,3)
- out = model[1](input)
- print(out.shape)
-
- #view():[1,10,1,1]->[1,10]
- out = out.view(out.shape[0],out.shape[1])
-
- out = [model[i](out) for i in range(4,7)]
- for o in out:
- print(o.shape)
-
- ######################
-
- torch.Size([1, 10, 1, 1])
- torch.Size([1, 10])
- torch.Size([1, 10])
- torch.Size([1, 10])
nn.ModuleDict书写格式也分为两种:一种是nn.ModuleDict( {name:module , name:module ,...} ),另一种是nn.ModuleDict([ [name,module] , [name,module], ... ])
- class MyNet(nn.Module):
- def __init__(self):
- super(MyNet, self).__init__()
- self.choices = nn.ModuleDict({
- '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
-
- net = MyNet()
- print(net)
输出结果为
- MyNet(
- (choices): ModuleDict(
- (conv): Conv2d(10, 10, kernel_size=(3, 3), stride=(1, 1))
- (pool): MaxPool2d(kernel_size=3, stride=3, padding=0, dilation=1, ceil_mode=False)
- )
- (activations): ModuleDict(
- (lrelu): LeakyReLU(negative_slope=0.01)
- (prelu): PReLU(num_parameters=1)
- )
- )
三、参考文献
PyTorch中的Sequential、ModuleList和ModuleDict用法总结_非晚非晚的博客-CSDN博客
nn.Sequential与nn.ModuleList_HySmiley的博客-CSDN博客
pytorch模型容器Containers nn.ModuleDict、nn.moduleList、nn.Sequential_nn.moduledict()_发呆的比目鱼的博客-CSDN博客
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。