1×1卷积与GoogleNet

打印 上一主题 下一主题

主题 1763|帖子 1763|积分 5289

1×1卷积

卷积核的尺寸等于1的卷积核
1×1卷积有什么用

1. 通道混合与特性转换



  • 背景:在卷积神经网络中,输入数据通常有多个通道(比方RGB图像有3个通道,颠末卷积层后通道数可能会增加)。不同通道的特性图可能包罗了不同的语义信息。
  • 作用:1×1卷积可以对输入的特性图在通道维度上进行加权求和和线性组合,从而实现通道间的混合。它可以或许将不同通道的特性进行整合,生成新的特性表现。比方,假设输入特性图的通道数为C,颠末1×1卷积后,可以将其转换为C'个通道的特性图,C'可以大于、小于或等于C。这种转换可以改变特性的表达方式,使网络可以或许学习到更复杂的特性关系。

2. 减少参数数量和盘算量



  • 背景:在深度卷积网络中,尤其是当卷积核较大且通道数较多时,参数数量和盘算量会急剧增加。比方,一个3×3卷积核在处理C个输入通道和C'个输出通道的特性图时,参数数量为3×3×C×C'。
  • 作用:1×1卷积可以作为一种高效的替代方案。它只在通道维度上进行操作,不涉及空间维度的卷积,因此参数数量大大减少。比方,1×1卷积的参数数量仅为1×1×C×C'。通过使用1×1卷积,可以在不明显降低网络性能的环境下,减少模子的参数数量和盘算量,从而进步模子的练习和推理速度。

3. 构建Inception模块



  • 背景:Inception模块是一种经典的卷积神经网络结构,其核心思想是通过并行的卷积操作(不同大小的卷积核)来捕捉不同尺度的特性,但直接使用多种卷积核会导致参数数量和盘算量大幅增加。
  • 作用:1×1卷积在Inception模块中扮演了关键脚色。它被用作降维操作,将输入特性图的通道数减少后再进行大卷积核的卷积操作。比方,在一个Inception模块中,先通过1×1卷积将输入特性图的通道数从C减少到C'(C'<C),然后再分别使用3×3、5×5等卷积核进行卷积。这样,既可以或许减少盘算量,又可以或许保存不同尺度特性的捕捉能力。

4. 构建ResNet中的瓶颈结构



  • 背景:ResNet(残差网络)通过引入残差学习办理了深层网络练习中的梯度消失和梯度爆炸问题。在ResNet中,瓶颈结构是一种常用的模块,它通过减少特性图的通道数来降低盘算量。
  • 作用:1×1卷积在瓶颈结构中用于降维和升维。比方,在一个典型的瓶颈模块中,首先使用1×1卷积将输入特性图的通道数从C减少到C/4,然后使用3×3卷积进行特性提取,最后再使用1×1卷积将通道数恢复到C。这种结构大大减少了盘算量,同时保存了特性的表达能力。
5. 实现注意力机制



  • 背景:注意力机制是一种模拟人类视觉注意力的机制,它可以让模子更加关注输入数据中紧张的部分。
  • 作用:1×1卷积可以用于实现通道注意力机制。比方,在SENet(Squeeze-and-Excitation Networks)中,通过全局均匀池化将特性图的空间信息压缩,然后使用1×1卷积对通道进行加权,生成通道注意力权重。这些权重可以用来对输入特性图的通道进行加权求和,从而增强紧张通道的特性,抑制不紧张的通道特性。
6. 构建轻量级网络



  • 背景:在移动设备或资源受限的环境中,需要使用轻量级的卷积神经网络来满足及时性和低功耗的要求。
  • 作用:1×1卷积由于其参数少、盘算量小的特点,可以用于构建轻量级网络。比方,在MobileNet中,通过深度可分离卷积(Depthwise Separable Convolution)和1×1卷积的联合,大大减少了模子的参数数量和盘算量,同时保持了较好的性能。
GoogleNet

GoogLeNet(InceptionNet)取得了2014年ImageNet分类大赛的冠军,参数量远小于VGG系列网络,而精度和速度则逾越了VGG系列

基本单位Inception Module


基本单位Inception Module

使用1*1卷积进行通道调整的Inception Module

完整模子配置

GoogLeNet模子结构


练习细节

