• 【网络结构】VGG


    概述

    VGG的一个核心思想就是使用多个较小的卷积代替较大的卷积并且能够保证感受野相同(如2个连续的3×3卷积核能够替代一个5×5卷积核,三个连续的3×3能够代替一个7×7卷积核)。
    这样的操作可以取得一个比较好结果的原因如下:
    1、相同感受野的情况下,多个小卷积的叠加,加深了网络,当然核心是引入了更多的非线性,模型的表征能力增强。
    2、参数更少。
    为什么2个连续的3×3卷积核与一个5×5卷积核感受野相同?

    5x5卷积,步长取1,padding取0,尺寸变化: ( x − 5 ) / 1 + 1 = x − 4 (x-5)/1+1=x-4 (x5)/1+1=x4
    2个3x3卷积,步长取1,padding取0,尺寸变化: ( x − 3 ) / 1 + 1 = x − 2 , ( x − 2 − 3 ) / 1 + 1 = x − 4 (x-3)/1+1=x-2,(x-2-3)/1+1=x-4 (x3)/1+1=x2,(x23)/1+1=x4
    在这里插入图片描述

    为什么参数更少?
    一个5x5的卷积的参数是 5 ∗ 5 ∗ C 5*5*C 55C,而两个3x3卷积的参数是 2 ∗ 3 ∗ 3 ∗ C 2*3*3*C 233C

    网络结构

    在这里插入图片描述
    最常用的就是VGG16,也就是上图的D,下图是VGG16直观一点的结构图。
    在这里插入图片描述

    实现

    import paddle
    import paddle.nn as nn
    
    paddle.set_device("cpu")
    class VGG(nn.Layer):
        # arch表述每一个stage的卷积个数
        def __init__(self, arch,num_classes=1000):
            super().__init__()
            self.in_channels=3
            self.conv3_64=self.make_layer(64,arch[0])
            self.conv3_128=self.make_layer(128,arch[1])
            self.conv3_256=self.make_layer(256,arch[2])
            self.conv3_512a=self.make_layer(512,arch[3])
            self.conv3_512b=self.make_layer(512,arch[4])
            
            self.pool=nn.MaxPool2D(2)
            
            self.fc1=nn.Linear(512*7*7, 4096)
            self.bn1=nn.BatchNorm1D(4096)
            self.fc2=nn.Linear(4096, 4096)
            self.bn2=nn.BatchNorm1D(4096)
            self.fc3=nn.Linear(4096, num_classes)
            
        def make_layer(self,channels,nums):
            layers=[]
            for i in range(nums):
                layers.append(nn.Conv2D(self.in_channels,channels,3,1,1))
                layers.append(nn.BatchNorm2D(channels))
                layers.append(nn.ReLU())
                self.in_channels=channels
            return nn.Sequential(*layers)
           
        def forward(self,x):
            # x:[n,3,224,224]
            print(x.shape)
            x=self.conv3_64(x) # x:[n,3,224,224]->[n,64,224,224]
            x=self.conv3_128(self.pool(x)) # x:[n,64,224,224]->[n,128,112,112]
            x=self.conv3_256(self.pool(x)) # x:[n,128,112,112]->[n,256,56,56]
            x=self.conv3_512a(self.pool(x)) # x:[n,256,56,56]->[n,512,28,28]
            x=self.conv3_512b(self.pool(x)) # x:[n,512,28,28]->[n,512,14,14]
            x=self.pool(x).flatten(1) # x:[n,512,14,14]->[n,512,7,7]->[n,512*7*7]
            
            x=self.fc1(x) # [n,512*7*7]->[n,4096]
            x=self.bn1(x) 
            x=self.fc2(x) # [n,4096]->[n,4096]
            x=self.bn2(x)
            x=self.fc3(x) # [n,4096]->[n,1000]
            return x
    
    def VGG_11():
        return VGG([1, 1, 2, 2, 2])
    
    def VGG_13():
        return VGG([1, 1, 2, 2, 2])
    
    def VGG_16():
        return VGG([2, 2, 3, 3, 3])
    
    def VGG_19():
        return VGG([2, 2, 4, 4, 4])        
    
    def main():
        vgg=VGG_16()
        paddle.summary(vgg, (1,3,224,224))
    
    if __name__ == '__main__':
        main()
        
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
  • 相关阅读:
    车联网远程监控管理提升车辆调度效率,实现高效运营
    基于Netty模拟大量WebSocket客户端
    For循环控制
    内网渗透-隧道代理转发
    【论文阅读】Dense Passage Retrieval for Open-Domain Question Answering
    扩散模型加持下,机器人模型DALL-E-Bot可以轻松完成自主重新排列任务
    【LeetCode】35. 搜索插入位置
    【UE】线框材质
    C++基础语法详解
    【面试】——Java面试重难点剖析
  • 原文地址:https://blog.csdn.net/qq_44173974/article/details/126129523