VGGNet架构解析

本文涉及的产品
云解析DNS,个人版 1个月
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
简介: VGGNet 是 2014 年 ImageNet Challenge 图像识别比赛的亚军。参赛团队是来自牛津 大学的研究组 VGG (Visual Geometry Group) 。VGGNet 的很多设计思想都受到 AlexNet 的影响,所以跟 AlexNet 也有一点点相似的地方。VGGNet 不仅在图像识别方向有着广泛应 用,很多目标检测,目标分割,人脸识别等方面的应用也会使用 VGGNet 作为基础模型。

@toc

参考论文:VERY DEEP CONVOLUTIONAL NETWORKS FOR LARGE-SCALE IMAGE RECOGNITION

作者:Karen Simonyan ∗ & Andrew Zisserman +

2014年ImageNet图像分类竞赛亚军、定位竞赛冠军

1、VGGNet简介

  VGGNet 是 2014 年 ImageNet Challenge 图像识别比赛的亚军。参赛团队是来自牛津 大学的研究组 VGG (Visual Geometry Group) 。VGGNet 的很多设计思想都受到 AlexNet 的影响,所以跟 AlexNet 也有一点点相似的地方。VGGNet 不仅在图像识别方向有着广泛应 用,很多目标检测,目标分割,人脸识别等方面的应用也会使用 VGGNet 作为基础模型。

  VGGNet 在 2014,2015 年左右的流行程度甚至超过了 2014 年 ImageNet Challenge 图像识别比赛的冠军 GoogleNet,是当时用得最多的深度学习模型。VGGNet 被广泛使用 也是有一定原因的,VGGNet 的网络结构比较简单,也容易搭建,并且 VGGNet 的单模型结 果与 GoogleNet 相当。ImageNet Challenge 是一个比赛,在比赛中我们经常会使用模型 融合(Ensemble Model)策略,把多个模型组合在一起,这样有可能会得到更好的结果。 2014 年,在 ImageNet Challenge 比赛中,多个 GoogleNet 融合后的结果比多个 VGGNet 融合后的结果要更好,所以 GoogleNet 得到了冠军。最早提出 VGGNet 的论文是《Very Deep Convolutional Networks for Large-Scale Image Recognition》

2、VGGNet模型结构

  VGGNet 有多个版本,如下图所示。

image-20220813194748898

   图中 ConvNet Configuration 表示网络结构;weight layers 表示网络层数;input 表示输入;conv 表示卷积;maxpool 表示最大池化;FC 表示全连接层。

  我们可以看出 VGGNet 有 6 个不同的版本,他们的主要区别是网络层数和网络结构的区 别。图中的 conv3 表示 3×3 的卷积,conv1 表示 1×1 的卷积;conv3-128 表示 3×3 的 卷积计算后生成 128 个特征图;LRN(Local Response Normalization)是局部响应归一 化,一种在 AlexNet 中使用的数据归一化计算,不过 VGGNet 的作者认为 LRN 并没有什么 用,所以在 VGGNet 中并没有使用。

  其中使用得比较多的有 B,因为它有 13 层,我们称之为 VGG13。使用得比较多的还有 D,因为它有 16 层,我们称之为 VGG16。使用得比较多的还有 E,因为它有 19 层,我们称 之为 VGG19。在 ImageNet Challenge 图像识别比赛中效果最好的是 VGG19,其次到 VGG16,最后是 VGG13。

  上面几种模型对应的参数量(单位:百万)

image-20220813194901611

  每个版本的模型网络结构不同,所以参数的数量也有所不同。参数数量最少的是 A,有 1 亿 3 千多万个参数。最多的是 E,有 1 亿 4 千多万个参数。别看网络中有很多的卷积层,其 实网络中大部分的参数都是在全连接层中。比如在 VGG16 中,卷积层的参数数量占所有参 数的 13%,而全连接层的参数数量占到了 87%。

3、VGG16架构

  由于在应用中VGG16架构用的多一点,所以这里研究并复现一下该架构。

3.1 模型结构

image-20220813195032890

img

   图中 fc 表示 fully connected,代表全连接;pool 表示 max pooling,代表最大池化; conv 表示 convolution,代表卷积;output 表示输出。

  VGG16 的所有卷积都是 3×3,步长为 1,same padding;所有池化都是 2×2,步长 为 2,same padding;输出层函数为 softmax,除了输出层以外,其他层激活函数都是 ReLU 函数。

  VGG16 受 AlexNet 的影响和启发,图片的输入为 224×224 的大小,卷积层后面也使用了 3 个全连接层,并且全连接层也是使用 4096 个神经元。

  VGG16 是一个 16 层的网络,它的结构比较简单易懂,叠加了很多个卷积池化层。2× 2,步长为 2 的池化特会使得特征图的长宽减少为原来 1/2,池化后的下一个卷积会使得特征图的数量会变成原来的 2 倍。

