VGG16

                    版权声明:本文为博主原创文章,未经博主允许不得转载。                        <a class="copy-right-url" href=" https://blog.csdn.net/loveliuzz/article/details/79135546"> https://blog.csdn.net/loveliuzz/article/details/79135546</a>
                </div>
                                                <link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-3019150162.css">
                                    <link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-3019150162.css">
            <div class="htmledit_views" id="content_views">

一、VGG-16网络框架介绍


VGGNet是牛津大学计算机视觉组(Visual Geometry Group)和Google DeepMind公司的研究员一起研发的深度卷积神经网络。

VGGNet探索了卷积神经网络的深度与其性能之间的关系,通过反复堆叠3*3的小型卷积核和2*2的最大池化层

VGGNet成功地构筑了16~19层深的卷积神经网络。VGGNet相比之前state-of-the-art的网络结构,错误率大幅下降, 

VGGNet论文中全部使用了3*3的小型卷积核和2*2的最大池化核,通过不断加深网络结构来提升性能。

VGG-16和VGG-19结构如下: 



总结:

(1)VGG-16网络中的16代表的含义为:含有参数的有16个层,共包含参数约为1.38亿。

(2)VGG-16网络结构很规整,没有那么多的超参数,专注于构建简单的网络,都是几个卷积层后面跟一个可以压缩

图像大小的池化层。即:全部使用3*3的小型卷积核和2*2的最大池化层

卷积层:CONV=3*3 filters, s = 1, padding = same convolution。

池化层:MAX_POOL = 2*2 , s = 2

(3)优点:简化了卷积神经网络的结构;缺点:训练的特征数量非常大。

(4)随着网络加深,图像的宽度和高度都在以一定的规律不断减小,

每次池化后刚好缩小一半,信道数目不断增加一倍

二、整体架构代码实现

