转载自:http://deanhan.com/2018/07/26/vgg16/

摘要

本文对图片分类任务中经典的深度学习模型VGG16进行了简要介绍,分析了其结构,并讨论了其优缺点。调用Keras中已有的VGG16模型测试其分类性能,结果表明VGG16对三幅测试图片均能正确分类。

前言

VGG是由Simonyan 和Zisserman在文献《Very Deep Convolutional Networks for Large Scale Image Recognition》中提出卷积神经网络模型,其名称来源于作者所在的牛津大学视觉几何组(Visual Geometry Group)的缩写。

该模型参加2014年的 ImageNet图像分类与定位挑战赛,取得了优异成绩:在分类任务上排名第二,在定位任务上排名第一。

结构

VGG中根据卷积核大小卷积层数目的不同,可分为AA-LRN,B,C,D,E共6个配置(ConvNet Configuration),其中以D,E两种配置较为常用,分别称为VGG16VGG19

下图给出了VGG的六种结构配置:

上图中,每一列对应一种结构配置。例如,图中绿色部分即指明了VGG16所采用的结构。

我们针对VGG16进行具体分析发现,VGG16共包含:

  • 13个卷积层(Convolutional Layer),分别用conv3-XXX表示
  • 3个全连接层(Fully connected Layer),分别用FC-XXXX表示
  • 5个池化层(Pool layer),分别用maxpool表示

其中,卷积层和全连接层具有权重系数,因此也被称为权重层,总数目为13+3=16,这即是

VGG16中16的来源。(池化层不涉及权重,因此不属于权重层,不被计数)。

特点

VGG16的突出特点是简单,体现在:

  1. 卷积层均采用相同的卷积核参数

    卷积层均表示为conv3-XXX,其中conv3说明该卷积层采用的卷积核的尺寸(kernel size)是3,即宽(width)和高(height)均为3,3*3很小的卷积核尺寸,结合其它参数(步幅stride=1,填充方式padding=same),这样就能够使得每一个卷积层(张量)与前一层(张量)保持相同的宽和高。XXX代表卷积层的通道数。

  2. 池化层均采用相同的池化核参数

    池化层的参数均为2××2,步幅stride=2,max的池化方式,这样就能够使得每一个池化层(张量)的宽和高是前一层(张量)的1212。

  3. 模型是由若干卷积层和池化层堆叠(stack)的方式构成,比较容易形成较深的网络结构(在2014年,16层已经被认为很深了)。

综合上述分析,可以概括VGG的优点为: Small filters, Deeper networks.

块结构

我们注意图1右侧,VGG16的卷积层和池化层可以划分为不同的块(Block),从前到后依次编号为Block1~block5。每一个块内包含若干卷积层一个池化层。例如:Block4包含:

  • 3个卷积层,conv3-512
  • 1个池化层,maxpool

并且同一块内,卷积层的通道(channel)数是相同的,例如:

  • block2中包含2个卷积层,每个卷积层用conv3-128表示,即卷积核为:3x3x3,通道数都是128
  • block3中包含3个卷积层,每个卷积层用conv3-256表示,即卷积核为:3x3x3,通道数都是256

下面给出按照块划分的VGG16的结构图,可以结合图2进行理解:

VGG的输入图像是 224x224x3 的图像张量(tensor),随着层数的增加,后一个块内的张量相比于前一个块内的张量:

  • 通道数翻倍,由64依次增加到128,再到256,直至512保持不变,不再翻倍
  • 高和宽变减半,由 $224 \rightarrow 112\rightarrow 56\rightarrow 28\rightarrow 14\rightarrow 7$

权重参数

尽管VGG的结构简单,但是所包含的权重数目却很大,达到了惊人的139,357,544个参数。这些参数包括卷积核权重全连接层权重

  • 例如,对于第一层卷积,由于输入图的通道数是3,网络必须学习大小为3x3,通道数为3的的卷积核,这样的卷积核有64个,因此总共有(3x3x3)x64 = 1728个参数
  • 计算全连接层的权重参数数目的方法为:前一层节点数×本层的节点数前一层节点数×本层的节点数。因此,全连接层的参数分别为:
    • 7x7x512x4096 = 1027,645,444
    • 4096x4096 = 16,781,321
    • 4096x1000 = 4096000

