一、Sequential 是什么
Sequential 主要出现在 Keras 库中,这是一个用于构建和训练深度学习模型的高级 API。Sequential 类允许你按顺序构建神经网络模型,其中每一层都按照给定的顺序逐层堆叠。这种模型适用于大多数线性堆叠的神经网络结构。Sequential是按顺序构建网络:所有的层都按添加的顺序连接,因此可以很容易地构建具有线性堆叠结构的网络模型。
二、需要搭建的结构
上图是一个CIFAR 10 model结构
对Input经过一系列的卷积核(kernel),然后经过最大池操作(Max-pooling),对得到的结果进行展平,得到Outputs
三、搭建CIFAR 10 model结构
可以看到Conv2d 二维卷积层所需要的参数:
由CIFAR 10 model结构图可以得知Output需要32,从而通过下面的式子计算出padding和stride的参数,这里默认dilations空洞卷积参数为1,若把stride设置成1,那么求得padding的值为2,从而得到上面的参数。
函数解释:
Flatten是对数据进行展平
Linear 层可以将前一层的输出(可以是特征图、一维特征向量等)进行线性组合,以生成新的特征表示。这有助于网络学习输入数据中的复杂模式。Linear需要有输入输出,输入是6444,输出是64
from torch import nn
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear
class Sen(nn.Module):
def __init__(self):
super(Sen,self).__init__()
#根据式子把所需要的参数的值给求出来
self.conv1 = Conv2d(3, 32, 5, 1, 2)
#根据结构图知道最大池化的参数是2
self.maxpool1 = MaxPool2d(2)
self.conv2 = Conv2d(32, 32, 5, padding=2)
self.maxpool2 = MaxPool2d(2)
self.conv3 = Conv2d(32, 64, 5, padding=2)
self.maxpool3 = MaxPool2d(2)
#经过Flatten进行数据的展平
self.flatten = Flatten()
#Linear 层可以将前一层的输出(可以是特征图、一维特征向量等)进行线性组合,以生成新的特征表示。这有助于网络学习输入数据中的复杂模式。
#1024是64*4*4
self.linear1 = Linear(1024, 64)
self.linear2 = Linear(64, 10)
def forward(self, x):
x = self.conv1(x)
x = self.maxpool1(x)
x = self.conv2(x)
x = self.maxpool2(x)
x = self.conv3(x)
x = self.maxpool3(x)
x = self.flatten(x)
x = self.linear1(x)
x = self.linear2(x)
return x
sen = Sen()
print(sen)
以上代码是直接根据CIFAR 10 model结构图一步一步的写的。
运行结果:
四、检查网络的正确性
如果把上面的代码网络写错,运行也不会报错,这样子我们就没法检验网络搭建是否出现错误。
例如我们把self.linear1 = Linear(1024, 64)
改写成`self.linear1 = Linear(10240, 64)进行运行
import torch
from torch import nn
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear
class Sen(nn.Module):
def __init__(self):
super(Sen,self).__init__()
#根据式子把所需要的参数的值给求出来
self.conv1 = Conv2d(3, 32, 5, 1, 2)
#根据结构图知道最大池化的参数是2
self.maxpool1 = MaxPool2d(2)
self.conv2 = Conv2d(32, 32, 5, padding=2)
self.maxpool2 = MaxPool2d(2)
self.conv3 = Conv2d(32, 64, 5, padding=2)
self.maxpool3 = MaxPool2d(2)
#经过Flatten进行数据的展平
self.flatten = Flatten()
#Linear 层可以将前一层的输出(可以是特征图、一维特征向量等)进行线性组合,以生成新的特征表示。这有助于网络学习输入数据中的复杂模式。
#1024是64*4*4
self.linear1 = Linear(10240, 64)
self.linear2 = Linear(64, 10)
def forward(self, x):
x = self.conv1(x)
x = self.maxpool1(x)
x = self.conv2(x)
x = self.maxpool2(x)
x = self.conv3(x)
x = self.maxpool3(x)
x = self.flatten(x)
x = self.linear1(x)
x = self.linear2(x)
return x
sen = Sen()
print(sen)
运行结果:
可以看到也不会发生报错,这样子我们无法识别搭建的网络是否出现错误,这时候我们可以通过一个假想输入来进行判断。
通过一个假想的输入:
input = torch.ones((64, 3, 32, 32))
output = sen(input)
print(output.shape)
来进行代码正确性的判断:
import torch
from torch import nn
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear
class Sen(nn.Module):
def __init__(self):
super(Sen,self).__init__()
#根据式子把所需要的参数的值给求出来
self.conv1 = Conv2d(3, 32, 5, 1, 2)
#根据结构图知道最大池化的参数是2
self.maxpool1 = MaxPool2d(2)
self.conv2 = Conv2d(32, 32, 5, padding=2)
self.maxpool2 = MaxPool2d(2)
self.conv3 = Conv2d(32, 64, 5, padding=2)
self.maxpool3 = MaxPool2d(2)
#经过Flatten进行数据的展平
self.flatten = Flatten()
#Linear 层可以将前一层的输出(可以是特征图、一维特征向量等)进行线性组合,以生成新的特征表示。这有助于网络学习输入数据中的复杂模式。
#1024是64*4*4
self.linear1 = Linear(1024, 64)
self.linear2 = Linear(64, 10)
def forward(self, x):
x = self.conv1(x)
x = self.maxpool1(x)
x = self.conv2(x)
x = self.maxpool2(x)
x = self.conv3(x)
x = self.maxpool3(x)
x = self.flatten(x)
x = self.linear1(x)
x = self.linear2(x)
return x
sen = Sen()
print(sen)
input = torch.ones((64, 3, 32, 32))
output = sen(input)
print(output.shape)
网络正确输出:
当我们把self.linear1 = Linear(1024, 64)
改写成self.linear1 = Linear(10240, 64)
,表示代码错误的情况。
import torch
from torch import nn
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear
class Sen(nn.Module):
def __init__(self):
super(Sen,self).__init__()
#根据式子把所需要的参数的值给求出来
self.conv1 = Conv2d(3, 32, 5, 1, 2)
#根据结构图知道最大池化的参数是2
self.maxpool1 = MaxPool2d(2)
self.conv2 = Conv2d(32, 32, 5, padding=2)
self.maxpool2 = MaxPool2d(2)
self.conv3 = Conv2d(32, 64, 5, padding=2)
self.maxpool3 = MaxPool2d(2)
#经过Flatten进行数据的展平
self.flatten = Flatten()
#Linear 层可以将前一层的输出(可以是特征图、一维特征向量等)进行线性组合,以生成新的特征表示。这有助于网络学习输入数据中的复杂模式。
#1024是64*4*4
self.linear1 = Linear(10240, 64)
self.linear2 = Linear(64, 10)
def forward(self, x):
x = self.conv1(x)
x = self.maxpool1(x)
x = self.conv2(x)
x = self.maxpool2(x)
x = self.conv3(x)
x = self.maxpool3(x)
x = self.flatten(x)
x = self.linear1(x)
x = self.linear2(x)
return x
sen = Sen()
print(sen)
input = torch.ones((64, 3, 32, 32))
output = sen(input)
print(output.shape)
运行结果:
可以看到报错,说明代码出现了问题。
五、运用Sequential进行代码编写
Sequential其实就相当于汉堡包,把代码都夹在一起,跟compose有点像。
使用了Sequential,看看我们的代码会不会变得更加容易。
import torch
from torch import nn
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequential
class Sen(nn.Module):
def __init__(self):
super(Sen,self).__init__()
self.model1 = Sequential(
Conv2d(3, 32, 5, 1, 2),
MaxPool2d(2),
Conv2d(32, 32, 5, padding=2),
MaxPool2d(2),
Conv2d(32, 64, 5, padding=2),
MaxPool2d(2),
Flatten(),
Linear(1024, 64),
Linear(64, 10)
)
def forward(self, x):
x = self.model1(x)
return x
sen = Sen()
print(sen)
input = torch.ones((64, 3, 32, 32))
output = sen(input)
print(output.shape)
运行结果:
可以看出运行结果跟上面繁杂写法是一样的。
同样,我们可以进行可视化进行观察
import torch
from torch import nn
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequential
from torch.utils.tensorboard import SummaryWriter
class Sen(nn.Module):
def __init__(self):
super(Sen,self).__init__()
self.model1 = Sequential(
Conv2d(3, 32, 5, 1, 2),
MaxPool2d(2),
Conv2d(32, 32, 5, padding=2),
MaxPool2d(2),
Conv2d(32, 64, 5, padding=2),
MaxPool2d(2),
Flatten(),
Linear(1024, 64),
Linear(64, 10)
)
def forward(self, x):
x = self.model1(x)
return x
sen = Sen()
print(sen)
input = torch.ones((64, 3, 32, 32))
output = sen(input)
print(output.shape)
writer = SummaryWriter("./logs_seq")
writer.add_graph(sen, input)
writer.close()
运行结果: