[ MOOC课程学习 ] 人工智能实践:Tensorflow笔记_CH8_1复现已有的卷积神经网络

课程链接
相关资料:VGG 论文阅读笔记

VGG 论文阅读笔记

2015年发表于ICLR的《VERY DEEP CONVOLUTIONAL NETWORKS FORLARGE-SCALE IMAGE RECOGNITION》

  1. 卷积配置
    为凸显深度对模型效果的影响,我们所有卷积采用相同配置。本章先介绍卷积网络的通用架构,再描述其评估中的具体细节,最后讨论我们的设计选择以及前人网络的比较。
    1.1 架构
    (1) 训练输入:固定尺寸224*224的RGB图像。
    (2) 预处理:每个像素值减去训练集上的RGB均值。
    (3) 卷积核:一系列3*3卷积核堆叠,步长为1,采用padding保持卷积后图像空间分辨率不变。
    (4) 空间池化:紧随卷积“堆”的最大池化,为2*2滑动窗口,步长为2。
    (5) 全连接层:特征提取完成后,接三个全连接层,前两个为4096通道,第三个为1000通道,最后是一个soft-max层,输出概率。
    (6) 所有隐藏层都用非线性修正ReLu。
    1.2 详细配置
    (1) 表1中每列代表不同的网络,只有深度不同(层数计算不包含池化层)。卷积的通道数量很小,第一层仅64通道,每经过一次最大池化,通道数翻倍,知道数量达到512通道。
    ConvNet configurations
    (2) 表2展示了每种模型的参数数量,尽管网络加深,但权重并未大幅增加,因为参数量主要集中在全连接层。
    Number of parameters
    每种模型的参数数量计算:
    1.3 讨论
    为什么?两个 3 × 3 卷积核相当于一个 5 × 5 卷积核的感受域,三个 3 × 3 卷积核相当于一个 7 × 7 卷积核的感受域。
    优点:三个卷积堆叠具有三个非线性修正层,使模型更具判别性;其次三个 3 × 3 卷积参数量更少,相当于在 7 × 7 卷积核上加入了正则化。
  2. 分类框架
    2.1 训练
    训练方法基本与AlexNet一致,除了多尺度训练图像采样方法不一致。
    训练采用mini-batch梯度下降法,batch size=256;
    采用动量优化算法,momentum=0.9;
    采用L2正则化方法,惩罚系数0.00005;
    dropout比率设为0.5;
    初始学习率为0.001,当验证集准确率不再提高时,学习率衰减为原来的0.1倍,总共下降三次;
    总迭代次数为370K(74epochs);
    数据增强采用随机裁剪,水平翻转,RGB颜色变化;
    设置训练图片大小的两种方法:
    定义S代表经过各向同性缩放的训练图像的最小边。
    第一种方法针对单尺寸图像训练,S=256或384,输入图片从中随机裁剪224*224大小的图片,原则上S可以取任意不小于224的值。
    第二种方法是多尺度训练,每张图像单独从[S min ,S max ]中随机选取S来进行尺寸缩放,由于图像中目标物体尺寸不定,因此训练中采用这种方法是有效的,可看作一种尺寸抖动的训练集数据增强。

    论文中提到,网络权重的初始化非常重要,由于深度网络梯度的不稳定性,不合适的初始化会阻碍网络的学习。因此我们先训练浅层网络,再用训练好的浅层网络去初始化深层网络。
    2.2 测试
    测试阶段,对于已训练好的卷积网络和一张输入图像,采用以下方法分类:
    首先,图像的最小边被各向同性的缩放到预定尺寸Q;
    然后,将原先的全连接层改换成卷积层,在未裁剪的全图像上运用卷积网络,输出是一个与输入图像尺寸相关的分类得分图,输出通道数与类别数相同;
    最后,对分类得分图进行空间平均化,得到固定尺寸的分类得分向量。
    我们同样对测试集做数据增强,采用水平翻转,最终取原始图像和翻转图像的soft-max分类概率的平均值作为最终得分。由于测试阶段采用全卷积网络,无需对输入图像进行裁剪,相对于多重裁剪效率会更高。但多重裁剪评估和运用全卷积的密集评估是互补的,有助于性能提升。
  3. 分类实验
    3.1单尺寸评估
    表3展示单一测试尺寸上的卷积网络性能
    T3
    3.2多尺寸评估
    表4展示多个测试尺寸上的卷积网络性能
    T4
    3.3 多重裁剪与密集网络评估
    表 5 展示多重裁剪与密集网络对比,并展示两者相融合的效果
    T5
    3.4 卷积模型的融合
    这部分探讨不同模型融合的性能,计算多个模型的 soft-max 分类概率的平均值来对它们的输出进行组合,由于模型的互补性,性能有所提高,这也用于比赛的最佳结果中。
    表 6 展示多个卷积网络融合的结果
    T6
    3.5 与当前最好算法的比较
    表七展示对当前最好算法的对比
    T7
  4. 结论
    本文评估了非常深的卷积网络在大规模图像分类上的性能。结果表明深度有利于分类准确率的提升。附录中展示了模型的泛化能力,再次确认了视觉表达中深度的重要性。