FeiFei Li在CS231的课件中给出了整个网络的全部参数的计算过程(不考虑偏置),如下图所示:

图中蓝色是计算权重参数数量的部分;红色是计算所需存储容量的部分。

VGG16具有如此之大的参数数目,可以预期它具有很高的拟合能力;但同时缺点也很明显:

  • 即训练时间过长,调参难度大。
  • 需要的存储容量大,不利于部署。例如存储VGG16权重值文件的大小为500多MB,不利于安装到嵌入式系统中。

实践

下面,我们应用Keras对VGG16的图像分类能力进行试验。

Keras是一个高层神经网络API,Keras由纯Python编写 ,是tensorflow和Theano等底层深度学习库的高级封装 。使用Keras时,我们不需要直接调用底层API构建深度学习网络,仅调用keras已经封装好的函数即可。

本次试验平台:python 3.6 + tensorflow 1.8 + keras 2.2,Google Colab

源代码如下:

 # -*- coding: utf-8 -*-
"""
Spyder Editor This is a temporary script file.
"""
import matplotlib.pyplot as plt from keras.applications.vgg16 import VGG16
from keras.preprocessing import image
from keras.applications.vgg16 import preprocess_input, decode_predictions
import numpy as np def percent(value):
return '%.2f%%' % (value * 100) # include_top=True,表示會載入完整的 VGG16 模型,包括加在最後3層的卷積層
# include_top=False,表示會載入 VGG16 的模型,不包括加在最後3層的卷積層,通常是取得 Features
# 若下載失敗,請先刪除 c:\<使用者>\.keras\models\vgg16_weights_tf_dim_ordering_tf_kernels.h5
model = VGG16(weights='imagenet', include_top=True) # Input:要辨識的影像
img_path = 'frog.jpg' #img_path = 'tiger.jpg' 并转化为224*224的标准尺寸
img = image.load_img(img_path, target_size=(224, 224)) x = image.img_to_array(img) #转化为浮点型
x = np.expand_dims(x, axis=0)#转化为张量size为(1, 224, 224, 3)
x = preprocess_input(x) # 預測,取得features,維度為 (1,1000)
features = model.predict(x) # 取得前五個最可能的類別及機率
pred=decode_predictions(features, top=5)[0] #整理预测结果,value
values = []
bar_label = []
for element in pred:
values.append(element[2])
bar_label.append(element[1]) #绘图并保存
fig=plt.figure(u"Top-5 预测结果")
ax = fig.add_subplot(111)
ax.bar(range(len(values)), values, tick_label=bar_label, width=0.5, fc='g')
ax.set_ylabel(u'probability')
ax.set_title(u'Top-5')
for a,b in zip(range(len(values)), values):
ax.text(a, b+0.0005, percent(b), ha='center', va = 'bottom', fontsize=7) fig = plt.gcf()
plt.show() name=img_path[0:-4]+'_pred'
fig.savefig(name, dpi=200)

上述程序的基本流程是:

  1. 载入相关模块,keras ,matplotlib,numpy
  2. 下载已经训练好的模型文件:
  3. 导入测试图像
  4. 应用模型文件对图像分类

需要额外说明的是:

  • 程序运行过程中,语句model = VGG16(weights='imagenet', include_top=True)会下载已经训练好的文件到c:\<使用者>\.keras\models文件夹下,模型的文件名为vgg16_weights_tf_dim_ordering_tf_kernels.h5,大小为527MB

  • 语句pred=decode_predictions(features, top=5)[0]会下载分类信息文件到c:\<使用者>\.keras\models文件夹下,模型的文件名为imagenet_class_index.json,该文件指明了ImageNet大赛所用的1000个图像类的信息。(由于下载地址在aws上,梯子请自备)

  • 程序运行结束,会在工作目录下生成测试图片的预测图,给出了最有可能的前5个类列。名称为:测试文件名_pred.png

  • 在程序中还可以查看模型的结构,语句为:model.summary(),命令行输出模型的结构配置为:
 _________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
