VGGNet的结构和复现

1 结构以及模型退化问题

上述为VGGNet的结构图,左边是VGG16D的步骤 16代表16层,有参数的层,其他结构也是如此

对于这6个机构来说,D中的VGG16是最优的,而VGG19相比较而言,没有VGG16优,VGG16有16层(包括13个卷积层和3个全连接层),而VGG19有19层(包括16个卷积层和3个全连接层),对于出现了的模型退化问题,有几个原因:

1 网络层次越深,提取的特征越是高度抽象,这可以帮助模型理解复杂的、高级的模式。然而,如果网络过深,最后几层可能会从数据中提取过于抽象的特征,与具体的输入图像的关联性减弱,导致模型性能降低

2 在非常深的网络中,梯度在反向传播过程中可能会因为多层传递而变得非常小(梯度消失)或非常大(梯度爆炸),这会使得网络难以训练

3 更深的网络通常有更多的参数,这可能会使模型更容易发生过拟合,特别是当训练数据有限时

等等一些原因

2 代码复现(6种结构的复现)

只是简单的复现

import torch.nn as nn
import torch

class VggBlock(nn.Module):
    
    def __init__(self, in_channel, out_channel, n, use_11 = False, LRN = False) -> None:
        super().__init__()
        layers = []
        for i in range(n):
            if use_11 and (i == n-1):
                kernel_size = (1, 1)
                padding = 0    
            else:
                kernel_size = (3, 3)
                padding = 1

            conv = nn.Sequential(
                nn.Conv2d(in_channel, out_channel, kernel_size=kernel_size, stride=1, padding=padding),
                nn.ReLU()
            )
            layers.append(conv)
            in_channel = out_channel
        if LRN == True:
            layers.append(nn.LocalResponseNorm(size=5))
        layers.append(nn.MaxPool2d(2))
        self.block = nn.Sequential(*layers)
    
    def forward(self, x):
        return self.block(x)



class VGGNet(nn.Module):
    
    def __init__(self, num_classes, features, classify_input_channel) -> None:
        super().__init__()
        self.num_classes = num_classes
        self.features = features
        self.pooling = nn.AdaptiveMaxPool2d(7)
        self.classify = nn.Sequential(
            nn.Linear(in_features=7 * 7 * classify_input_channel, out_features=4096),
            nn.ReLU(),
            nn.Linear(in_features=4096, out_features=4096),
            nn.ReLU(),
            nn.Linear(in_features=4096, out_features=self.num_classes),
        )

    def forward(self, images):
        z = self.features(images)
        z = self.pooling(z)
        z = z.flatten(1)
        return self.classify(z) 
    

class VGGNet11A(nn.Module):

    def __init__(self, num_classes) -> None:
        super().__init__()
        features = nn.Sequential(
            VggBlock(3, 64, 1),
            VggBlock(64, 128, 1),
            VggBlock(128, 256, 2),
            VggBlock(256, 512, 2),
            VggBlock(512, 512, 2)
        )
        self.vggnet = VGGNet(num_classes, features, classify_input_channel=512)

    def forward(self, images):
        return self.vggnet(images)
    

class VGGNet11ALRN(nn.Module):

    def __init__(self, num_classes) -> None:
        super().__init__()
        features = nn.Sequential(
            VggBlock(3, 64, 1, LRN=True),
            VggBlock(64, 128, 1),
            VggBlock(128, 256, 2),
            VggBlock(256, 512, 2),
            VggBlock(512, 512, 2)
        )
        self.vggnet = VGGNet(num_classes, features, classify_input_channel=512)

    def forward(self, images):
        return self.vggnet(images)


class VGGNet13B(nn.Module):

    def __init__(self, num_classes) -> None:
        super().__init__()
        features = nn.Sequential(
            VggBlock(3, 64, 2),
            VggBlock(64, 128, 2),
            VggBlock(128, 256, 2),
            VggBlock(256, 512, 2),
            VggBlock(512, 512, 2)
        )
        self.vggnet = VGGNet(num_classes, features, classify_input_channel=512)

    def forward(self, images):
        return self.vggnet(images)
    

class VGGNet16C(nn.Module):

    def __init__(self, num_classes) -> None:
        super().__init__()
        features = nn.Sequential(
            VggBlock(3, 64, 2),
            VggBlock(64, 128, 2),
            VggBlock(128, 256, 3, use_11=True),
            VggBlock(256, 512, 3, use_11=True),
            VggBlock(512, 512, 3, use_11=True)
        )
        self.vggnet = VGGNet(num_classes, features, classify_input_channel=512)

    def forward(self, images):
        return self.vggnet(images)
    

class VGGNet16C(nn.Module):

    def __init__(self, num_classes) -> None:
        super().__init__()
        features = nn.Sequential(
            VggBlock(3, 64, 2),
            VggBlock(64, 128, 2),
            VggBlock(128, 256, 3),
            VggBlock(256, 512, 3),
            VggBlock(512, 512, 3)
        )
        self.vggnet = VGGNet(num_classes, features, classify_input_channel=512)

    def forward(self, images):
        return self.vggnet(images)
    

class VGGNet16C(nn.Module):

    def __init__(self, num_classes) -> None:
        super().__init__()
        features = nn.Sequential(
            VggBlock(3, 64, 2),
            VggBlock(64, 128, 2),
            VggBlock(128, 256, 4),
            VggBlock(256, 512, 4),
            VggBlock(512, 512, 4)
        )
        self.vggnet = VGGNet(num_classes, features, classify_input_channel=512)

    def forward(self, images):
        return self.vggnet(images)