GoogLeNet是一种深度卷积神经网络架构,于2014年由Google团队提出,是ILSVRC(ImageNet Large Scale Visual Recognition Challenge)比赛的冠军模型,其创新点主要集中在以下几个方面:
Inception模块: GoogLeNet引入了Inception模块,该模块使用不同大小的卷积核和池化层来捕获不同尺度的特征。Inception模块内部通过多个并行的卷积层和池化层来处理输入数据,然后将它们的输出进行拼接,从而增加了网络对不同尺度特征的感知能力。这种结构有助于提高网络的表达能力,同时减少了参数数量。
import torch.nn as nn
import torch
import torch.nn.functional as F
'''step1: 写一个包含卷积层和relu激活函数模块的类'''
class Conv_relu(nn.Module):
def __init__(self,in_channels,out_channels,**kwargs):
super(Conv_relu, self).__init__()
self.conv=nn.Conv2d(in_channels,out_channels,**kwargs)
self.relu=nn.ReLU(inplace=True)
def forward(self,x):
x=self.conv(x)
x=self.relu(x)
return x
'''step2: 构建Inception模块,包含4个分支
branch1:1×1卷积
branch2:1×1卷积降维-->3×3卷积
branch3:1×1卷积将为-->5×5卷积
branch4:3×3最大池化-->1×1降维
'''
class Inception(nn.Module):
def __init__(self,in_channels,out_channels1x1,reduce_channels3x3,out_channels3x3,
reduce_channels5x5,out_channels5x5,out_channels1x1_pool,):
super(Inception, self).__init__()
#branch1:1×1卷积
self.branch1=Conv_relu(in_channels,out_channels1x1,kernel_size=1)
#branch2:1×1卷积降维-->3×3卷积
self.branch2 =nn.Sequential(
Conv_relu(in_channels, reduce_channels3x3, kernel_size=1),
Conv_relu(reduce_channels3x3,out_channels3x3,kernel_size=3,padding=1)
)
#branch3:1×1卷积将为-->5×5卷积
self.branch3 =nn.Sequential(
Conv_relu(in_channels, reduce_channels5x5, kernel_size=1),
Conv_relu(reduce_channels5x5,out_channels5x5,kernel_size=5,padding=2)
)
#branch4:3×3最大池化-->1×1降维
self.branch4 =nn.Sequential(
nn.MaxPool2d(kernel_size=3,stride=1,padding=1),
Conv_relu(in_channels,out_channels1x1_pool,kernel_size=1)
)
def forward(self,x):
x1=self.branch1(x)
x2 = self.branch2(x)
x3 = self.branch3(x)
x4 = self.branch4(x)
x=torch.cat([x1,x2,x3,x4],dim=1)
return x
# return x1,x2,x3,x4,x
if __name__ == '__main__':
inc_=Inception(192, 64, 96, 128, 16, 32, 32)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
inc_.to(device)
input_tensor=torch.randn(1,192,64,64).to(device)
# out1,out2,out3,out4,out=inc_(input_tensor)
out = inc_(input_tensor)
# print('branch1特征图尺寸:', out1.size())
# print('branch2特征图尺寸:', out2.size())
# print('branch3特征图尺寸:', out3.size())
# print('branch4特征图尺寸:', out4.size())
print('拼接后的特征图尺寸:', out.size())
1x1卷积的使用: GoogLeNet在Inception模块中广泛使用了1x1卷积。1x1卷积可以用来进行特征的线性组合,从而降低特征维度,减少计算负担。这种技术被称为“瓶颈结构”,可以在不引入过多计算负担的情况下增加网络的深度和宽度。
Global Average Pooling(全局平均池化): 在传统的卷积神经网络中,通常使用全连接层来进行分类,这会导致大量的参数和计算量。GoogLeNet使用了全局平均池化来替代全连接层,通过对特征图的所有通道进行平均池化,生成一个特征向量,然后使用一个softmax分类器进行分类。这种做法减少了参数数量,防止过拟合,并降低了计算复杂性。
辅助分类器(Auxiliary Classifiers): GoogLeNet引入了两个辅助分类器,分别连接到中间层的不同位置。这些辅助分类器在训练过程中引入了额外的损失函数,帮助网络更快地进行训练。在测试阶段,这些辅助分类器不起作用,只有主分类器的输出被使用。这种结构有助于缓解梯度消失问题,促进梯度在网络中的传播。
# 辅助分类器
import torch.nn as nn
import torch
import torch.nn.functional as F
class Aux_classifier(nn.Module):
def __init__(self,in_channels,num_classes):
super(Aux_classifier, self).__init__()
self.avgpool=nn.AvgPool2d(kernel_size=5, stride=3)
self.conv=Conv_relu(in_channels,128)
self.fc1 = nn.Linear(2048, 1024)
self.fc2 = nn.Linear(1024, num_classes)
def forward(self,x):
x=self.avgpool(x)
x=self.conv(x)
x=torch.flatten(x,1)
x=F.dropout(x,0.5,training=self.training)
x=F.relu(self.fc1(x),inplace=True)
x=F.dropout(x,0.5,training=self.training)
x=self.fc2(x)
return x
总之,GoogLeNet通过引入Inception模块、1x1卷积、全局平均池化以及辅助分类器等创新点,成功地构建了一个更深、更宽的网络,具备强大的特征提取和分类能力,并在当时的图像分类竞赛中取得了显著的成绩。这些创新点也为后续深度神经网络的设计提供了重要的启示。