input_12 (InputLayer) (None, 224, 224, 3) 0
_________________________________________________________________
block1_conv1 (Conv2D) (None, 224, 224, 64) 1792
_________________________________________________________________
block1_conv2 (Conv2D) (None, 224, 224, 64) 36928
_________________________________________________________________
block1_pool (MaxPooling2D) (None, 112, 112, 64) 0
_________________________________________________________________
block2_conv1 (Conv2D) (None, 112, 112, 128) 73856
_________________________________________________________________
block2_conv2 (Conv2D) (None, 112, 112, 128) 147584
_________________________________________________________________
block2_pool (MaxPooling2D) (None, 56, 56, 128) 0
_________________________________________________________________
block3_conv1 (Conv2D) (None, 56, 56, 256) 295168
_________________________________________________________________
block3_conv2 (Conv2D) (None, 56, 56, 256) 590080
_________________________________________________________________
block3_conv3 (Conv2D) (None, 56, 56, 256) 590080
_________________________________________________________________
block3_pool (MaxPooling2D) (None, 28, 28, 256) 0
_________________________________________________________________
block4_conv1 (Conv2D) (None, 28, 28, 512) 1180160
_________________________________________________________________
block4_conv2 (Conv2D) (None, 28, 28, 512) 2359808
_________________________________________________________________
block4_conv3 (Conv2D) (None, 28, 28, 512) 2359808
_________________________________________________________________
block4_pool (MaxPooling2D) (None, 14, 14, 512) 0
_________________________________________________________________
block5_conv1 (Conv2D) (None, 14, 14, 512) 2359808
_________________________________________________________________
block5_conv2 (Conv2D) (None, 14, 14, 512) 2359808
_________________________________________________________________
block5_conv3 (Conv2D) (None, 14, 14, 512) 2359808
_________________________________________________________________
block5_pool (MaxPooling2D) (None, 7, 7, 512) 0
_________________________________________________________________
flatten (Flatten) (None, 25088) 0
_________________________________________________________________
fc1 (Dense) (None, 4096) 102764544
_________________________________________________________________
fc2 (Dense) (None, 4096) 16781312
_________________________________________________________________
predictions (Dense) (None, 1000) 4097000
=================================================================
Total params: 138,357,544
Trainable params: 138,357,544
Non-trainable params: 0
_________________________________________________________________

可以看到总的训练参数为 $138,357,544$。

代码及图片文件全部放在我的github

结果

分别对虎(tiger),猫(cat),卷纸(paper_towel)三张图片进行分类:




网上随便下的图,效果还行.