用VGG_6.py文件实现前向传播过程以及网络的参数:


  1. #!/usr/bin/env python
  2. # -*- coding:utf-8 -*-
  3. # Author:ZhengzhengLiu
  4. import tensorflow as tf
  5. #VGG_16全部使用3*3卷积核和2*2的池化核
  6. #创建卷积层函数
  7. def conv_op(input_op,name,kh,kw,n_out,dh,dw,p):
  8. """
  9. param :
  10. input_op -- 输入tensor
  11. name -- 该层的名称
  12. kh -- 卷积核的高
  13. kw -- 卷积核的宽
  14. n_out -- 卷积核数目/输出通道数
  15. dh -- 步长的高
  16. dw -- 步长的宽
  17. p -- 参数(字典类型)
  18. return:
  19. A -- 卷积层的输出
  20. """
  21. n_in = input_op.get_shape()[-1].value #输入的通道数
  22. with tf.variable_scope(name) as scope:
  23. weights = tf.get_variable(name=scope+"w",shape=[kh,kw,n_in,n_out],dtype=tf.float32,
  24. initializer=tf.contrib.layers.xavier_initializer_con2d())
  25. biases = tf.get_variable(name=scope+"b",shape=[n_out],dtype=tf.float32,
  26. initializer=tf.constant_initializer(0.0),trainable=True)
  27. conv = tf.nn.conv2d(input=input_op,filter=weights,strides=[1,dh,dw,1],padding="SAME")
  28. Z = tf.nn.bias_add(conv,biases)
  29. A = tf.nn.relu(Z,name=scope)
  30. p[name+"w"] = weights
  31. p[name+"b"] = biases
  32. return A
  33. #创建最大池化层的函数
  34. def maxpool_op(input_op,name,kh,kw,dh,dw):
  35. """
  36. param :
  37. input_op -- 输入tensor
  38. name -- 该层的名称
  39. kh -- 池化核的高
  40. kw -- 池化核的宽
  41. dh -- 步长的高
  42. dw -- 步长的宽
  43. return:
  44. pool -- 该层的池化的object
  45. """
  46. pool = tf.nn.max_pool(input_op,ksize=[1,kh,kw,1],strides=[1,dh,dw,1],padding="SAME",name=name)
  47. return pool
  48. #创建全连接层的函数
  49. def fc_op(input_op,name,n_out,p):
  50. """
  51. param :
  52. input_op -- 输入tensor
  53. name -- 该层的名称
  54. n_out -- 输出通道数
  55. p -- 参数字典
  56. return:
  57. A -- 全连接层最后的输出
  58. """
  59. n_in = input_op.get_shape()[-1].value
  60. with tf.variable_scope(name) as scope:
  61. weights = tf.get_variable(name=scope+"w",shape=[n_in,n_out],dtype=tf.float32,
  62. initializer=tf.contrib.layers.xavier_initializer())
  63. # biases不再初始化为0,赋予一个较小的值,以避免dead neuron
  64. biases = tf.get_variable(name=scope+"b",shape=[n_out],dtype=tf.float32,
  65. initializer=tf.constant_initializer(0.1))
  66. #tf.nn.relu_layer对输入变量input_op与weights做矩阵乘法加上biases,再做非线性relu变换
  67. A = tf.nn.relu_layer(input_op,weights,biases,name=scope)
  68. p[name + "w"] = weights
  69. p[name + "b"] = biases
  70. return A
  71. #构建VGG_16网络的框架
  72. def VGG_16(input_op,keep_prob):
  73. """
  74. param :
  75. input_op -- 输入tensor
  76. keep_prob -- 控制dropout比率的占位符
  77. return:
  78. fc8 -- 最后一层全连接层
  79. softmax -- softmax分类
  80. prediction -- 预测
  81. p -- 参数字典
  82. """
  83. p = {} #初始化参数字典
  84. #第一段卷积网络——两个卷积层和一个最大池化层
  85. #两个卷积层的卷积核大小为3*3,卷积核数量均为64,步长s=1,输出均为:224*224*64
  86. conv1_1 = conv_op(input_op,name="conv1_1",kh=3,kw=3,n_out=64,dh=1,dw=1,p=p)
  87. conv1_2 = conv_op(conv1_1,name="conv1_2",kh=3,kw=3,n_out=64,dh=1,dw=1,p=p)
  88. #最大池化层采用的尺寸大小为:2*2,步长s=2,输出为:112*112*64
  89. pool1 = maxpool_op(conv1_2,name="pool1",kh=2,kw=2,dh=2,dw=2)
  90. # 第二段卷积网络——两个卷积层和一个最大池化层
  91. # 两个卷积层的卷积核大小为3*3,卷积核数量均为128,步长s=1,输出均为:112*112*128
  92. conv2_1 = conv_op(pool1,name="conv2_1",kh=3,kw=3,n_out=128,dh=1,dw=1,p=p)
  93. conv2_2 = conv_op(conv2_1,name="conv2_2",kh=3,kw=3,n_out=128,dh=1,dw=1,p=p)
  94. # 最大池化层采用的尺寸大小为:2*2,步长s=2,输出为:56*56*128
  95. pool2 = maxpool_op(conv2_2,name="pool2",kh=2,kw=2,dh=2,dw=2)
  96. # 第三段卷积网络——三个卷积层和一个最大池化层
  97. # 三个卷积层的卷积核大小为3*3,卷积核数量均为256,步长s=1,输出均为:56*56*256
  98. conv3_1 = conv_op(pool2,name="conv3_1",kh=3,kw=3,n_out=256,dh=1,dw=1,p=p)
  99. conv3_2 = conv_op(conv3_1,name="conv3_2",kh=3,kw=3,n_out=256,dh=1,dw=1,p=p)
  100. conv3_3 = conv_op(conv3_2,name="conv3_3",kh=3,kw=3,n_out=256,dh=1,dw=1,p=p)
  101. # 最大池化层采用的尺寸大小为:2*2,步长s=2,输出为:28*28*256
  102. pool3 = maxpool_op(conv3_3,name="pool3",kh=2,kw=2,dh=2,dw=2)
  103. # 第四段卷积网络——三个卷积层和一个最大池化层
  104. # 三个卷积层的卷积核大小为3*3,卷积核数量均为512,步长s=1,输出均为:28*28*512
  105. conv4_1 = conv_op(pool3, name="conv4_1", kh=3, kw=3, n_out=512, dh=1, dw=1, p=p)
  106. conv4_2 = conv_op(conv4_1, name="conv4_2", kh=3, kw=3, n_out=512, dh=1, dw=1, p=p)
  107. conv4_3 = conv_op(conv4_2, name="conv4_3", kh=3, kw=3, n_out=512, dh=1, dw=1, p=p)
  108. # 最大池化层采用的尺寸大小为:2*2,步长s=2,输出为:14*14*512
  109. pool4 = maxpool_op(conv4_3, name="pool4", kh=2, kw=2, dh=2, dw=2)
  110. # 第五段卷积网络——三个卷积层和一个最大池化层
  111. # 三个卷积层的卷积核大小为3*3,卷积核数量均为512,步长s=1,输出均为:14*14*512
  112. conv5_1 = conv_op(pool4, name="conv5_1", kh=3, kw=3, n_out=512, dh=1, dw=1, p=p)
  113. conv5_2 = conv_op(conv5_1, name="conv5_2", kh=3, kw=3, n_out=512, dh=1, dw=1, p=p)
  114. conv5_3 = conv_op(conv5_2, name="conv5_3", kh=3, kw=3, n_out=512, dh=1, dw=1, p=p)
  115. # 最大池化层采用的尺寸大小为:2*2,步长s=2,输出为:7*7*512
  116. pool5 = maxpool_op(conv5_3, name="pool5", kh=2, kw=2, dh=2, dw=2)
  117. # 第六、七段 —— 含4096个隐藏节点的全连接层及dropout
  118. pool5_shape = pool5.get_shape().as_list()
  119. flattened_shape = pool5_shape[1] * pool5_shape[2] * pool5_shape[3]
  120. dense = tf.reshape(pool5, shape=[-1, flattened_shape],name="dense") # 向量化
  121. fc6 = fc_op(dense,name="fc6",n_out=4096,p=p)
  122. fc6_drop = tf.nn.dropout(fc6,keep_prob=keep_prob,name="fc6_drop")
  123. fc7 = fc_op(fc6_drop, name="fc7", n_out=4096, p=p)
  124. fc7_drop = tf.nn.dropout(fc7, keep_prob=keep_prob, name="fc7_drop")
  125. #最后一层输出层含1000个节点,进行softmax分类
  126. fc8 = fc_op(fc7_drop,name="fc8",n_out=1000,p=p)
  127. softmax = tf.nn.softmax(fc8)
  128. prediction = tf.argmax(softmax,1)
  129. return prediction,softmax,fc8,psamsan

