目标检测入坑指南1:LeNet神经网络

学了蛮久的目标检测了,但是有好多细节总是忘或者模棱两可,感觉有必要写博客记录一下学习笔记和一些心得,既可以加深印象又可以方便他人。博客内容集成自各大学习资源,所以图片也就不加水印了,需要自取。本专栏会详细记录本人在研究目标检测过程中的所学所感,主要包括:1.目标检测算法解读,如R-CNN系列、YOLO系列;2.论文阅读笔记;3.其它目标检测相关的概念和技巧,如attention机制的应用。由于水平有限,不少地方可能会有不准确甚至错误,也希望大家多多包涵并指正一下!


在这里插入图片描述

一、引言

目标检测整体的框架是由backbone、neck和head组成的,所以在学习具体的目标检测算法之前,有必要了解一下常见的卷积神经网络结构,这有利于后面学习目标检测算法的backbone部分。首先就是LeNet,这是最早的卷积神经网络之一,虽然结构比较简单,但是刚好适合入门,为后续学习打下基础。

LeNet是卷积神经网络的奠基人Yann LeCun在1998年提出的,用于解决手写数字识别任务。如今各大深度学习框架中使用的LeNet都是经过简化改进过得LeNet-5N,5表示网络有5个卷积层/下采样层(没算输入输出和全连接层)。和原始的LeNet有所不同,激活函数已经由原来的tanh改为现在常用的ReLU(ReLU是在后面要讲的AlexNet中被首先使用)。

二、整体结构

在这里插入图片描述
和卷积层(convolutions)+下采样层(subsampling,也可以叫池化层)+ReLU层的套路有所区别,LeNet的连接方式是卷积层+ReLU层+下采样层,即:

卷积层C1—>ReLU—>下采样层S2—>卷积层C3—>ReLU—>下采样层S4—>卷积层C5—>全连接层F6

也就是把下采样层和ReLU的顺序换了一下,但是卷积层后面紧跟下采样层的模式是没变的。

在这个网络中,中间的C1~C5是特征提取部分,其中卷积层用来识别图像里的特征,比如线条和物体的局部特征,下采样层用来降低卷积层对位置的敏感性。卷积层的输出shape为(batch_size, channels, height, width),因此当卷积层的输出传入全连接层时,会对每个特征图(feature map)做拉伸(flatten)处理,把全连接层的输入形状变为二维,其中第一个维度是batch_size,第二维是每个样本拉伸后的向量表示。

三、逐层解析

1. 卷积层C1:6@28×28

C1层采用卷积层对输入的图像进行特征提取,用6个5×5的卷积核生成6个特征图。其步长(stride)为1且没有使用扩充值(padding),因此卷积后的特征图尺寸为(32-5+1)×(32-5+1)=28×28。一个卷积核拥有的可训练参数个数为5×5+1=26,其中1为偏置参数(bias),所以整个C1层的可训练参数个数为(5×5+1)×6=156。该层的连接数为(5×5+1)×6×(32-5+1)×(32-5+1)=122304。

2. 下采样层S2:6@14×14

下采样层主要对特征进行降维处理,效果与池化相同。S2层使用2×2的滤波器池化C1层的特征图,因此会生成6个尺寸为14×14的特征图。在计算时,首先将滤波器里的4个值相加,然后乘以可训练参数w,加上偏置参数b,最后通过sigmoid函数形成新的值。由于每个特征图都共享相同的w和b这两个参数,因此S2层的可训练参数个数为2×6=12。该层的连接数为(2×2+1)×14×14×6=5880。

3. 卷积层C3:16@10×10

C3层有16个大小为5×5的卷积核,步长为1且没有使用扩充值,因此卷积后的特征图尺寸为(14-5+1)×(14-5+1)=10×10。值得注意的是,S2层和C3层的卷积核并不是全连接的,而是部分连接的:

在这里插入图片描述

如图所示,Yann LeCun给出了他所使用的一套连接组合,行代表C3层中的卷积核,列代表S2层中的特征图。第1列表示C3层中的0号卷积核与S2层中的0号、1号、2号特征图相连。用3个卷积核分别与S2层中的0号、1号、2号特征图进行卷积操作,然后将卷积结果相加,加上一个偏置参数,最后通过sigmoid函数得出卷积后对应的特征图。在上图中,3个特征图一组的有6个,4个特征图一组的有9个,6个特征一族的有1个,因此C3层的参数个数为(5×5×3+1)×6+(5×5×4+1)×9+(5×5×6+1)×1=1516。Yann LeCun希望通过不同的卷积核与特征图的组合,迫使C3层生成的特征图有所区别。该层的连接数为(14-5+1)×(14-5+1)×1516=151600。

