CIFAR10数据集实战-LeNet5神经网络(上)

2019-12-19 11:01:25 浏览数 (1)

上次课我们讲解了对于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),

0 人点赞