欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

VGG论文笔记

程序员文章站 2024-03-15 09:21:23
...

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层。

下图是本文使用的网络的配置:
VGG论文笔记


本文一共构建了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:5x104
FC前两层的dropout rate:0.5
学习速率:开始设置为102,当验证集上的误差停止下降时将学习速率降低为当前的十分之一。

在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!')

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

上一篇: Maxout论文笔记

下一篇: