一位深度学习小萌新的学渣笔记(三)VGG网络介绍及代码详解

前言

继续学习霹雳大神的神经网络讲解视频

更新不易,希望大家可以去看原视频支持up主

VGG网络详解及感受野的计算
使用pytorch搭建VGG网络

VGG网络结构详解与模型的搭建

简单介绍VGG

模型结构

在这里插入图片描述
在这里插入图片描述

  • 经常用的是16层结构👆13层个卷积层以及3个全连接层

亮点

  • 网络亮点:通过堆叠多个3x3 的卷积核来以替代大尺度卷积核(减少所需参数)

感受野

概念

在这里插入图片描述

例子

在这里插入图片描述

感受野计算公式

在这里插入图片描述
也就是说我们特征层3中的一个单元就相当于我们原图中的5*5的感受视野

为什么论文中说堆叠两个3x3的卷积核代替5x5的卷积核,堆叠三个3x3的卷积核替代7x7的卷积核?
在VGG网络中卷积核的步距(stride)是默认为 1 的
可以经过计算得到
在这里插入图片描述
目的:减少网络中训练参数的个数
同样可以通过计算证明
在这里插入图片描述
一个C是卷积核的深度就是有多层卷积,还有一个C是卷积核的个数,(因为这里假设的输入输出channel相同,所以输出的特征矩阵也是C
在这里插入图片描述

VGG16

参数使用

在这里插入图片描述

卷积层

通过这个参数设定的卷积层输出的高度和宽度不变:
由计算可以算得
在这里插入图片描述
我们设定的卷积核的大小就是 3*3
out =( in - 3 + 2 )/ 1 + 1 = in

下采样层

通过这个参数设定的下采样层输出的高度和宽度直接缩小为原来的一半:
out =( in - 2 + 0 )/ 2 + 1 = in / 2

基本结构

16 weight layers
Input (224x224 RGB images)

两层3x3的卷积核+ReLU
Maxpool最大下采样层

两层3x3的卷积核+ReLU
Maxpool最大下采样层

三层3x3的卷积核+ReLU
Maxpool最大下采样层

三层3x3的卷积核+ReLU
Maxpool最大下采样层

连接两个全连接层+ReLU
一层全连接层

加上一个soft-max处理进行激活
在这里插入图片描述
(2层)由于采用的卷积核conv3-64 的深度是64 所以输出的特征矩阵 宽和高不变 深度变成64
22422464
由于采用的下采样层maxpool 将特征矩阵 宽和高缩减为原来的一半 深度不变还是64 11211264
(2层)后面又是卷积核conv3-128的深度是128 所以输出的特征矩阵 宽和高不变 深度变成128
112112128
下采样层maxpool 将特征矩阵 宽和高缩减为原来的一半 深度不变还是128
5656128
(三层)卷积核conv3-256的深度是256 所以输出的特征矩阵 宽和高不变 深度变成256
5656256
下采样层maxpool 将特征矩阵 宽和高缩减为原来的一半 深度不变还是256
2828256
(三层)卷积核conv3-512的深度是512 所以输出的特征矩阵 宽和高不变 深度变成512
2828512
下采样层maxpool 将特征矩阵 宽和高缩减为原来的一半 深度不变还是512
1414512
(三层)卷积核conv3-512的深度是512 所以输出的特征矩阵 宽和高不变 深度变成512
1414512
下采样层maxpool 将特征矩阵 宽和高缩减为原来的一半 深度不变还是512
77512
(三层)全连接层
FC-4096(ReLU)
FC-4096(ReLU)
FC-1000

model.py中代码解读

提取特征网络结构

卷积层+下采样层
cfgs = {
    'vgg11': [64, 'M', 128, 'M', 256, 256, 'M', 512, 512, 'M', 512, 512, 'M'],
    #所有的卷积核大小都是3*3  64个卷积核  最大池化下采样层  128个卷积核 最大池化层  256个卷积核   256个卷积核  下采样层  512个卷积核  512个卷积核   下采样层   512个卷积核  512个卷积核  下采样层  
    'vgg13': [64, 64, 'M', 128, 128, 'M', 256, 256, 'M', 512, 512, 'M', 512, 512, 'M'],
    'vgg16': [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 'M', 512, 512, 512, 'M', 512, 512, 512, 'M'],
    'vgg19': [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 256, 'M', 512, 512, 512, 512, 'M', 512, 512, 512, 512, 'M'],
}

生成提取特征网络结构


def make_features(cfg: list):#传入一个配置变量 是一个list的类型 传入定义配置的列表
    layers = [] #定义一个空列表来存放我们创建的每一层结构
    in_channels = 3 #输入通道是3
    for v in cfg: #由for循环遍历我们的配置列表就可以得到  可以得到一个有卷积操作和池化操作做组成一个列表
        if v == "M": #如果是一个最大池化层的话
            layers += [nn.MaxPool2d(kernel_size=2, stride=2)] 
            #创建一个最大池化下采样2d 已经规定了池化核的大小都是2, 步长也是2
        else:  #否则就是一个卷积核
            conv2d = nn.Conv2d(in_channels, v, kernel_size=3, padding=1)
            #创建一个卷积层  输入的彩色图像的深度是3 输出的特征矩阵的深度也就是对应着我们卷积核的个数,卷积核大小是3*3 padding=1     stride默认是等于1
            layers += [conv2d, nn.ReLU(True)]
            #每一个卷积层都是采用ReLU激活函数 定义在一起 并添加到layers的空列表中
            in_channels = v
            #讲in channels改变 使得上一层的输出变成下一层的输入
    return nn.Sequential(*layers)
    #Sequential函数将我们的列表通过非关键字参数的形式传入  
    #Sequential

分类网络结构

全连接层

class VGG(nn.Module):#继承自nn.Module的父类
    def __init__(self, features, num_classes=1000, init_weights=False):
    #初始化函数中  features是我们通过makefeatures函数生成的特征网络结构  所需要分类的类别个数
     #是否对我们网络进行权重初始化= False 
        super(VGG, self).__init__()
        self.features = features #是我们刚刚生成的网络features
        self.classifier = nn.Sequential(    #同样是利用sequential函数来生成分类网络结构  
            nn.Dropout(p=0.5), #目的是为了减少过拟合 0.5概率随机失活神经元
            nn.Linear(512*7*7, 2048), #输入节点个数就是我们展平之后所得到的一维向量的元素个数
            #全连接层的输出节点个数原论文中是4096 为了减少训练参数就是设置为2048
            nn.ReLU(True),#激活函数
            nn.Dropout(p=0.5),
            nn.Linear(2048, 2048),#输入节点个数是上一层的输出节点个数  
             #全连接层的输出节点个数原论文中是4096 为了减少训练参数就是设置为2048
            nn.ReLU(True),
            nn.Linear(2048, num_classes)
            #输入节点个数是上一层的输出节点个数  输出节点个数是对应我们分类的类别个数
            
        )
        if init_weights: #如果有初始化的参数的话
            self._initialize_weights() #进入到提前定义好的初始化权重函数当中

    def forward(self, x): #forward正向传播的过程 x是我们输入的图像数据
        # N x 3 x 224 x 224
        x = self.features(x) #通过我们的特征网络结构
        # N x 512 x 7 x 7
        x = torch.flatten(x, start_dim=1) #通过一个展平处理 第0个维度是我们的batch维度 从channel开始展平         
        # N x 512*7*7
        x = self.classifier(x) #通过我们的分类网络结构
        return x

    def _initialize_weights(self):
        for m in self.modules(): #遍历我们网络的每一个子模块
            if isinstance(m, nn.Conv2d):#如果遍历的当前层是一个卷积层的话
                # nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
                nn.init.xavier_uniform_(m.weight)
                #用我们的xavier的初始化方法去初始化我们的卷积层的权重
                if m.bias is not None: #如果采用了偏置的话
                    nn.init.constant_(m.bias, 0) #将我们的偏置初始化为0
            elif isinstance(m, nn.Linear):#如果遍历的当前层是一个全连接层的话
                nn.init.xavier_uniform_(m.weight)
                #用我们的xavier的初始化方法去初始化我们的全连接层权重
                # nn.init.normal_(m.weight, 0, 0.01)
                nn.init.constant_(m.bias, 0)
				#将我们的偏置初始化为0

实例化我们的VGG网络


def vgg(model_name="vgg16", **kwargs):
#model_name可以实例化的我们所给定的网络模型 
    try:
        cfg = cfgs[model_name] #得到我们的配置列表
    except:
        print("Warning: model number {} not in cfgs dict!".format(model_name))
        exit(-1)
    model = VGG(make_features(cfg), **kwargs) #通过VGG的类来实例化我们VGG网络
    #第一个参数 make_features是一个函数 feature的参数是所对应的配置文件, **kwargs可变长度的字典变量,包括了class_num=1000.init_weights=False.
    return model

train.py代码解读

和训练AlexNet基本上一样

predict.py

和训练AlexNet基本上一样

  • 9
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
以下是使用预训练的VGG16模型进行迁移学习的代码示例: ```python import tensorflow as tf from tensorflow.keras.preprocessing.image import ImageDataGenerator from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Dense, Dropout, Flatten from tensorflow.keras.applications import VGG16 # 设置数据集路径和参数 train_data_dir = 'train/' validation_data_dir = 'validation/' img_width, img_height = 224, 224 batch_size = 32 epochs = 10 # 加载预训练的VGG16模型 vgg16_model = VGG16(weights='imagenet', include_top=False, input_shape=(img_width, img_height, 3)) # 冻结预训练模型的所有层 for layer in vgg16_model.layers: layer.trainable = False # 构建模型 model = Sequential() model.add(vgg16_model) model.add(Flatten()) model.add(Dense(256, activation='relu')) model.add(Dropout(0.5)) model.add(Dense(1, activation='sigmoid')) # 编译模型 model.compile(loss='binary_crossentropy', optimizer=tf.keras.optimizers.Adam(lr=0.0001), metrics=['accuracy']) # 数据增强 train_datagen = ImageDataGenerator(rescale=1./255, shear_range=0.2, zoom_range=0.2, horizontal_flip=True) validation_datagen = ImageDataGenerator(rescale=1./255) train_generator = train_datagen.flow_from_directory(train_data_dir, target_size=(img_width, img_height), batch_size=batch_size, class_mode='binary') validation_generator = validation_datagen.flow_from_directory(validation_data_dir, target_size=(img_width, img_height), batch_size=batch_size, class_mode='binary') # 训练模型 model.fit(train_generator, steps_per_epoch=train_generator.samples // batch_size, epochs=epochs, validation_data=validation_generator, validation_steps=validation_generator.samples // batch_size) ``` 在这个示例中,我们使用预训练的VGG16模型作为特征提取器,并添加了几个全连接层来进行分类。我们还对预训练模型的所有层进行了冻结,并使用ImageDataGenerator进行数据增强。最后,我们使用fit()方法来训练模型。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值