VGG 实现代码重点讲解

  1. item(): 遍历(键值对)。class ndarray的一个方法
  2. tf.shape(a)a.get_shape()比较
    相同点:都可以得到 tensor a 的尺寸
    不同点:
    (1) tf.shape() 中 a 的数据类型可以是 tensor, list, array,并且返回的是 tensor

    import tensorflow as tf
    import numpy as np
    x=tf.constant([[1,2,3],[4,5,6]])
    y=[[1,2,3],[4,5,6]]
    z=np.arange(24).reshape([2,3,4])
    sess=tf.Session()
    
    x_shape=tf.shape(x)
    y_shape=tf.shape(y)
    z_shape=tf.shape(z)
    
    print(x_shape) # Tensor("Shape:0", shape=(2,), dtype=int32)
    print(y_shape) # Tensor("Shape_1:0", shape=(2,), dtype=int32)
    print(z_shape) # Tensor("Shape_2:0", shape=(3,), dtype=int32)
    print(sess.run(x_shape)) # [2 3]
    print(sess.run(y_shape)) # [2 3]
    print(sess.run(z_shape)) # [2 3 4]

    (2) a.get_shape()中 a 的数据类型只能是 tensor,且返回的是一个元组(tuple)。

    import tensorflow as tf
    import numpy as np
    x=tf.constant([[1,2,3],[4,5,6]])
    y=[[1,2,3],[4,5,6]]
    z=np.arange(24).reshape([2,3,4])
    sess=tf.Session()
    
    x_shape=x.get_shape()
    print(x_shape) # (2, 3)
    
    y_shape=y.get_shape()
    print(y_shape) # AttributeError: 'list' object has no attribute 'get_shape'
    
    z_shape=z.get_shape()
    print(z_shape) # AttributeError: 'numpy.ndarray' object has no attribute 'get_shape'
    
  3. tf.nn.bias_add(乘加和,bias):把 bias 加到乘加和上。
  4. np.argsort(列表):对列表从小到大排序。
  5. os.getcwd():返回当前工作目录。
  6. np.save("name.npy",某数组):将某数组写入“name.npy”文件,如果文件路径末尾没有扩展名.npy,该扩展名会被自动加上。某变量 = np.load("name.npy",encoding = " ").item():将“name.npy”文件读出给某变量。encoding = ” “可以不写‘latin1’、‘ASCII’、‘bytes’,默认为’ASCII’。
  7. tf.split(value, num_or_size_splits, axis=0, num=None, name="split")

    def split(value, num_or_size_splits, axis=0, num=None, name="split"):
      """Splits a tensor into sub tensors.
    
      If `num_or_size_splits` is an integer type, `num_split`, then splits `value`
      along dimension `axis` into `num_split` smaller tensors.
      Requires that `num_split` evenly divides `value.shape[axis]`.
    
      If `num_or_size_splits` is not an integer type, it is presumed to be a Tensor
      `size_splits`, then splits `value` into `len(size_splits)` pieces. The shape
      of the `i`-th piece has the same size as the `value` except along dimension
      `axis` where the size is `size_splits[i]`.
    
      For example:
    
      ```python
      # 'value' is a tensor with shape [5, 30]
      # Split 'value' into 3 tensors with sizes [4, 15, 11] along dimension 1
      split0, split1, split2 = tf.split(value, [4, 15, 11], 1)
      tf.shape(split0)  # [5, 4]
      tf.shape(split1)  # [5, 15]
      tf.shape(split2)  # [5, 11]
      # Split 'value' into 3 tensors along dimension 1
      split0, split1, split2 = tf.split(value, num_or_size_splits=3, axis=1)
      tf.shape(split0)  # [5, 10]
      ```
    
      Args:
        value: The `Tensor` to split.
        num_or_size_splits: Either a 0-D integer `Tensor` indicating the number of
          splits along split_dim or a 1-D integer `Tensor` integer tensor containing
          the sizes of each output tensor along split_dim. If a scalar then it must
          evenly divide `value.shape[axis]`; otherwise the sum of sizes along the
          split dimension must match that of the `value`.
        axis: A 0-D `int32` `Tensor`. The dimension along which to split.
          Must be in the range `[-rank(value), rank(value))`. Defaults to 0.
        num: Optional, used to specify the number of outputs when it cannot be
          inferred from the shape of `size_splits`.
        name: A name for the operation (optional).
    
      Returns:
        if `num_or_size_splits` is a scalar returns `num_or_size_splits` `Tensor`
        objects; if `num_or_size_splits` is a 1-D Tensor returns
        `num_or_size_splits.get_shape[0]` `Tensor` objects resulting from splitting
        `value`.
    
      Raises:
        ValueError: If `num` is unspecified and cannot be inferred.
      """
  8. tf.concat(values, axis, name="concat")

    def concat(values, axis, name="concat"):
      """Concatenates tensors along one dimension.
    
      Concatenates the list of tensors `values` along dimension `axis`.  If
      `values[i].shape = [D0, D1, ... Daxis(i), ...Dn]`, the concatenated
      result has shape
    
          [D0, D1, ... Raxis, ...Dn]
    
      where
    
          Raxis = sum(Daxis(i))
    
      That is, the data from the input tensors is joined along the `axis`
      dimension.
    
      The number of dimensions of the input tensors must match, and all dimensions
      except `axis` must be equal.
    
      For example:
    
      ```python
      t1 = [[1, 2, 3], [4, 5, 6]]
      t2 = [[7, 8, 9], [10, 11, 12]]
      tf.concat([t1, t2], 0)  # [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]
      tf.concat([t1, t2], 1)  # [[1, 2, 3, 7, 8, 9], [4, 5, 6, 10, 11, 12]]
    
      # tensor t3 with shape [2, 3]
      # tensor t4 with shape [2, 3]
      tf.shape(tf.concat([t3, t4], 0))  # [4, 3]
      tf.shape(tf.concat([t3, t4], 1))  # [2, 6]
      ```
    
      Note: If you are concatenating along a new axis consider using stack.
      E.g.
    
      ```python
      tf.concat([tf.expand_dims(t, axis) for t in tensors], axis)
      ```
    
      can be rewritten as
    
      ```python
      tf.stack(tensors, axis=axis)
      ```
    
      Args:
        values: A list of `Tensor` objects or a single `Tensor`.
        axis: 0-D `int32` `Tensor`.  Dimension along which to concatenate. Must be
          in the range `[-rank(values), rank(values))`.
        name: A name for the operation (optional).
    
      Returns:
        A `Tensor` resulting from concatenation of the input tensors.
      """
  9. 绘图

    
    # 绘图
    
    fig = plt.figure("图名字") # 实例化图对象。
    ax = fig.add_subplot(mnk) # 将画布分割成 m 行 n 列,图像画在从左到右从上到下的第 k 块。
    ax.plot(x,y)
    plt.show()
    
    axo = imshow(图) # 画子图
    img = io.imread(图片路径) # 读入图片

VGG源码包含的文件

  • app.py 读入待判图,给出可视化结果
  • vgg16.py 还原网络和参数
  • utils.py 一些辅助函数,包括
    • 读入图片
    • 计算百分比形式的概率
  • Nclasses.py 含labels字典
  • vgg16.npy 包含了神经网络的所有参数 (Table1里编号为D的网络结构)

猜你喜欢

转载自blog.csdn.net/RanMW1129/article/details/81139884