转载:https://blog.csdn.net/gdxdekx/article/details/122691668
https://blog.csdn.net/Just_do_myself/article/details/124195393
1.介绍查看帮助文档的方法
代码查看:
import torch
import torch.nn as nn
# help(torch.ones),我们可以调用help函数。例如,我们来[查看张量ones函数的用法。]
help(torch.ones)
# 查看torch.nn.Sequential的帮助文档
help(nn.Sequential)
2.用法
CLASS torch.nn.Sequential(*args: Module)
A sequential container. Modules will be added to it in the order they are passed in the constructor. Alternatively, an
OrderedDict
of modules can be passed in. Theforward()
method ofSequential
accepts any input and forwards it to the first module it contains. It then “chains” outputs to inputs sequentially for each subsequent module, finally returning the output of the last module.The value a
Sequential
provides over manually calling a sequence of modules is that it allows treating the whole container as a single module, such that performing a transformation on theSequential
applies to each of the modules it stores (which are each a registered submodule of theSequential
).What’s the difference between a
Sequential
and a torch.nn.ModuleList? AModuleList
is exactly what it sounds like–a list for storingModule
s! On the other hand, the layers in aSequential
are connected in a cascading way.
Sequential容器。 模块将按照它们在构造函数中传递的顺序添加。 另外,可以将模块的有序列表传递给。 然后,它将“链”输出输入到每个后续模块,最后返回最后一个模块的输出。顺序通过手动调用一个模块的序列提供的值是,它允许将整个容器视为单个模块,以便在顺序上执行转换适用于其存储的每个模块(每个模块都是一个注册的子模块 顺序)。
Sequential
和nn.modulelist有什么区别? modulelist 恰恰是听起来的样子 - 存储模块s的列表! 另一方面,连续的Sequential
以级联的方式连接。
看个例子:
import torch
import torch.nn as nn
from collections import OrderedDict
# 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())
]))
结果:
nn.Sequential()的本质作用
按照上边的说法,与一层一层的单独调用模块组成序列相比,nn.Sequential() 可以允许将整个容器视为单个模块(即相当于把多个模块封装成一个模块),forward()方法接收输入之后,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后直接输出激活函数作用之后的结果。
nn.Sequential()和torch.nn.ModuleList的区别在于:torch.nn.ModuleList只是一个储存网络模块的list,其中的网络模块之间没有连接关系和顺序关系。而nn.Sequential()内的网络模块之间是按照添加的顺序级联的。
nn.Sequential()源码
def __init__(self, *args):
super().__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)
nn.Sequential()首先判断接收的参数是否为OrderedDict类型,如果是的话,分别取出OrderedDict内每个元素的key(自定义的网络模块名)和value(网络模块),然后将其通过add_module方法添加到nn.Sequrntial()中。