上次课我们讲解了对于CIFAR10数据读取部分代码的编写,本节讲解如何编写经典的LeNet5神经网络。
首先创建python文件,命名LeNet5。
开始写代码
先引入相关工具包、完成类的初始化
代码语言:javascript复制import torch
from torch import nn
class LeNet5(nn.Module):
# 将所有的类都继承给nn.module
def __init__(self):
super(LeNet5, self).__init__()
# 调用类的初始化
self.conv_unit = nn.Sequential(
# 把网络结构放在Sequential中十分方便
)
下面把网络结构放在Sequential中
注意因为CIFAR10均为彩色图片,即为RGB三个通道
这里的输入部分的size为x: [batch, 3, 32, 32]
按照其提示书写
这里的input_channel为3,看图片发现out_channel为6
而kernel_size并没有标明,这里先假设为5。stride也没有标明,先假设为1。同样padding假设为0。
第一层为
代码语言:javascript复制nn.Conv2d(in_channels=3, out_channels=6, kernel_size=5, stride=1, padding=0)
# 第一层完成了[b, 3, 32, 32] => [b, 6, size_h, size_w]
# 这里由于使用了stride,暂时不确定size
下一层为pooling层
代码语言:javascript复制nn.AvgPool2d(kernel_size=2, stride=2, padding=0),
# 由于没有相关参数资料,部分只能靠猜测
这种pooling后,长宽各减半
第二个卷积层和pooling层
代码语言:javascript复制nn.Conv2d(in_channels=6, out_channels=16, kernel_size=5, stride=1, padding=0)
# 图中显示原来的6个channel变为16个channel
nn.AvgPool2d(kernel_size=2, stride=2, padding=0)
# 假设第二层的pooling部分与第一层的相同
由原图发现下一层为16个channel通道的全连接输出,因此这里进行打平操作,并接入全连接层
代码语言:javascript复制self.fc_unit = nn.Sequential(
# fc即指代full connect全连接
nn.Linear(2, 120),
# 这里只知道由一个维度变到了120,再由120变到64,
# 由于不清楚是什么维度变到了120,这里暂时先写2
nn.ReLU(),
nn.Linear(120, 64),
nn.ReLU(),
nn.Linear(84, 10),
)
为能知道具体的维度信息,这里可以先构建一个随机的假数据,代入其中先行进行计算。
代码语言:javascript复制tmp = torch.randn(2, 3, 32, 32)
out = self.conv_unit(tmp)
# 将假数据带入到out中
print('conv:', out.shape)
再加入相关代码,使之能单独运行
代码语言:javascript复制def main():
net = LeNet5()
if __name__ == '__main__':
main()
加入后整体代码为
代码语言:javascript复制import torch
from torch import nn
class LeNet5(nn.Module):
# 将所有的类都继承给nn.module
def __init__(self):
super(LeNet5, self).__init__()
# 调用类的初始化
self.conv_unit = nn.Sequential(
# 把网络结构放在Sequential中十分方便
nn.Conv2d(in_channels=3, out_channels=6, kernel_size=5, stride=1, padding=0),
# 第一层完成了[b, 3, 32, 32] => [b, 6, size_h, size_w]
# 这里由于使用了stride,暂时不确定size
nn.AvgPool2d(kernel_size=2, stride=2, padding=0),
# 由于没有相关参数资料,部分只能靠猜测
nn.Conv2d(in_channels=6, out_channels=16, kernel_size=5, stride=1, padding=0),
# 图中显示原来的6个channel变为16个channel
nn.AvgPool2d(kernel_size=2, stride=2, padding=0),
# 假设第二层的pooling部分与第一层的相同
)
self.fc_unit = nn.Sequential(
# fc即指代full connect全连接
nn.Linear(2, 120),
# 这里只知道由一个维度变到了120,再由120变到84,
# 由于不清楚是什么维度变到了120,这里暂时先写2
nn.ReLU(),
nn.Linear(120, 84),
nn.ReLU(),
nn.Linear(84, 10),
)
tmp = torch.randn(2, 3, 32, 32)
out = self.conv_unit(tmp)
# 将假数据带入到out中
print('conv:', out.shape)
def main():
net = LeNet5()
if __name__ == '__main__':
main()
开始运行
输出结果为
代码语言:javascript复制conv: torch.Size([2, 16, 5, 5])
由此得知打平操作后的数据变为16*5*5。
对原代码进行更改
代码语言:javascript复制nn.Linear(16*5*5, 120),