图像分类是计算机视觉中最基础的任务,学者对于分类任务的研究进程,基本上等价于深度学习模型的发展史。GoogLeNet是2014年ImageNet比赛的冠军模型,由谷歌工程师设计的网络结构,它在命名上致敬最早的卷积神经网路LeNet。主要特点:不仅有纵向的“深度”,还具有横向的“宽度”。
图像分类,顾名思义,分析图像是哪一种类别。举个例子:以下图片你可以一眼看出来,是猫是狗?但计算机做不到这点,卷积运算就像一把钥匙打开了图像处理的大门,而深度学习的发展算是将其发扬光大。
有人提问:如果一只猫和一只狗在一张图片里,那该如何判定呢?这就不是一个简单的图像分类任务,而是更复杂的目标检测任务、图像分割任务、语义分割任务。以后慢慢道来~
数据集介绍
图像分类网络结构是卷积层、池化层和全连接层的线性组合。这里借用LeNet网络模型对各层进行说明。
(1)卷积层
(2)池化层
(3)全连接层
请移步上一遍博客全连接神经网络详解,全连接层的主要功能就是一个分类器,通常使用CrossEntropyLoss。
以下两张狗狗的照片,你可以区分它们的品种吗?若要提高网络模型的分类精度,最简单的两条途径:增大数据样本和扩大网络模型。GoogLeNet创新性工作便是提出了Inception模块,它允许增加网络的深度和宽度,同时保证调用的计算资源不变。
# GoogLeNet模型代码
import numpy as np
import paddle
from paddle.nn import Conv2D, MaxPool2D, AdaptiveAvgPool2D, Linear
## 组网
import paddle.nn.functional as F
# 定义Inception块
class Inception(paddle.nn.Layer):
def __init__(self, c0, c1, c2, c3, c4, **kwargs):
'''
Inception模块的实现代码,
c1,图(b)中第一条支路1x1卷积的输出通道数,数据类型是整数
c2,图(b)中第二条支路卷积的输出通道数,数据类型是tuple或list,
其中c2[0]是1x1卷积的输出通道数,c2[1]是3x3
c3,图(b)中第三条支路卷积的输出通道数,数据类型是tuple或list,
其中c3[0]是1x1卷积的输出通道数,c3[1]是3x3
c4,图(b)中第一条支路1x1卷积的输出通道数,数据类型是整数
'''
super(Inception, self).__init__()
# 依次创建Inception块每条支路上使用到的操作
self.p1_1 = Conv2D(in_channels=c0,out_channels=c1, kernel_size=1)
self.p2_1 = Conv2D(in_channels=c0,out_channels=c2[0], kernel_size=1)
self.p2_2 = Conv2D(in_channels=c2[0],out_channels=c2[1], kernel_size=3, padding=1)
self.p3_1 = Conv2D(in_channels=c0,out_channels=c3[0], kernel_size=1)
self.p3_2 = Conv2D(in_channels=c3[0],out_channels=c3[1], kernel_size=5, padding=2)
self.p4_1 = MaxPool2D(kernel_size=3, stride=1, padding=1)
self.p4_2 = Conv2D(in_channels=c0,out_channels=c4, kernel_size=1)
def forward(self, x):
# 支路1只包含一个1x1卷积
p1 = F.relu(self.p1_1(x))
# 支路2包含 1x1卷积 + 3x3卷积
p2 = F.relu(self.p2_2(F.relu(self.p2_1(x))))
# 支路3包含 1x1卷积 + 5x5卷积
p3 = F.relu(self.p3_2(F.relu(self.p3_1(x))))
# 支路4包含 最大池化和1x1卷积
p4 = F.relu(self.p4_2(self.p4_1(x)))
# 将每个支路的输出特征图拼接在一起作为最终的输出结果
return paddle.concat([p1, p2, p3, p4], axis=1)
Inception模块的提出,给深度学习重新拓展了一个维度,利用密集模块构造最优稀疏结构,是改进计算机神经网络的可行方法,相比较浅和较宽的网络,在计算需求增加的情况下获得显著的质量增益。需要注意的是,论文中构造的GoogLeNet一共有22层,而2015年提出的Resnet网络结构精度更高,网络层数达到101层,并且缓解了梯度消失和梯度爆炸的问题。所以,在选择backbone骨干的时候,普遍采用Resnet预训练的参数。