VERY DEEP CONVOLUTIONAL NETWORKS
FOR LARGE-SCALE IMAGE RECOGNITION
该文章介绍了基于深度卷积神经网络的大规模图像分类(经典网络),验证了卷积神经网络的深度对大规模图像分类准确率的影响。
作者:Karen Simonyan & Andrew Zisserman
单位:牛津大学(Visual Geometry Group)
论文地址
自从2012年AlexNet将深度学习的方法应用 ImageNet的图像分类比赛中并取得state of the art的惊人结果后,大家开始相仿并在此基础上进行大量尝试和改进。
1. 小卷积核
在第一个卷积层用了更小的卷积核和卷积stride
2. 多尺度
训练和测试使用整张图的不同尺度
vgg作者不仅将上面的两种方法应用到自己的网络设计和训练测试阶段,同时还考虑了网络深度对结果的影响。
2014年在ILSVRC比赛中获得了分类项目的第二名(第一名是GoogLeNet),和定位项目的第一名。同时模型对其他数据集有很好的泛化能力。
VGG由于其结果简单,提取特征能力强,所以应用场景广泛。
例如:快速风格迁移算法,目标检测的backbone,提取特征(faster rcnn, ssd等),gan网络内容特征提取,进行内容计算(内容损失是gan网络损失的一部分)。
进行了6组对比实验,如下图所示,包括A,A-LRN,B,C,D,E六种不同的网络结构。其中A-LRN网络在A网络的基础上加入了LRN层,B网络在A-LRN网络基础上加入了两个3x3卷积层,C网络在B网络基础上又加入了3个1x1卷积,D网络将C网络中的1x1卷积换成了3x3卷积,E网络又在D网络的基础上加入了3个3x3卷积。
单尺度测试结果对比
结论
:
结论:
dense evaluation & multi-crop两种测试方法联合使用效果最好模型融合结果对比
结论:
融合模型D和E之后模型错误率进一步下降
与其他网络结果对比
结论:
GoogLeNet分类效果冠军,VGG亚军优于其他网络。
感受野(Receptive Field)的定义是卷积神经网络每一层输出的特征图(feature map)上的像素点在输入图片上映射的区域大小。再通俗点的解释是,特征图上的一个点跟原图上有关系的点的区域。
感受野概念为什么重要?
感受野被称作是CNN最重要的概念之一,目标检测的流行算法比如SSD,Faster-Rcnn等中prior box和Anchor box的设计都是以感受野为依据进行的设计。
输入原始图大小为7x7,
conv1: 3x3 strides=1 valid
feature: (7-3+1) / 1 = 5
conv2: 3x3 strides=1 valid
feature: (5-3+1) / 1 = 3
原始输入感受野:1
conv1层感受野:3
conv2层感受野:5
思考:
如果conv1: 5x5 strides=1 valid 感受野是多少?
答:感受野为5
结论
1个5x5卷积核感受野大小与2个3x3卷积核的感受野等效,以此类推三个3x3的卷积核的感受野与一个7x7卷积核的感受野等效。
注意:这只是理论感受野,实际上起作用的感受野是小于理论感受野
本文研究了在大规模图片识别中,卷积神经网络的深度对准确率的影响。我们的主要贡献是通过非常小的3x3卷积核的神经网络架构全面评估了增加深度对网络的影响,结果表明16-19层的网络可以使现有设置的网络性能得到显著提高。这项发现是我们在2014年的ImageNet比赛中提交方案的基础,我们的团队分别在定位和分类中获得了第一和第二的成绩。我们还证明了此模型可以泛化到其他数据集上,并达到当前最佳水平。我们已经公布了两个性能最佳的卷积神经网络模型(vgg16和vgg19),以便深度视觉在计算机视觉中的进一步研究。
Q1: 为什么使用3x3的卷积核?
训练数据处理
论文中写道"Let S be the smallest side of an isotropically-rescaled training images"各向同性地缩放训练图像最小边。
以S=256为例
多尺度数据
数据增强demo
import numpy as np
from PIL import Image
S = 256
crop_size = 224
image_path = 'test.jpg'
image = Image.open(image_path)
image_w, image_h = image.size
# 各向同性缩放,最小边为256
scale = S / min(image_w, image_h)
scale_w = np.int(image_w * scale)
scale_h = np.int(image_h * scale)
print(scale_w, scale_h)
resize_image = image.resize((scale_w, scale_h), Image.BICUBIC) # 使用线性插值方式进行缩放
# 图像裁剪
max_offset_width = np.random.randint(low=0, high=scale_w-crop_size+1, dtype='int32')
max_offset_height = np.random.randint(low=0, high=scale_h-crop_size+1, dtype='int32')
crop_image = resize_image.crop((max_offset_width, max_offset_height,
max_offset_width+crop_size, max_offset_height+crop_size))
print(crop_image.size)
# 图像变换
transpose_image = crop_image.transpose(Image.FLIP_LEFT_RIGHT) # 水平翻转
r, g, b = transpose_image.split() # 分离图像三个通道
pic = Image.merge('RGB', (g, r, b)) # 交换g,r通道
image.show()
pic.show()
批量大小:batchsize=256
权重衰减:weight decay= 5 ∗ 1 0 − 4 5*10^{-4} 5∗10−4
学习率:learning rate=0.01 衰减因子为0.1
动量:momentum=0.9(优化方式为带动量的SGD)
迭代步数:370K
迭代轮数:epochs=75
卷积核初始化方式:均值为0,方差为1的高斯分布(深层网络使用浅层网络权重初始化)
偏置初始化方式:初始化为0
全连接层初始化方式:高斯分布(std=0.005), bias常数初始化(0.1)
卷积层替换全连接层
全连接层的计算公式: f c = w T x + b f_c = w^Tx+b fc=wTx+b
假设输入到全连接层特征大小为7*7*5,输出的特征大小为1000*1
首先将输入特征变为一个列向量
7*7*5 ------> (245, 1)
则x大小为(245, 1)
然后与全连接层的权重相乘,偏置相加
w的大小为(245, 1000)
b的大小为(1000, 1)
假如测试时输入到全连接层的特征大小为14*14*5,我们需要输出的特征大小依旧为1000*1,x大小变为(980, 1)
而此时的w大小为(245, 1000)
就会出现尺寸不匹配问题。
如果使用卷积层,使用1000个7*7*5的卷积代替fc层,卷积参数量为7*7*5*1000=245*1000,与fc层参数量相同,所以可以将fc层学习到的参数赋给卷积层。
假设输入特征为7*7*5,令strides=1,最后输出尺寸为[1, 1, 1, 1000]可以降维为[1, 1000];如果输入特征为14*14*5,最后得到特征为[1, 2, 2, 1000]即为一个scoremap,我们对他求平均得到[1, 1000]向量
简单描述:使用预训练的神经网络模型,来训练我们自己的数据集合,即使用训练好的权重来初始化我们的网络,并不是随机初始化。在实践中中我们通常不会完全从头开始随机初始化训练DCNN,这是因为有能满足深度网络需求的足够大小的数据集相当少见。作为代替,常见的是在一个大型数据集上预训练DCNN,然后使用这一训练的DCNN权重作为初始设置或作为相关任务的固定的特征提取器。
什么情况下使用?
自己设计的网络不好用,精度太低
数据集合相似,但数据量小
自己的计算资源不够
为什么微调会有效?
神经网络浅层学习的是通用特征即基础特征,比如边缘、轮廓颜色等特征。深层是针对特定数据的更抽象的特征,对于人脸来说可能就是某个人的脸。全连接层就是就是对特征进行组合并评分分类。我们可以利用网络的前几层学习到的通用特征,仅让网络学习数据的抽象特征,节省资源和时间。
迁移学习策略取决于多种因素,但最重要的两个是新数据集的大小以及新数据集与原数据集的相似度。以下是4个主要情景: