VGG文章复现

VGG:Very Deep Convollutional Networks for Large-Scale Image Recognition

摘要:本文研究了卷积网络的深度对于图像识别任务的准确率的影响。本文的主要贡献:通过堆叠3x3卷积层增加网络深度,系统地研究了网络深度增加到16-19层的过程中性能的提升。上面的研究基于14年ImageNet比赛提交的模型(分类第一名,定位第二名)。另外,我们的模型泛化能力很好,在其它数据集上也取得了state of art。我们开源了两个性能最好的网络,以方便大家在计算机视觉上的进一步研究。
关键点:网络深度,性能

文章总结
系统研究了网络深度对性能的影响。顺便研究了LRN层对性能的影响。另外,VGG大量使用了3x3小卷积。

1. 简介

VGG为了研究了网络深度对性能的影响,在固定架构的其它参数的情况下,通过增加卷积层来逐渐增加网络的深度(整个网络使用的都是3x3卷积核)。作者也提到了,提取到的高层特征也可以使用SVM分类

2. 卷积网络配置

为了衡量深度带来的性能提升,所有的卷积网络层的配置完全一致。

输入:224x224x3
预处理:减去mean RGB值
网络可用组件:3x3卷积层;1x1卷积层;卷积的stride为1;卷积的padding为same以保证conv后分辨率不变;卷积的channel以2的倍数增加(从64开始,最高512);池化选择ksize为2x2stride为2的max-pooling。卷积后接一个三层FC:4096-4096-1000+softmax。整个网络使用ReLU激活函数。有一个网络版本含有LRN层。

下图是本文使用的网络的配置:
网络配置图


本文一共构建了6个模型(A-E):
A:(11层)8层conv,3层FC
A-LRN:(11层)在A上,增加1个LRN(放在第一个conv后)。
B:(13层)在B上,增加2层3x3 conv
C:(16层)在C上,增加3层1x1 conv
D:(16层)在B上,增加3层3x3 conv
E:(19层)在C上,增加3层3x3 conv

讨论
VGG在更深的情况下,以较少的参数量取得了比大卷积核浅层网络更好的性能。VGG的第一层不同于AlexNet和ZFNet(AlexNet:11x11 stride 2)(ZFNet:7x7 stride 2),VGG整个网络采用3x3 stride 1卷积。在没有池化时,两个3x3 filter的感受野等效于一个5x5 filter的感受野,3个3x3 filter可以等效1个7x7 filter的感受野。用小卷积核代替大卷积核有两个作用:1.增加了ReLU的个数,从而增加了模型非线性能力;2.减少了参数量;作者认为用3个3x3 conv代替1个7x7 conv,可以看做是对7x7 conv进行了正则。
在模型C中,使用了1x1卷积,它在不改变感受野大小的情况下,增加了模型的非线性。

3.网络在分类任务上的配置

训练
优化算法:mini-batch GD with momentum(0.9)
损失函数:Multinomial Logistic Regression损失函数推荐阅读内容
batch size:256
weight decay rate:5x 10 4
FC前两层的dropout rate:0.5
学习速率:开始设置为 10 2 ,当验证集上的误差停止下降时将学习速率降低为当前的十分之一。

在ImageNet上,训练过程中学习速率下降了3次,迭代了370k次(74epochs)

模型参数的初始化很重要,VGG使用训练好浅层网络的参数初始化更深网络部分层的参数,当然也可以使用Glorot & Bengio (2010)提出的Xavier参数初始化方法。

模型输入的224x224图像从rescaled的图像随机裁剪而来,并进行随机的水平翻转和随机RGB颜色变化。

rescale就是将图像重新调整大小

VGG的TensorFlow实现

#coding:utf-8
'''
下面对VGG文章中的A,A-LRN,B,C,D,E模型进行了实现。

通过更改inference的version参数就可以得到文中的不同深度及配置的模型。
'''
import tensorflow as tf
relu = tf.nn.relu


def print_activation(x):
  print(x.op.name, x.get_shape().as_list())