VGG16学习笔记的更多相关文章

  1. 深度学习笔记(七)SSD 论文阅读笔记简化

    一. 算法概述 本文提出的SSD算法是一种直接预测目标类别和bounding box的多目标检测算法.与faster rcnn相比,该算法没有生成 proposal 的过程,这就极大提高了检测速度.针 ...

  2. 深度学习笔记(七)SSD 论文阅读笔记

    一. 算法概述 本文提出的SSD算法是一种直接预测目标类别和bounding box的多目标检测算法.与faster rcnn相比,该算法没有生成 proposal 的过程,这就极大提高了检测速度.针 ...

  3. Deep learning with Python 学习笔记(4)

    本节讲卷积神经网络的可视化 三种方法 可视化卷积神经网络的中间输出(中间激活) 有助于理解卷积神经网络连续的层如何对输入进行变换,也有助于初步了解卷积神经网络每个过滤器的含义 可视化卷积神经网络的过滤 ...

  4. Deep learning with Python 学习笔记(3)

    本节介绍基于Keras的使用预训练模型方法 想要将深度学习应用于小型图像数据集,一种常用且非常高效的方法是使用预训练网络.预训练网络(pretrained network)是一个保存好的网络,之前已在 ...

  5. tensorflow学习笔记——VGGNet

    2014年,牛津大学计算机视觉组(Visual Geometry Group)和 Google DeepMind 公司的研究员一起研发了新的深度卷积神经网络:VGGNet ,并取得了ILSVRC201 ...

  6. 官网实例详解-目录和实例简介-keras学习笔记四

    官网实例详解-目录和实例简介-keras学习笔记四 2018-06-11 10:36:18 wyx100 阅读数 4193更多 分类专栏: 人工智能 python 深度学习 keras   版权声明: ...

  7. Tensorflow学习笔记No.8

    使用VGG16网络进行迁移学习 使用在ImageNet数据上预训练的VGG16网络模型对猫狗数据集进行分类识别. 1.预训练网络 预训练网络是一个保存好的,已经在大型数据集上训练好的卷积神经网络. 如 ...

  8. js学习笔记:webpack基础入门(一)

    之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...

  9. PHP-自定义模板-学习笔记

    1.  开始 这几天,看了李炎恢老师的<PHP第二季度视频>中的“章节7:创建TPL自定义模板”,做一个学习笔记,通过绘制架构图.UML类图和思维导图,来对加深理解. 2.  整体架构图 ...

随机推荐

  1. 【Hadoop】MapReduce笔记(二):MapReduce容错,任务失败处理

    典型问题:Hadoop如何判断一个任务失败?失败了怎么做? 分析:实际情况下,用户代码存在软件错误.进程崩溃.机器故障等都会导致失败.Hadoop判断的失败有不同级别类型,针对不同级别的失败有不同的处 ...

  2. 3-3if-else条件结构 & 3-4 & 3-5

    新建类: ConditionDemo2 package com.imooc.operator; public class ConditionDemo2 { public static void mai ...

  3. JavaScript代码风格和分号使用问题

    1.推荐代码风格 JavaScript Standard Style  规定相对松散更多人使用此规范 Airbnb JavaScript Style  规定更严格但也没毛病 2.JavaScript代 ...

  4. bzoj 2738: 矩阵乘法【整体二分+树状数组】

    脑子一抽开始写主席树,敲了一会发现不对-- 整体二分,用二维树状数组维护值为当前区间的格子个数,然后根据k的大小和当前询问的子矩阵里的值和k的大小关系来决定这个询问放在哪一部分向下递归 #includ ...

  5. 2014-7-7 NOIP模拟赛(图论)

    1.无线通讯网(wireless.pas/cpp/c) [题目描述] 国防部计划用无线网络连接若干个边防哨所.2种不同的通讯技术用来搭建无线网络:每个边防哨所都要配备无线电收发器:有一些哨所还可以增配 ...

  6. npm,cnpm,nrm区别

    npm npm(node package manager)是nodejs的包管理器,用于node插件管理(包括安装.卸载.管理依赖等) nrm nrm只是单纯的提供了几个常用的下载包的uri地址,并能 ...

  7. Cordova 系列之Mac OS 环境配置

    1.从AppStore 安装xcode 2.安装node.js环境 http://nodejs.org/ 3.使用命令行安装 cordova 命令行帮助:http://cordova.apache.o ...

  8. Java | 基础归纳 | Map.Entry<String, String>

    public class Test { private static Map<String,String> student; private static void init() { st ...

  9. Codeforces Round #546 (Div. 2) B. Nastya Is Playing Computer Games

    链接:https://codeforces.com/contest/1136/problem/B 题意: 有n个井盖,每个井盖上有一个小石头. 给出n和k,k表示刚开始在第k个井盖上方. 有三种操作, ...

  10. js onclick=‘save()’ 和 onclick='return save()'

    onclick="function()" 表示只会执行 function , 但是不会传回 function 中之回传值onclick = "return functio ...