4. 下采样层S4:16@5×5

S4与S2层类似,滤波器也是2×2的,所以S4层输出的特征图尺寸为5×5。该层的参数个数为2×16=32,连接数为(2×2+1)×5×5×16=2000。

5. 卷积层C5:120

C5层有120个5×5的卷积核,将产生120个1×1的特征图,与S4层是全连接的。需要注意的是,由于S4层的大小为5×5,而该层的卷积核大小也是5×5,所以特征图尺寸就是(5-5+1)×(5-5+1)=1×1,看起来就和全连接层的效果一样,但这只是巧合,如果改变输入图像的尺寸,该层就不是全连接的了。C5层的参数个数要参照C3层的计算方式,并且此时是没有组合的,所以是(5×5×16+1)×120=48120。由于得到的特征图大小恰好为1×1,因此连接数为(5×5×16+1)×120×1×1=48120。

6. 全连接层F6:84

F6层有84个单元,单元的个数和输出层的设计有关。每一个单元都计算输入向量与权值参数的点积并加上偏置参数,最后传给sigmoid函数得出结果。在这里,将输出作为输出层的径向基函数(RBF)的初始参数,用来识别完整的ASCII字符集。C5层有120个单元,F6层有84个单元,每个单元都将容纳120个单元的计算结果,因此F6层的参数个数为(120+1)×84=10164。由于是全连接,所以连接数与参数数量一样,也是10164。

7. OUTPUT输出层:10

OUTPUT层也是全连接层,共有10个单元,代表数字0~9。利用RBF,将F6层84个单元的输出作为单元i(i是0到9)的输入,计算欧氏距离,距离越近结果就越小,表明识别的样本越符合该单元表示的字符。由于是全连接,所以参数个数连接数都是84×10=840。

四、实例演示

上述描述都是基于32×32的输入图像,那如果是28×28的输入图像该怎么办?由于全连接层的存在,输入图像的尺寸是限制为固定值的,因此如果要处理28×28的输入图像,需要将原始图像resize为32×32,或者改变全连接层(在后面的博客中会详细讲解会什么会出现输入尺寸限定,以及如何解决)。先放代码:

from torch import nn

class LeNet(nn.Module):
    def __init__(self, dim, num_classes):
        super().__init__()
        self.conv1 = nn.Sequential(
            nn.Conv2d(in_channels=dim, out_channels=20, kernel_size=5, stride=1, padding=2),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2)
        )
        self.conv2 = nn.Sequential(
            nn.Conv2d(in_channels=20, out_channels=50, kernel_size=5, stride=1, padding=2),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2)
        )
        self.fc = nn.Sequential(
            nn.Linear(2450, 500),
            nn.ReLU(),
            nn.Linear(500, num_classes)
        )

    def forward(self, x):
        x = self.conv1(x)
        x = self.conv2(x)
        x = x.view(x.size(0), -1)
        output = self.fc(x)
        return output

这里假定输入的是单通道灰度图。对于输入的(1, 28, 28)的图像:

  1. 经过第一个卷积层,这一层有20个5×5的卷积核,滑动步长为1,并且设置padding=2,得到的特征图尺寸为(20, 28, 28)。
  2. 经过第一个池化层,卷积核尺寸为2×2,滑动步长为2,经过最大池化操作后图像尺寸会减半,得到的特征图尺寸为(20, 14, 14)。
  3. 经过第二个卷积层,这一层有50个5×5的卷积核,滑动步长和填充值依然设置为1和2,,得到的特征图尺寸为(50, 14, 14)。
  4. 经过第二个池化层,卷积核尺寸和滑动步长与第一个池化层保持一致,因此图像尺寸再度减半,得到的特征图尺寸为(50, 7, 7)。
  5. 经过第一个全连接层,将输入维度50×7×7=2450降到500,也就是输出的神经元数目为500。
  6. 经过第二个全连接层,将输入维度降从500降到10,得到10维的特征向量,用于10个数字的分类训练,送入softmax分类就可以得到分类结果的概率。

在上述代码中,将原本的卷积层C5更改为全连接层,可以达到同等的效果。可以看到,如果想要处理不同尺寸的图片,就要通过逐层计算,得到全连接层前一层所输出的特征图尺寸,这样才能知道全连接层的输入应该更改为多少,还是很麻烦的。所以绝大多数处理方式都是将输入图片直接resize或者crop成固定的尺寸后再输入进网络中。

猜你喜欢

转载自blog.csdn.net/qq_43631268/article/details/121871756