import torch
from torch import nn
import torch.nn.functional as F
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.embedding = nn.Embedding(num_embeddings = 10000,
embedding_dim = 3,padding_idx = 1)
self.conv = nn.Sequential()
self.conv.add_module("conv_1",nn.Conv1d(in_channels = 3,
out_channels = 16,kernel_size = 5))
self.conv.add_module("pool_1",nn.MaxPool1d(kernel_size = 2))
self.conv.add_module("relu_1",nn.ReLU())
self.conv.add_module("conv_2",nn.Conv1d(in_channels = 16,
out_channels = 128,
kernel_size = 2))
self.conv.add_module("pool_2",nn.MaxPool1d(kernel_size = 2))
self.conv.add_module("relu_2",nn.ReLU())
self.dense = nn.Sequential()
self.dense.add_module("flatten",nn.Flatten())
self.dense.add_module("linear",nn.Linear(6144,1))
self.dense.add_module("sigmoid",nn.Sigmoid())
def forward(self,x):
x = self.embedding(x).transpose(1,2)
x = self.conv(x)
y = self.dense(x)
return y
net = Net()
.modules()
,返回一个生成器,包括模块下的所有各个层级的模块,也包括模块本身1、先打印看一下返回值:
print(list(net.modules()))
输出:
[Net(
(embedding): Embedding(10000, 3, padding_idx=1)
(conv): Sequential(
(conv_1): Conv1d(3, 16, kernel_size=(5,), stride=(1,))
(pool_1): MaxPool1d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(relu_1): ReLU()
(conv_2): Conv1d(16, 128, kernel_size=(2,), stride=(1,))
(pool_2): MaxPool1d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(relu_2): ReLU()
)
(dense): Sequential(
(flatten): Flatten()
(linear): Linear(in_features=6144, out_features=1, bias=True)
(sigmoid): Sigmoid()
)
),
Embedding(10000, 3, padding_idx=1),
Sequential(
(conv_1): Conv1d(3, 16, kernel_size=(5,), stride=(1,))
(pool_1): MaxPool1d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(relu_1): ReLU()
(conv_2): Conv1d(16, 128, kernel_size=(2,), stride=(1,))
(pool_2): MaxPool1d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(relu_2): ReLU()
),
Conv1d(3, 16, kernel_size=(5,), stride=(1,)),
MaxPool1d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False), ReLU(),
Conv1d(16, 128, kernel_size=(2,), stride=(1,)),
MaxPool1d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False), ReLU(),
Sequential(
(flatten): Flatten()
(linear): Linear(in_features=6144, out_features=1, bias=True)
(sigmoid): Sigmoid()
),
Flatten(),
Linear(in_features=6144, out_features=1, bias=True),
Sigmoid()]
可以看出该属性返回的信息比较多,你可以理解为它会一级一级的返回信息,先返回整个模块本身,然后是第一级子模块,然后再返回各个一级子模块里的子模块,也就是二级子模块。其实只要具体的模型具体分析,每次都按照上述方式打印出来看一看这些子模块是怎样保存的,那么就可以正确的索引到你想要的某一特定层。
2、下面就来获取指定的某一层,然后获取之后还能获取该层的属性信息:
modules=list(net.modules())
print(modules[2][1])
print(modules[2][1].kernel_size,modules[2][1].ceil_mode)
输出:
MaxPool1d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
2 False
.named_modules()
,返回一个生成器,包括模块下的所有各个层级的模块以及它们的名字,也包括模块本身1、先打印看一下返回值:
print(list(net.named_modules()))
输出:
[('', Net(
(embedding): Embedding(10000, 3, padding_idx=1)
(conv): Sequential(
(conv_1): Conv1d(3, 16, kernel_size=(5,), stride=(1,))
(pool_1): MaxPool1d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(relu_1): ReLU()
(conv_2): Conv1d(16, 128, kernel_size=(2,), stride=(1,))
(pool_2): MaxPool1d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(relu_2): ReLU()
)
(dense): Sequential(
(flatten): Flatten()
(linear): Linear(in_features=6144, out_features=1, bias=True)
(sigmoid): Sigmoid()
)
)),
('embedding', Embedding(10000, 3, padding_idx=1)),
('conv', Sequential(
(conv_1): Conv1d(3, 16, kernel_size=(5,), stride=(1,))
(pool_1): MaxPool1d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(relu_1): ReLU()
(conv_2): Conv1d(16, 128, kernel_size=(2,), stride=(1,))
(pool_2): MaxPool1d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(relu_2): ReLU()
)),
('conv.conv_1', Conv1d(3, 16, kernel_size=(5,), stride=(1,))),
('conv.pool_1', MaxPool1d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)),
('conv.relu_1', ReLU()),
('conv.conv_2', Conv1d(16, 128, kernel_size=(2,), stride=(1,))),
('conv.pool_2', MaxPool1d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)),
('conv.relu_2', ReLU()),
('dense', Sequential(
(flatten): Flatten()
(linear): Linear(in_features=6144, out_features=1, bias=True)
(sigmoid): Sigmoid()
)),
('dense.flatten', Flatten()),
('dense.linear', Linear(in_features=6144, out_features=1, bias=True)),
('dense.sigmoid', Sigmoid())]
2、下面就来获取指定的某一层,然后获取之后还能获取该层的属性信息:
modules=list(net.named_modules())
print(modules[2][1][1])
print(modules[2][1][1].kernel_size,modules[2][1][1].ceil_mode)
输出:
MaxPool1d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
2 False
可以看出,和第一种方式相比,我们取的是同一层,但是在索引上多了一维,那是因为每一层的名称占了一维。
._modules
,返回的是一个有序字典,里面包含了各个一级子模块,不包含本身,也不包含更低级的子模块。1、先打印看一下返回值:
print(net._modules)
输出:
OrderedDict([('embedding', Embedding(10000, 3, padding_idx=1)),
('conv', Sequential(
(conv_1): Conv1d(3, 16, kernel_size=(5,), stride=(1,))
(pool_1): MaxPool1d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(relu_1): ReLU()
(conv_2): Conv1d(16, 128, kernel_size=(2,), stride=(1,))
(pool_2): MaxPool1d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(relu_2): ReLU()
)),
('dense', Sequential(
(flatten): Flatten()
(linear): Linear(in_features=6144, out_features=1, bias=True)
(sigmoid): Sigmoid()
))])
2、再遍历一下该字典,注意需要遍历其.items()属性:
for name,layer in net._modules.items():
print(name)
print(layer)
输出:
embedding
Embedding(10000, 3, padding_idx=1)
conv
Sequential(
(conv_1): Conv1d(3, 16, kernel_size=(5,), stride=(1,))
(pool_1): MaxPool1d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(relu_1): ReLU()
(conv_2): Conv1d(16, 128, kernel_size=(2,), stride=(1,))
(pool_2): MaxPool1d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(relu_2): ReLU()
)
dense
Sequential(
(flatten): Flatten()
(linear): Linear(in_features=6144, out_features=1, bias=True)
(sigmoid): Sigmoid()
)
可以看出,和.modules()
相比,返回的信息简洁了很多,因为它只返回第一级子模块,没有继续的返回各个子模块的子模块。
3、下面我们就来看一下如何去除具体的某一层,并打印出该层的属性:
modules=net._modules
print(modules['conv'][0])
print(modules['conv'][0].kernel_size,modules['conv'][0].stride)
输出:
Conv1d(3, 16, kernel_size=(5,), stride=(1,))
(5,) (1,)
children()
: 返回一个生成器,包括模块下的所有子模块print(list(net.children()))
输出:
[Embedding(10000, 3, padding_idx=1),
Sequential(
(conv_1): Conv1d(3, 16, kernel_size=(5,), stride=(1,))
(pool_1): MaxPool1d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(relu_1): ReLU()
(conv_2): Conv1d(16, 128, kernel_size=(2,), stride=(1,))
(pool_2): MaxPool1d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(relu_2): ReLU()
),
Sequential(
(flatten): Flatten()
(linear): Linear(in_features=6144, out_features=1, bias=True)
(sigmoid): Sigmoid()
)]
print(list(net.named_children()))
输出:
[('embedding', Embedding(10000, 3, padding_idx=1)),
('conv', Sequential(
(conv_1): Conv1d(3, 16, kernel_size=(5,), stride=(1,))
(pool_1): MaxPool1d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(relu_1): ReLU()
(conv_2): Conv1d(16, 128, kernel_size=(2,), stride=(1,))
(pool_2): MaxPool1d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(relu_2): ReLU()
)),
('dense', Sequential(
(flatten): Flatten()
(linear): Linear(in_features=6144, out_features=1, bias=True)
(sigmoid): Sigmoid()
))]
可以看到,当返回的是生成器的时候,我们需要使用list
将其变成能够显示具体内容的列表,否则直接打印的话是不显示具体内容的。当然我们可以直接遍历该生成器,此时就不需要使用list
了。