3.2 各block块参数说明

  VGG16 的输入是 224×224 大小的图片。

  block1 为第 1,2 层,其中包含了 2 个卷积和 1 池化,卷积后图像大小没有发生变化 224×224,池化后特征图大小变成了 112×112,特征图的数量为 64。

  block2 为第 3,4 层,其中包含了 2 个卷积和 1 池化,卷积后图像大小没有发生变化 112×112,池化后特征图大小变成了 56×56,特征图的数量为 128。

  block3 为第 5,6,7 层,其中包含了 3 个卷积和 1 池化,卷积后图像大小没有发生变化 56×56,池化后特征图大小变成了 28×28,特征图的数量为 256。

  block4 为第 8,9,10 层,其中包含了 3 个卷积和 1 池化,卷积后图像大小没有发生变 化 28×28,池化后特征图大小变成了 14×14,特征图的数量为 512。

  block5 为第 11,12,13 层,其中包含了 3 个卷积和 1 池化,卷积后图像大小没有发生 变化 14×14,池化后特征图大小变成了 7×7,特征图的数量为 512。大家可能会稍微有点 疑惑,block5 中的特征图的数量按照规律不应该会变成 1024 吗,但是这里还是 512。这里的原因我猜测是作者他们肯定也尝试过 1024,但是最后的效果估计跟 512 的效果差不多。 并且改成 1024 后会增加很多计算量和需要训练的权值,所以最后的版本中就没有使用 1024。

  第 14 层计算。把 pool5 的 512 个 7×7 的特征图数据跟 fc1 中的 4096 个神经元进行全 连接计算。

  第 15 层计算。把 fc2 的 4096 个神经元跟 fc1 中的 4096 个神经元进行全连接计算。

  第 16 层计算。把 output 的 1000(ImageNet Challenge 比赛有 1000 个分类)个神 经元跟 fc2 中的 4096 个神经元进行全连接计算。最后再经过 softmax 计算得到类别的概率 值进行输出。

   VGGNet 网络结构本身并没有太多创新的内容,它可以看成是对 AlexNet 网络的改进优 化版本。

3.3 VGG16模型复现

import numpy as np
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.utils import to_categorical
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Dropout, Conv2D, MaxPool2D, Flatten, Input
from tensorflow.keras.models import Model
from tensorflow.keras.optimizers import Adam
import matplotlib.pyplot as plt
from tensorflow.keras.callbacks import LearningRateScheduler
from plot_model import plot_model
这里我是在自己的数据集上面跑的,所以只有17个类别,原始应该是用的ImageNet数据集,有1000个类别
# 类别数
num_class = 17
# 批次大小
batch_size = 32
# 周期数
epochs = 100
# 图片大小
image_size = 224

网络搭建

本来想训练下这个模型,但是近一亿四千万的参数我机器实在是跑不动,想跑的话还是用预训练好的模型跑吧,这里主要是复现模型结构。
# VGG16网络搭建
inputs = Input(shape=(image_size,image_size,3))
# block1
x=Conv2D(filters=64,kernel_size=(3,3),strides=(1,1),padding='same',activation='relu')(inputs)
x=Conv2D(filters=64,kernel_size=(3,3),strides=(1,1),padding='same',activation='relu')(x)
x=MaxPool2D(pool_size=(2,2),strides=2,padding='same')(x)

# block2
x=Conv2D(filters=128,kernel_size=(3,3),strides=(1,1),padding='same',activation='relu')(x)
x=Conv2D(filters=128,kernel_size=(3,3),strides=(1,1),padding='same',activation='relu')(x)
x=MaxPool2D(pool_size=(2,2),strides=2,padding='same')(x)

# block3
x=Conv2D(filters=256,kernel_size=(3,3),strides=(1,1),padding='same',activation='relu')(x)
x=Conv2D(filters=256,kernel_size=(3,3),strides=(1,1),padding='same',activation='relu')(x)
x=Conv2D(filters=256,kernel_size=(3,3),strides=(1,1),padding='same',activation='relu')(x)
x=MaxPool2D(pool_size=(2,2),strides=2,padding='same')(x)

# block4
x=Conv2D(filters=512,kernel_size=(3,3),strides=(1,1),padding='same',activation='relu')(x)
x=Conv2D(filters=512,kernel_size=(3,3),strides=(1,1),padding='same',activation='relu')(x)
x=Conv2D(filters=512,kernel_size=(3,3),strides=(1,1),padding='same',activation='relu')(x)
x=MaxPool2D(pool_size=(2,2),strides=2,padding='same')(x)

# block5
x=Conv2D(filters=512,kernel_size=(3,3),strides=(1,1),padding='same',activation='relu')(x)
x=Conv2D(filters=512,kernel_size=(3,3),strides=(1,1),padding='same',activation='relu')(x)
x=Conv2D(filters=512,kernel_size=(3,3),strides=(1,1),padding='same',activation='relu')(x)
x=MaxPool2D(pool_size=(2,2),strides=2,padding='same')(x)
# 全连接
x=Flatten()(x)
x=Dense(4096,activation='relu')(x)
x=Dropout(0.5)(x)
x=Dense(4096,activation='relu')(x)
x=Dropout(0.5)(x)
out=Dense(1000,activation='softmax')(x)
model=Model(inputs=inputs,outputs=out)
model.summary()
plot_model(model,to_file='img/VGG16.png',show_shapes=True)

