一个序列容器,用于搭建神经网络的模块被按照被传入的构造器的顺序添加到 n n . S e q u e n t i a l ( ) nn.Sequential() nn.Sequential()容器中,除此之外,一个包含神经网络模块的 O r d e r e d D i c t OrderedDict OrderedDict也可以传入到 n n . S e q u e n t i a l ( ) nn.Sequential() nn.Sequential()容器中,利用 n n . S e q u e n t i a l ( ) nn.Sequential() nn.Sequential()搭建好的网络架构,模型前向传播时调用 f o r w a r d ( ) forward() forward()方法,模型接收的输入首先被传入nn.Sequential()包含的第一个网络模块中.然后第一个网络模块的输出被传入第二个网络模块作为输入,按照顺序依次计算并传播,直到nn.Sequential()里的最后一个模块输出结果。
# Using Sequential to create a small model. When `model` is run,
# input will first be passed to `Conv2d(1,20,5)`. The output of
# `Conv2d(1,20,5)` will be used as the input to the first
# `ReLU`; the output of the first `ReLU` will become the input
# for `Conv2d(20,64,5)`. Finally, the output of
# `Conv2d(20,64,5)` will be used as input to the second `ReLU`
model = nn.Sequential(
nn.Conv2d(1,20,5),
nn.ReLU(),
nn.Conv2d(20,64,5),
nn.ReLU()
)
# Using Sequential with OrderedDict. This is functionally the
# same as the above code
model = nn.Sequential(OrderedDict([
('conv1', nn.Conv2d(1,20,5)),
('relu1', nn.ReLU()),
('conv2', nn.Conv2d(20,64,5)),
('relu2', nn.ReLU())
]))
按照上面的说法,与一层一层单独调用模块组成序列相比, n n . S e q u e n t i a l nn.Sequential nn.Sequential可以允许将整个容器视为单个模块,(即相当于把多个模块封装成一个模块), f o r w a r d ( ) forward() forward()接收输入之后, n n . S e q u e n t i a l ( ) nn.Sequential() nn.Sequential()按照**内部模块的顺序自动依次计算并输出结果
**。
这就意味着我们可以利用nn.Sequential() 自定义自己的网络层。
from torch import nn
class net(nn.Module):
def __init__(self, in_channel, out_channel):
super(net, self).__init__()
self.layer1 = nn.Sequential(nn.Conv2d(in_channel, in_channel / 4, kernel_size=1),
nn.BatchNorm2d(in_channel / 4),
nn.ReLU())
self.layer2 = nn.Sequential(nn.Conv2d(in_channel / 4, in_channel / 4),
nn.BatchNorm2d(in_channel / 4),
nn.ReLU())
self.layer3 = nn.Sequential(nn.Conv2d(in_channel / 4, out_channel, kernel_size=1),
nn.BatchNorm2d(out_channel),
nn.ReLU())
def forward(self, x):
x = self.layer1(x)
x = self.layer2(x)
x = self.layer3(x)
return x
上边的代码,我们通过nn.Sequential()将卷积层,BN层和激活函数层封装在一个层中,输入x经过卷积、BN和ReLU后直接输出激活函数作用之后的结果。
def __init__(self, *args):
super(Sequential, self).__init__()
if len(args) == 1 and isinstance(args[0], OrderedDict):
for key, module in args[0].items():
self.add_module(key, module)
else:
for idx, module in enumerate(args):
self.add_module(str(idx), module)
n n . S e q u e n t i a l nn.Sequential nn.Sequential首先判断接收的参数是否为 O r d e r e d D i c t OrderedDict OrderedDict类型,如果是的话,分别取出OrderedDict内每个元素的key(自定义的网络模块名)和value(网络模块),然后将其通过add_module方法添加到nn.Sequrntial()中。
# NB: We can't really type check this function as the type of input
# may change dynamically (as is tested in
# TestScript.test_sequential_intermediary_types). Cannot annotate
# with Any as TorchScript expects a more precise type
def forward(self, input):
for module in self:
input = module(input)
return input
调用 f o r w a r d ( ) forward() forward()方法,进行前向传播时, f o r for for循环按照顺序遍历,nn.Sequential()中存储的网络模块,并以此计算输出结果,并返回最终的计算结果。
会自己总结各个模块的用处,然后会建立自己的网络架构,了解自己的代码产生能力。