三、用slim实现VGG_16网络的代码如下:


  1. def vgg16(inputs):
  2. with slim.arg_scope([slim.conv2d, slim.fully_connected],
  3. activation_fn=tf.nn.relu,
  4. weights_initializer=tf.truncated_normal_initializer(0.0, 0.01),
  5. weights_regularizer=slim.l2_regularizer(0.0005)):
  6. net = slim.repeat(inputs, 2, slim.conv2d, 64, [3, 3], scope='conv1')
  7. net = slim.max_pool2d(net, [2, 2], scope='pool1')
  8. net = slim.repeat(net, 2, slim.conv2d, 128, [3, 3], scope='conv2')
  9. net = slim.max_pool2d(net, [2, 2], scope='pool2')
  10. net = slim.repeat(net, 3, slim.conv2d, 256, [3, 3], scope='conv3')
  11. net = slim.max_pool2d(net, [2, 2], scope='pool3')
  12. net = slim.repeat(net, 3, slim.conv2d, 512, [3, 3], scope='conv4')
  13. net = slim.max_pool2d(net, [2, 2], scope='pool4')
  14. net = slim.repeat(net, 3, slim.conv2d, 512, [3, 3], scope='conv5')
  15. net = slim.max_pool2d(net, [2, 2], scope='pool5')
  16. net = slim.fully_connected(net, 4096, scope='fc6')
  17. net = slim.dropout(net, 0.5, scope='dropout6')
  18. net = slim.fully_connected(net, 4096, scope='fc7')
  19. net = slim.dropout(net, 0.5, scope='dropout7')
  20. net = slim.fully_connected(net, 1000, activation_fn=None, scope='fc8')
  21. return net



posted @ 2019-08-03 22:46  core!  阅读(1430)  评论(0编辑  收藏  举报