nn.moduleList 和Sequential由来、用法和实例 —— 写网络模型
對(duì)于cnn前饋神經(jīng)網(wǎng)絡(luò)如果前饋一次寫一個(gè)forward函數(shù)會(huì)有些麻煩,在此就有兩種簡(jiǎn)化方式,ModuleList和Sequential。其中Sequential是一個(gè)特殊的module,它包含幾個(gè)子Module,前向傳播時(shí)會(huì)將輸入一層接一層的傳遞下去。ModuleList也是一個(gè)特殊的module,可以包含幾個(gè)子module,可以像用list一樣使用它,但不能直接把輸入傳給ModuleList。下面舉例說(shuō)明。
目錄
一、nn.Sequential()對(duì)象
1、模型建立方式
第一種寫法:
?第二種寫法:
第三種寫法:
2、檢查以及調(diào)用模型
查看模型
根據(jù)名字或序號(hào)提取子Module對(duì)象
調(diào)用模型
二、nn.ModuleList()對(duì)象
為什么有他?
什么時(shí)候用?
和list的區(qū)別?
1. extend和append方法
2. 建立以及使用方法
3. yolo v3構(gòu)建網(wǎng)絡(luò)
一、nn.Sequential()對(duì)象
建立nn.Sequential()對(duì)象,必須小心確保一個(gè)塊的輸出大小與下一個(gè)塊的輸入大小匹配?;旧?#xff0c;它的行為就像一個(gè)nn.Module。
?
1、模型建立方式
第一種寫法:
nn.Sequential()對(duì)象.add_module(層名,層class的實(shí)例)
1
2
3
4
net1?=?nn.Sequential()
net1.add_module('conv', nn.Conv2d(3,?3,?3))
net1.add_module('batchnorm', nn.BatchNorm2d(3))
net1.add_module('activation_layer', nn.ReLU())
?第二種寫法:
nn.Sequential(*多個(gè)層class的實(shí)例)
1
2
3
4
5
net2?=?nn.Sequential(
????????nn.Conv2d(3,?3,?3),
????????nn.BatchNorm2d(3),
????????nn.ReLU()
????????)
第三種寫法:
nn.Sequential(OrderedDict([*多個(gè)(層名,層class的實(shí)例)]))
1
2
3
4
5
6
from?collections?import?OrderedDict
net3=?nn.Sequential(OrderedDict([
??????????('conv', nn.Conv2d(3,?3,?3)),
??????????('batchnorm', nn.BatchNorm2d(3)),
??????????('activation_layer', nn.ReLU())
????????]))
?
?
2、檢查以及調(diào)用模型
查看模型
print對(duì)象即可
1
2
3
print('net1:', net1)
print('net2:', net2)
print('net3:', net3)
net1: Sequential(
(conv): Conv2d (3, 3, kernel_size=(3, 3), stride=(1, 1))
(batchnorm): BatchNorm2d(3, eps=1e-05, momentum=0.1, affine=True)
(activation_layer): ReLU()
)
net2: Sequential(
(0): Conv2d (3, 3, kernel_size=(3, 3), stride=(1, 1))
(1): BatchNorm2d(3, eps=1e-05, momentum=0.1, affine=True)
(2): ReLU()
)
net3: Sequential(
(conv): Conv2d (3, 3, kernel_size=(3, 3), stride=(1, 1))
(batchnorm): BatchNorm2d(3, eps=1e-05, momentum=0.1, affine=True)
(activation_layer): ReLU()
)
根據(jù)名字或序號(hào)提取子Module對(duì)象
1
2
# 可根據(jù)名字或序號(hào)取出子module
net1.conv, net2[0], net3.conv
(Conv2d (3, 3, kernel_size=(3, 3), stride=(1, 1)),
Conv2d (3, 3, kernel_size=(3, 3), stride=(1, 1)),
Conv2d (3, 3, kernel_size=(3, 3), stride=(1, 1)))
調(diào)用模型
可以直接網(wǎng)絡(luò)對(duì)象(輸入數(shù)據(jù)),也可以使用上面的Module子對(duì)象分別傳入(input)。
1
2
3
4
5
input?=?V(t.rand(1,?3,?4,?4))
output?=?net1(input)
output?=?net2(input)
output?=?net3(input)
output?=?net3.activation_layer(net1.batchnorm(net1.conv(input)))
?
二、nn.ModuleList()對(duì)象
為什么有他?
寫一個(gè)module然后就寫foreword函數(shù)很麻煩,所以就有了這兩個(gè)。它被設(shè)計(jì)用來(lái)存儲(chǔ)任意數(shù)量的nn. module。
什么時(shí)候用?
如果在構(gòu)造函數(shù)__init__中用到list、tuple、dict等對(duì)象時(shí),一定要思考是否應(yīng)該用ModuleList或ParameterList代替。
如果你想設(shè)計(jì)一個(gè)神經(jīng)網(wǎng)絡(luò)的層數(shù)作為輸入傳遞。
和list的區(qū)別?
ModuleList是Module的子類,當(dāng)在Module中使用它的時(shí)候,就能自動(dòng)識(shí)別為子module。
當(dāng)添加 nn.ModuleList 作為 nn.Module 對(duì)象的一個(gè)成員時(shí)(即當(dāng)我們添加模塊到我們的網(wǎng)絡(luò)時(shí)),所有 nn.ModuleList 內(nèi)部的 nn.Module 的 parameter 也被添加作為 我們的網(wǎng)絡(luò)的 parameter。
?
class MyModule(nn.Module):
def __init__(self):
super(MyModule, self).__init__()
self.linears = nn.ModuleList([nn.Linear(10, 10) for i in range(10)])
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. extend和append方法
nn.moduleList定義對(duì)象后,有extend和append方法,用法和python中一樣,extend是添加另一個(gè)modulelist? append是添加另一個(gè)module
class LinearNet(nn.Module):
def __init__(self, input_size, num_layers, layers_size, output_size):
super(LinearNet, self).__init__()
self.linears = nn.ModuleList([nn.Linear(input_size, layers_size)])
self.linears.extend([nn.Linear(layers_size, layers_size) for i in range(1, self.num_layers-1)])
self.linears.append(nn.Linear(layers_size, output_size)
2. 建立以及使用方法
建立以及使用方法如下,
1
2
3
4
5
6
modellist?=?nn.ModuleList([nn.Linear(3,4), nn.ReLU(), nn.Linear(4,2)])
input?=?V(t.randn(1,?3))
for?model?in?modellist:
????input?=?model(input)
# 下面會(huì)報(bào)錯(cuò),因?yàn)閙odellist沒有實(shí)現(xiàn)forward方法
# output = modelist(input)
?
和普通list不一樣,它和torch的其他機(jī)制結(jié)合緊密,繼承了nn.Module的網(wǎng)絡(luò)模型class可以使用nn.ModuleList并識(shí)別其中的parameters,當(dāng)然這只是個(gè)list,不會(huì)自動(dòng)實(shí)現(xiàn)forward方法,
1
2
3
4
5
6
7
8
9
class?MyModule(nn.Module):
????def?__init__(self):
????????super(MyModule,?self).__init__()
????????self.list?=?[nn.Linear(3,?4), nn.ReLU()]
????????self.module_list?=?nn.ModuleList([nn.Conv2d(3,?3,?3), nn.ReLU()])
????def?forward(self):
????????pass
model?=?MyModule()
print(model)
MyModule(
(module_list): ModuleList(
(0): Conv2d (3, 3, kernel_size=(3, 3), stride=(1, 1))
(1): ReLU()
)
)
1
2
for?name, param?in?model.named_parameters():
????print(name, param.size())
('module_list.0.weight', torch.Size([3, 3, 3, 3]))
('module_list.0.bias', torch.Size([3]))
可見,普通list中的子module并不能被主module所識(shí)別,而ModuleList中的子module能夠被主module所識(shí)別。這意味著如果用list保存子module,將無(wú)法調(diào)整其參數(shù),因其未加入到主module的參數(shù)中。
除ModuleList之外還有ParameterList,其是一個(gè)可以包含多個(gè)parameter的類list對(duì)象。在實(shí)際應(yīng)用中,使用方式與ModuleList類似。
?
3. yolo v3構(gòu)建網(wǎng)絡(luò)
首先module_list = nn.ModuleList()
然后?
??for index, x in enumerate(blocks[1:]):#根據(jù)不同的block 遍歷module
????????module = nn.Sequential()
? ? ? ? 然后根據(jù)cfg讀進(jìn)來(lái)的數(shù)據(jù),
? ? ? ? module.add_module("batch_norm_{0}".format(index), bn)
? ? ? ? module.add_module("conv_{0}".format(index), conv)
? ? ? ? ?等等
? ? ? ? ?module_list.append(module)
?
---------------------
作者:Snoopy_Dream
來(lái)源:CSDN
原文:https://blog.csdn.net/e01528/article/details/84397174
版權(quán)聲明:本文為博主原創(chuàng)文章,轉(zhuǎn)載請(qǐng)附上博文鏈接!
總結(jié)
以上是生活随笔為你收集整理的nn.moduleList 和Sequential由来、用法和实例 —— 写网络模型的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: BERT可视化工具bertviz体验
- 下一篇: Pytorch的默认初始化分布 nn.E