def inference(inputs,
              num_classes=1000,
              is_training=True,
              dropout_keep_prob=0.5,
              version='A'):
  '''
  inputs: a tensor of images
  num_classes: the num of category.
  is_training: set ture when it used for training
  dropout_keep_prob: the rate of dropout during training
  version: ['A','A-LRN','B','C','D','E']
  '''
  x = inputs
  print_activation(x)
  with tf.variable_scope('unit_1'):
    x = tf.layers.Conv2D(64, [3,3], padding='SAME', activation=relu)(x)
    print_activation(x)
    if version=='A-LRN':
      x = tf.nn.local_response_normalization(x, name='lrn')   
      print_activation(x)   
    elif version in ['B','C','D','E']:
      x = tf.layers.Conv2D(64, [3,3], padding='SAME', activation=relu)(x)
      print_activation(x)
    x = tf.layers.MaxPooling2D([2,2], [2,2], padding='SAME')(x)
    print_activation(x)
  with tf.variable_scope('unit_2'):
    x = tf.layers.Conv2D(128, [3,3], padding='SAME', activation=relu)(x)
    print_activation(x)
    if version in ['B','C','D','E']:
      x = tf.layers.Conv2D(128, [3,3], padding='SAME', activation=relu)(x)
      print_activation(x)
    x = tf.layers.MaxPooling2D([2,2], [2,2], padding='SAME')(x)
    print_activation(x)
  with tf.variable_scope('unit_3'):
    x = tf.layers.Conv2D(256, [3,3], padding='SAME', activation=relu)(x)
    print_activation(x)
    x = tf.layers.Conv2D(256, [3,3], padding='SAME', activation=relu)(x)
    print_activation(x)
    if version=='C':
      x = tf.layers.Conv2D(256, [1,1], padding='SAME', activation=relu)(x)
      print_activation(x)
    if version in ['D','E']:
      x = tf.layers.Conv2D(256, [3,3], padding='SAME', activation=relu)(x)
      print_activation(x)
    if version=='E':
      x = tf.layers.Conv2D(256, [3,3], padding='SAME', activation=relu)(x)
      print_activation(x)
    x = tf.layers.MaxPooling2D([2,2], [2,2], padding='SAME')(x)
    print_activation(x)
  with tf.variable_scope('unit_4'):
    x = tf.layers.Conv2D(512, [3,3], padding='SAME', activation=relu)(x)
    print_activation(x)
    x = tf.layers.Conv2D(512, [3,3], padding='SAME', activation=relu)(x)
    print_activation(x)
    if version=='C':
      x = tf.layers.Conv2D(512, [1,1], padding='SAME', activation=relu)(x)
      print_activation(x)
    if version in ['D','E']:
      x = tf.layers.Conv2D(512, [3,3], padding='SAME', activation=relu)(x)
      print_activation(x)
    if version=='E':
      x = tf.layers.Conv2D(512, [3,3], padding='SAME', activation=relu)(x)
      print_activation(x)
    x = tf.layers.MaxPooling2D([2,2], [2,2], padding='SAME')(x)
    print_activation(x)
  with tf.variable_scope('unit_5'):
    x = tf.layers.Conv2D(512, [3,3], padding='SAME', activation=relu)(x)
    print_activation(x)
    x = tf.layers.Conv2D(512, [3,3], padding='SAME', activation=relu)(x)
    print_activation(x)
    if version=='C':
      x = tf.layers.Conv2D(512, [1,1], padding='SAME', activation=relu)(x)
      print_activation(x)
    if version in ['D','E']:
      x = tf.layers.Conv2D(512, [3,3], padding='SAME', activation=relu)(x)
      print_activation(x)
    if version=='E':
      x = tf.layers.Conv2D(512, [3,3], padding='SAME', activation=relu)(x)
      print_activation(x)
    x = tf.layers.MaxPooling2D([2,2], [2,2], padding='SAME')(x)
    print_activation(x)
  with tf.variable_scope('fc'):
    x = tf.layers.Flatten()(x)
    x = tf.layers.Dense(4096)(x)
    print_activation(x)
    x = tf.layers.Dense(4096)(x)
    print_activation(x)
    logits = tf.layers.Dense(num_classes)(x)
    print_activation(logits)
  return logits
#下面是文章3.2节用conv代替FC的代码
#      x = tf.layers.Conv2D(4096, [7,7], activation=relu)(x)
#      print_activation(x)
#      x = tf.layers.Conv2D(4096, [1,1], activation=relu)(x)
#      print_activation(x)
#      logits = tf.layers.Conv2D(num_classes, [1,1], activation=relu)(x)
#      print_activation(logits)
#  return logits

if __name__ == '__main__':
  with tf.variable_scope('inputs'):
    images = tf.placeholder(tf.float32, [None,224,224,3])
    labels = tf.placeholder(tf.float32, [None, 1000])

  logits = inference(inputs=images, num_classes=1000, 
                     is_training=True, version='A')
  print('inference is ok!')

注意:使用本博客的代码,请添加引用

猜你喜欢

转载自blog.csdn.net/u014061630/article/details/80298932
VGG
今日推荐