网络结构搭建实例
1. 网络结构图
-
图示为适应 cifar10 数据集的一个网络结构图,本文主要针对于复现如下网络结构,并介绍相关函数的使用
2. 网络结构各层参数分析
-
复现网络结构前需要对各层的参数进行分析
-
第一层:
Input (3*32*32)
-->Conv(5*5)
-->output(32*32*32)
得,卷积层的参数为:nn.Conv2d(in_channels = 3, out_channels = 32, kernel_siza = 5, stride = 1, # 公式计算 padding = 2, # 公式计算 dilation=1) # 公式计算
-
第二层:
MaxPooling(2*2)
-->output(32*16*16)
得,池化层的参数为:nn.MaxPool(kernel_size=2, stride=2, # 公式计算 padding=0, # 公式计算 dilation=1) # 公式计算
-
第三层:
Conv(5*5)
-->output(32*16*16)
,卷积层参数为nn.Conv2d(in_channels = 32, out_channels = 32, kernel_siza = 5, stride = 1, # 公式计算 padding = 2, # 公式计算 dilation=1) # 公式计算
-
第四层:
MaxPooling(2*2)
-->output(32*8*8)
,池化层的参数为nn.MaxPool(kernel_size=2, stride=2, # 公式计算 padding=0, # 公式计算 dilation=1) # 公式计算
-
第五层:
Conv(5*5)
-->output(64*8*8)
,卷积层参数为nn.Conv2d(in_channels=32, out_channels=64, kernel_size=5, stride = 1, # 公式计算 padding = 2, # 公式计算 dilation=1) # 公式计算
-
第六层:
MaxPooling(2*2)
-->output(64*4*4)
,卷积层参数为nn.MaxPool(kernel_size=2, stride=2, # 公式计算 padding=0, # 公式计算 dilation=1) # 公式计算
-
第七层:
Flatten()
展开并线性变换为64结点-
nn.Flatten()
层主要用于将数据展开,对于一个(64, 4, 4)
维度的数据,就是以最后一个维度优先的原则,将整个多维矩阵展平,维度变为为:(64, 4, 4)
–>(1, 1024)
nn.Flatten()
-
Linear(1024, 64)
全连接层将1024个数据,映射为64个数据,数据维度变换位:(1, 1024)
-->(1, 64)
nn.Linear(in_features=1024, out_features=64)
-
-
第八层:全连接层
(1, 64)
-->(1, 10)
,对应的线性层参数为nn.Linear(in_features=64, out_features=10)
-
3. 构建完整的网络结构
-
创建一个基本网络架构
Model
,forward
函数中定义完整的数据处理流程class Model(nn.Module): def __init__(self): super(Model, self).__init__() self.conv1 = nn.Conv2d(in_channels=3, out_channels=32, kernel_size=5, stride=1, padding=2, dilation=1) self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1) self.conv2 = nn.Conv2d(in_channels=32, out_channels=32, kernel_size=5, stride=1, padding=2, dilation=1) self.pool2 = nn.MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1) self.conv3 = nn.Conv2d(in_channels=32, out_channels=64, kernel_size=5, stride=1, padding=2, dilation=1) self.pool3 = nn.MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1) self.flatten = nn.Flatten() self.linear1 = nn.Linear(in_features=1024, out_features=64) self.linear2 = nn.Linear(in_features=64, out_features=10) def forward(self, x): x = self.conv1(x) # 第一层卷积 x = self.pool1(x) # 第二层池化 x = self.conv2(x) # 第三层卷积 x = self.pool2(x) # 第四层池化 x = self.conv3(x) # 第五层卷积 x = self.pool3(x) # 第六层池化 x = self.flatten(x) # 第七层展开 x = self.linear1(x) # 第七层全连接 x = self.linear2(X) # 第八层全连接 return x
-
在应用到具体的数据处理之前,可以通过创建一个基本的数据样例,来判断网络的整体输出结构是否有问题
input = torch.ones(64, 3, 32, 32) model = Model() output = model(input) print(output.size()) # torch.Size([64, 10])
4. 使用Sequential简化代码
-
Sequential
与Compose
类功能相仿,都是将完整的数据处理序列进行集成,从而简化代码结构class Model(nn.Module): def __init__(self): super(Model, self).__init__() self.model = nn.Sequential( nn.Conv2d(3, 32, 5, 1, 2, 1), nn.MaxPool2d(2, 2, 0, 1), nn.Conv2d(32, 32, 5, 1, 2, 1), nn.MaxPool2d(2, 2, 0, 1), nn.Conv2d(32, 64, 5, 1, 2, 1), nn.MaxPool2d(2, 2, 0, 1), nn.Flatten(), nn.Linear(1024, 64), nn.Linear(64, 10) ) def forward(self, x): x = self.model(x) return x
Sequential()
函数将所有的层结构操作集成起来,配建成一个完整的数据处理序列,该函数能够将冗余的代码简化,代码结构更友好
5. 使用TensorBoard可视化网络结构图
-
TensorBoard
模块提供了网络结构图可视化模块add_graph
,能够细节化展示网络结构图with SummaryWriter("log") as writer: writer.add_graph(model = Model(), input_to_model=input)
model:
指定需要进行展示的Model类的实例input_to_model:
指明用于传入网络结构中进行处理的数据
-
使用命令
tensorboard --logdir=log
打开tensorboard
的控制台-
选择GRAPHS视图,可以看到基于
Model
类实例构建的网络结构简图 -
双击结点,并使用滚轮放大结构图,可以看到详细的参数,如图所示,x是一个
(64, 3, 32, 32)
的数据作为input
-
这里同样可以查看完整的网络结构示意图,每一条脉络上都清楚的标明了当前数据在进行网络数据处理的过程中,维度数据的变换
-
6. print
函数对网络的输出结果
-
对于上述手动搭建的网络结构,在不适用
Sequential
的情况下,直接输出Model
类的实例化print(Model()) >>> Model( (conv1): Conv2d(3, 32, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2)) (pool1): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) (conv2): Conv2d(32, 32, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2)) (pool2): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) (conv3): Conv2d(32, 64, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2)) (pool3): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) (flatten): Flatten(start_dim=1, end_dim=-1) (linear1): Linear(in_features=1024, out_features=64, bias=True) (linear2): Linear(in_features=64, out_features=10, bias=True) )
(xxx): layer():
输出结果中:
的前半部分(xxx)
是网络层在 Model 类中定义的变量名称, 后半部分layer()
是每一层对应的具体参数
-
对于一个使用
Sequential
简化的网络结构的输出结果如下print(Model()) >>> Model( (model): Sequential( (0): Conv2d(3, 32, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2)) (1): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) (2): Conv2d(32, 32, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2)) (3): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) (4): Conv2d(32, 64, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2)) (5): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) (6): Flatten(start_dim=1, end_dim=-1) (7): Linear(in_features=1024, out_features=64, bias=True) (8): Linear(in_features=64, out_features=10, bias=True) ) )
- 输出结果中表明了数据处理顺序,并给出了每一层的具体参数