模型摘要如下:

Model: "model"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_1 (InputLayer)         [(None, 224, 224, 3)]     0         
_________________________________________________________________
conv2d (Conv2D)              (None, 224, 224, 64)      1792      
_________________________________________________________________
conv2d_1 (Conv2D)            (None, 224, 224, 64)      36928     
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 112, 112, 64)      0         
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 112, 112, 128)     73856     
_________________________________________________________________
conv2d_3 (Conv2D)            (None, 112, 112, 128)     147584    
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 56, 56, 128)       0         
_________________________________________________________________
conv2d_4 (Conv2D)            (None, 56, 56, 256)       295168    
_________________________________________________________________
conv2d_5 (Conv2D)            (None, 56, 56, 256)       590080    
_________________________________________________________________
conv2d_6 (Conv2D)            (None, 56, 56, 256)       590080    
_________________________________________________________________
max_pooling2d_2 (MaxPooling2 (None, 28, 28, 256)       0         
_________________________________________________________________
conv2d_7 (Conv2D)            (None, 28, 28, 512)       1180160   
_________________________________________________________________
conv2d_8 (Conv2D)            (None, 28, 28, 512)       2359808   
_________________________________________________________________
conv2d_9 (Conv2D)            (None, 28, 28, 512)       2359808   
_________________________________________________________________
max_pooling2d_3 (MaxPooling2 (None, 14, 14, 512)       0         
_________________________________________________________________
conv2d_10 (Conv2D)           (None, 14, 14, 512)       2359808   
_________________________________________________________________
conv2d_11 (Conv2D)           (None, 14, 14, 512)       2359808   
_________________________________________________________________
conv2d_12 (Conv2D)           (None, 14, 14, 512)       2359808   
_________________________________________________________________
max_pooling2d_4 (MaxPooling2 (None, 7, 7, 512)         0         
_________________________________________________________________
flatten (Flatten)            (None, 25088)             0         
_________________________________________________________________
dense (Dense)                (None, 4096)              102764544 
_________________________________________________________________
dropout (Dropout)            (None, 4096)              0         
_________________________________________________________________
dense_1 (Dense)              (None, 4096)              16781312  
_________________________________________________________________
dropout_1 (Dropout)          (None, 4096)              0         
_________________________________________________________________
dense_2 (Dense)              (None, 1000)              4097000   
=================================================================
Total params: 138,357,544
Trainable params: 138,357,544
Non-trainable params: 0

image-20220813200219310

References

Karen Simonyan, & Andrew Zisserman (2015). Very Deep Convolutional Networks for Large-Scale Image Recognition

【精读AI论文】VGG深度学习图像分类算法

目录
相关文章
|
4天前
|
运维 Kubernetes 监控
深入解析微服务架构的演进与实践
本文旨在探究微服务架构从诞生到成熟的发展历程,分析其背后的技术推动力和业务需求,并结合具体案例,揭示实施微服务过程中的挑战与解决策略。通过对微服务架构与传统单体架构的对比,阐明微服务如何优化现代应用开发流程,提高系统的可扩展性、可维护性和敏捷性。
14 0
|
11天前
|
负载均衡 监控 安全
微服务架构中的API网关模式解析
【7月更文挑战第4天】在微服务架构中,API网关不仅是一个技术组件,它是连接客户端与微服务之间的桥梁,负责请求的路由、负载均衡、认证、限流等关键功能。本文将深入探讨API网关的设计原则、实现方式及其在微服务架构中的作用和挑战,帮助读者理解如何构建高效、可靠的API网关。
|
14天前
|
消息中间件 Java API
解析Java微服务架构:从零构建高性能系统
解析Java微服务架构:从零构建高性能系统
|
18天前
|
存储 SQL BI
深入解析实时数仓Doris:介绍、架构剖析、应用场景与数据划分细节
深入解析实时数仓Doris:介绍、架构剖析、应用场景与数据划分细节
|
19天前
|
存储 缓存 监控
深入解析Elasticsearch的内存架构与管理
深入解析Elasticsearch的内存架构与管理
深入解析Elasticsearch的内存架构与管理
|
12天前
|
人工智能 搜索推荐 计算机视觉
[AI Perplexica] 深入解析,AI 架构揭秘
了解 Perplexica 的核心架构,探索其用户界面、代理链、大型语言模型、嵌入模型等关键组件的运作方式,揭秘 AI 如何高效处理复杂查询任务。
|
13天前
|
负载均衡 Java 微服务
Java中的可扩展微服务架构设计案例解析
Java中的可扩展微服务架构设计案例解析
|
16天前
|
存储 前端开发 JavaScript
构建高性能返利App的技术架构解析
构建高性能返利App的技术架构解析
|
17天前
|
网络协议 安全 分布式数据库
技术分享:分布式数据库DNS服务器的架构思路
技术分享:分布式数据库DNS服务器的架构思路
19 0
|
26天前
|
XML Java 数据格式
深度解析 Spring 源码:从 BeanDefinition 源码探索 Bean 的本质
深度解析 Spring 源码:从 BeanDefinition 源码探索 Bean 的本质
28 3

推荐镜像

更多