增加了不同深度的两个分支分类器辅助练习,使网络练习更加轻易。辅助丧失

复现GoogleNet网络
  1. # coding:utf8
  2. # Copyright 2023 longpeng2008. All Rights Reserved.
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # If you find any problem,please contact us
  5. #
  6. #     longpeng2008to2012@gmail.com
  7. #
  8. # or create issues
  9. # =============================================================================
  10. import torch
  11. import torch.nn as nn
  12. # 卷积模块
  13. class BasicConv(nn.Module):
  14.     def __init__(self, in_channels, out_channels, kernel_size, stride=(1, 1), padding=(0, 0)):
  15.         super(BasicConv, self).__init__()
  16.         self.conv = nn.Conv2d(in_channels=in_channels, out_channels=out_channels, kernel_size=kernel_size,
  17.                               stride=stride, padding=padding)
  18.         self.relu = nn.ReLU(inplace=True)
  19.     def forward(self, x):
  20.         x = self.conv(x)
  21.         x = self.relu(x)
  22.         return x
  23. # 额外的损失分支
  24. class SideBranch(nn.Module):
  25.     def __init__(self, in_channels, num_classes):
  26.         super(SideBranch, self).__init__()
  27.         self.avg_pool = nn.AvgPool2d(kernel_size=5, stride=3)
  28.         self.conv1x1 = BasicConv(in_channels=in_channels, out_channels=128, kernel_size=1)
  29.         self.fc_1 = nn.Linear(in_features=2048, out_features=1024)
  30.         self.relu = nn.ReLU(inplace=True)
  31.         self.fc_2 = nn.Linear(in_features=1024, out_features=num_classes)
  32.     def forward(self, x):
  33.         x = self.avg_pool(x)
  34.         x = self.conv1x1(x)
  35.         x = torch.flatten(x, 1)
  36.         x = self.fc_1(x)
  37.         x = self.relu(x)
  38.         x = torch.dropout(x, 0.7, train=True)
  39.         x = self.fc_2(x)
  40.         return x
  41. # Inception模块
  42. class InceptionBlock(nn.Module):
  43.     def __init__(self, in_channels, ch1x1, ch3x3reduce, ch3x3, ch5x5reduce, ch5x5, chpool):
  44.         super(InceptionBlock, self).__init__()
  45.         self.branch_1 = BasicConv(in_channels=in_channels, out_channels=ch1x1, kernel_size=1)
  46.         self.branch_2 = nn.Sequential(
  47.             BasicConv(in_channels=in_channels, out_channels=ch3x3reduce, kernel_size=1),
  48.             BasicConv(in_channels=ch3x3reduce, out_channels=ch3x3, kernel_size=3, padding=1)
  49.         )
  50.         self.branch_3 = nn.Sequential(
  51.             BasicConv(in_channels=in_channels, out_channels=ch5x5reduce, kernel_size=1),
  52.             BasicConv(in_channels=ch5x5reduce, out_channels=ch5x5, kernel_size=5, padding=2)
  53.         )
  54.         self.branch_4 = nn.Sequential(
  55.             nn.MaxPool2d(kernel_size=3, padding=1, stride=1, ceil_mode=True),
  56.             BasicConv(in_channels=in_channels, out_channels=chpool, kernel_size=1)
  57.         )
  58.     def forward(self, x):
  59.         x_1 = self.branch_1(x)
  60.         x_2 = self.branch_2(x)
  61.         x_3 = self.branch_3(x)
  62.         x_4 = self.branch_4(x)
  63.         x = torch.cat([x_1, x_2, x_3, x_4], dim=1)
  64.         return x
  65. # GoogLeNet/Inception模型
  66. class Inception_V1(nn.Module):
  67.     def __init__(self, num_classes):
  68.         super(Inception_V1, self).__init__()
  69.         self.BasicConv_1 = BasicConv(in_channels=3, out_channels=64, kernel_size=7, stride=2, padding=3)
  70.         self.max_pool_1 = nn.MaxPool2d(kernel_size=3, stride=2, ceil_mode=True)  # 把不足square_size的边保留下来,单独计算
  71.         self.lrn_1 = nn.LocalResponseNorm(2)
  72.         self.conv_1x1 = BasicConv(in_channels=64, out_channels=64, kernel_size=1)
  73.         self.conv_3x3 = BasicConv(in_channels=64, out_channels=192, kernel_size=3, padding=1)
  74.         self.lrn_2 = nn.LocalResponseNorm(2)
  75.         self.max_pool_2 = nn.MaxPool2d(kernel_size=3, stride=2, ceil_mode=True)
  76.         #   in_channels,ch1x1, ch3x3reduce,ch3x3,ch5x5reduce,ch5x5,chpool
  77.         self.InceptionBlock_3a = InceptionBlock(192, 64, 96, 128, 16, 32, 32)
  78.         self.InceptionBlock_3b = InceptionBlock(256, 128, 128, 192, 32, 96, 64)
  79.         self.max_pool_3 = nn.MaxPool2d(kernel_size=3, stride=2, ceil_mode=True)
  80.         self.InceptionBlock_4a = InceptionBlock(480, 192, 96, 208, 16, 48, 64)
  81.         self.SideBranch_1 = SideBranch(512, num_classes)
  82.         self.InceptionBlock_4b = InceptionBlock(512, 160, 112, 224, 24, 64, 64)
  83.         self.InceptionBlock_4c = InceptionBlock(512, 128, 128, 256, 24, 64, 64)
  84.         self.InceptionBlock_4d = InceptionBlock(512, 112, 144, 288, 32, 64, 64)
  85.         self.SideBranch_2 = SideBranch(528, num_classes)
  86.         self.InceptionBlock_4e = InceptionBlock(528, 256, 160, 320, 32, 128, 128)
  87.         self.max_pool_4 = nn.MaxPool2d(kernel_size=3, stride=2, ceil_mode=True)
  88.         self.InceptionBlock_5a = InceptionBlock(832, 256, 160, 320, 32, 128, 128)
  89.         self.InceptionBlock_5b = InceptionBlock(832, 384, 192, 384, 48, 128, 128)
  90.         self.avg_pool = nn.AdaptiveAvgPool2d(1)
  91.         self.flatten = nn.Flatten()
  92.         self.fc = nn.Linear(in_features=1024, out_features=num_classes)
  93.     def forward(self, x):
  94.         x = self.BasicConv_1(x)
  95.         x = self.max_pool_1(x)
  96.         x = self.lrn_1(x)
  97.         x = self.conv_1x1(x)
  98.         x = self.conv_3x3(x)
  99.         x = self.lrn_1(x)
  100.         x = self.max_pool_2(x)
  101.         x = self.InceptionBlock_3a(x)
  102.         x = self.InceptionBlock_3b(x)
  103.         x = self.max_pool_3(x)
  104.         x = self.InceptionBlock_4a(x)
  105.         x_1 = self.SideBranch_1(x)
  106.         x = self.InceptionBlock_4b(x)
  107.         x = self.InceptionBlock_4c(x)
  108.         x = self.InceptionBlock_4d(x)
  109.         x_2 = self.SideBranch_2(x)
  110.         x = self.InceptionBlock_4e(x)
  111.         x = self.max_pool_4(x)
  112.         x = self.InceptionBlock_5a(x)
  113.         x = self.InceptionBlock_5b(x)
  114.         x = self.avg_pool(x)
  115.         x = self.flatten(x)
  116.         x = torch.dropout(x, 0.4, train=True)
  117.         x = self.fc(x)
  118.         x_1 = torch.softmax(x_1, dim=1)
  119.         x_2 = torch.softmax(x_2, dim=1)
  120.         x_3 = torch.softmax(x, dim=1)
  121.         # output = x_3 + (x_1 + x_2) * 0.3
  122.         return x_3, x_2, x_1
  123. if __name__ == '__main__':
  124.     # 创建模型,给定输入,前向传播,存储模型
  125.     input = torch.randn([1, 3, 224, 224])
  126.     model = Inception_V1(num_classes=1000)
  127.     torch.save(model, 'googlenet.pth')
  128.     x_3, x_2, x_1 = model(input)
  129.     # 观察输出,只需要观察shape是我们想要的即可
  130.     print(x_1.shape)
  131.     print(x_2.shape)
  132.     print(x_3.shape)
  133.     torch.onnx.export(model, input, 'googlenet.onnx', opset_version=10)
复制代码


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

熊熊出没

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表