1.建立模型
import torch.nn as nn
import torch
import numpy as np
第一种方法:nn.Sequential()对象.add_module(层名,层class的实例)
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(多个层class的实例)
net2=nn.Sequential(
nn.Conv2d(3,3,3),
nn.BatchNorm2d(3),
nn.ReLU()
)
第三种方法:nn.Sequential(OrderedDict([层名,层class的实例]))
from collections import OrderedDict
net3=nn.Sequential(OrderedDict([
('conv',nn.Conv2d(3,3,3)),
('batchnorm',nn.BatchNorm2d(3)),
('activation_layer',nn.ReLU())
]))
2.查看模型
print(net1)
Sequential(
(conv): Conv2d(3, 3, kernel_size=(3, 3), stride=(1, 1))
(batchnorm): BatchNorm2d(3, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(activation_layer): ReLU()
)
print(net2)
Sequential(
(0): Conv2d(3, 3, kernel_size=(3, 3), stride=(1, 1))
(1): BatchNorm2d(3, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(2): ReLU()
)
print(net3)
Sequential(
(conv): Conv2d(3, 3, kernel_size=(3, 3), stride=(1, 1))
(batchnorm): BatchNorm2d(3, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(activation_layer): ReLU()
)
3.提取子module对象
net1.conv
Conv2d(3, 3, kernel_size=(3, 3), stride=(1, 1))
BatchNorm2d(3, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
net2[0]
Conv2d(3, 3, kernel_size=(3, 3), stride=(1, 1))
net3.conv
Conv2d(3, 3, kernel_size=(3, 3), stride=(1, 1))
4.调用模型
可以直接将数据输入网络中,也可以使用上面的Module子对象分别传入输入数据
a=torch.rand(1,3,4,4)
output1=net1(a)
output1.shape
torch.Size([1, 3, 2, 2])
output1=net2(a)
output1.shape
torch.Size([1, 3, 2, 2])
output1=net3(a)
output1.shape
torch.Size([1, 3, 2, 2])
output1=net3.conv(a)
output1.shape
torch.Size([1, 3, 2, 2])
5.查看每层参数
for name,parm in net1.named_parameters():
print(name,parm)
conv.weight Parameter containing:
tensor([[[[ 0.1248, -0.1676, -0.0221],
[-0.1005, 0.1782, 0.1286],
[ 0.1199, 0.1207, -0.1452]],
[[-0.1085, 0.0304, 0.0343],
[-0.0180, 0.1129, 0.1154],
[-0.0113, 0.0513, -0.0662]],
[[-0.0264, -0.0293, 0.1318],
[ 0.1089, 0.0927, -0.0658],
[-0.1722, 0.0948, 0.1745]]],
[[[ 0.1377, 0.1561, 0.0465],
[-0.1419, -0.1055, -0.0563],
[ 0.0818, 0.1034, -0.1776]],
[[ 0.0144, -0.0388, -0.0545],
[ 0.1214, 0.1893, -0.1189],
[ 0.0596, -0.0839, -0.1748]],
[[ 0.1665, 0.0308, -0.1102],
[ 0.0777, -0.1707, 0.0012],
[ 0.1142, -0.0522, -0.0888]]],
[[[-0.0491, -0.1448, -0.0026],
[ 0.0584, -0.1670, 0.1772],
[-0.0135, -0.1363, -0.1036]],
[[ 0.1768, -0.1662, 0.1386],
[ 0.1426, -0.1009, -0.0828],
[ 0.1675, 0.0223, -0.1242]],
[[-0.1465, 0.0104, 0.1871],
[-0.1870, -0.1127, -0.1707],
[ 0.1605, -0.1369, 0.1509]]]])
conv.bias Parameter containing:
tensor(1.00000e-02 *
[ 4.3432, 9.0630, 6.4161])
batchnorm.weight Parameter containing:
tensor([ 0.1980, 0.8656, 0.5977])
batchnorm.bias Parameter containing:
tensor([ 0., 0., 0.])
ModuleList是Module的子类,当在Module中使用它的时候,可以自动识别为子module
modellist=nn.ModuleList([nn.Linear(3,4),nn.ReLU(),nn.Linear(4,2)])
print(modellist)
ModuleList(
(0): Linear(in_features=3, out_features=4, bias=True)
(1): ReLU()
(2): Linear(in_features=4, out_features=2, bias=True)
)
input=torch.rand(1,3)
input
tensor([[ 0.5325, 0.4064, 0.4870]])
for model in modellist:
input=model(input)
print(input)
tensor([[ 0.5814, -0.0939]])
如下使用方法将报错
output=modellist(input)
---------------------------------------------------------------------------
NotImplementedError Traceback (most recent call last)
<ipython-input-44-1418d0eaf845> in <module>
----> 1 output=modellist(input)
~/anaconda3/lib/python3.6/site-packages/torch/nn/modules/module.py in __call__(self, *input, **kwargs)
489 result = self._slow_forward(*input, **kwargs)
490 else:
--> 491 result = self.forward(*input, **kwargs)
492 for hook in self._forward_hooks.values():
493 hook_result = hook(self, input, result)
~/anaconda3/lib/python3.6/site-packages/torch/nn/modules/module.py in forward(self, *input)
81 registered hooks while the latter silently ignores them.
82 """
---> 83 raise NotImplementedError
84
85 def register_buffer(self, name, tensor):
NotImplementedError:
ModuleList 类似于list,模型中未自动实现forward函数
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()
)
)
for name, parm in model.named_parameters():
print(name,parm.size())
MyModule(
(module_list): ModuleList(
(0): Conv2d(3, 3, kernel_size=(3, 3), stride=(1, 1))
(1): ReLU()
)
)
module_list.0.weight torch.Size([3, 3, 3, 3])
module_list.0.bias torch.Size([3])
module_list.0.weight torch.Size([3, 3, 3, 3])
module_list.0.bias torch.Size([3])
list中的子module并不能被主module所识别,而ModuleList中的子module能够被主module所识别。这意味着如果用list保存子module,将无法调整其参数,因其未加入到主module的参数中。
结论:直接利用Sequential构建网络可以不用定义forward函数,利用ModuleList时需要构建forward函数,构建自己模型常用ModuleList函数建立子模型,建立forward函数实现前向传播;
参考:
https://www.cnblogs.com/hellcat/p/8477195.html