VGG

VGG是当前最流行的CNN模型之一,2014年由Simonyan和Zisserman提出,其命名来源于论文作者所在的实验室Visual Geometry Group。AlexNet模型通过构造多层网络,取得了较好的效果,但是并没有给出深度神经网络设计的方向。VGG通过使用一系列大小为3x3的小尺寸卷积核和pooling层构造深度卷积神经网络,并取得了较好的效果。VGG模型因为结构简单、应用性极强而广受研究者欢迎,尤其是它的网络结构设计方法,为构建深度神经网络提供了方向。

图3 是VGG-16的网络结构示意图,有13层卷积和3层全连接层。VGG网络的设计严格使用

VGG - 图1 的卷积层和池化层来提取特征,并在网络的最后面使用三层全连接层,将最后一层全连接层的输出作为分类的预测。 在VGG中每层卷积将使用ReLU作为激活函数,在全连接层之后添加dropout来抑制过拟合。使用小的卷积核能够有效地减少参数的个数,使得训练和测试变得更加有效。比如使用两层 VGG - 图2 卷积层,可以得到感受野为5的特征图,而比使用 VGG - 图3 的卷积层需要更少的参数。由于卷积核比较小,可以堆叠更多的卷积层,加深网络的深度,这对于图像分类任务来说是有利的。VGG模型的成功证明了增加网络的深度,可以更好的学习图像中的特征模式。

VGG - 图4

图3:VGG模型网络结构示意图

VGG在眼疾识别数据集iChallenge-PM上的具体实现如下代码所示:

  1. # -*- coding:utf-8 -*-
  2. # VGG模型代码
  3. import numpy as np
  4. import paddle
  5. import paddle.fluid as fluid
  6. from paddle.fluid.layer_helper import LayerHelper
  7. from paddle.fluid.dygraph.nn import Conv2D, Pool2D, BatchNorm, Linear
  8. from paddle.fluid.dygraph.base import to_variable
  9. # 定义vgg块,包含多层卷积和1层2x2的最大池化层
  10. class vgg_block(fluid.dygraph.Layer):
  11. def __init__(self, name_scope, num_convs, in_channels, out_channels):
  12. """
  13. num_convs, 卷积层的数目
  14. num_channels, 卷积层的输出通道数,在同一个Incepition块内,卷积层输出通道数是一样的
  15. """
  16. super(vgg_block, self).__init__(name_scope)
  17. self.conv_list = []
  18. for i in range(num_convs):
  19. conv_layer = self.add_sublayer('conv_' + str(i), Conv2D(num_channels=in_channels,
  20. num_filters=out_channels, filter_size=3, padding=1, act='relu'))
  21. self.conv_list.append(conv_layer)
  22. in_channels = out_channels
  23. self.pool = Pool2D(pool_stride=2, pool_size = 2, pool_type='max')
  24. def forward(self, x):
  25. for item in self.conv_list:
  26. x = item(x)
  27. return self.pool(x)
  28. class VGG(fluid.dygraph.Layer):
  29. def __init__(self, name_scope, conv_arch=((2, 64),
  30. (2, 128), (3, 256), (3, 512), (3, 512))):
  31. super(VGG, self).__init__(name_scope)
  32. self.vgg_blocks=[]
  33. iter_id = 0
  34. # 添加vgg_block
  35. # 这里一共5个vgg_block,每个block里面的卷积层数目和输出通道数由conv_arch指定
  36. in_channels = [3, 64, 128, 256, 512, 512]
  37. for (num_convs, num_channels) in conv_arch:
  38. block = self.add_sublayer('block_' + str(iter_id),
  39. vgg_block(self.full_name(), num_convs, in_channels=in_channels[iter_id],
  40. out_channels=num_channels))
  41. self.vgg_blocks.append(block)
  42. iter_id += 1
  43. self.fc1 = Linear(input_dim=512*7*7, output_dim=4096,
  44. act='relu')
  45. self.drop1_ratio = 0.5
  46. self.fc2= Linear(input_dim=4096, output_dim=4096,
  47. act='relu')
  48. self.drop2_ratio = 0.5
  49. self.fc3 = Linear(input_dim=4096, output_dim=1)
  50. def forward(self, x):
  51. for item in self.vgg_blocks:
  52. x = item(x)
  53. x = fluid.layers.reshape(x, [x.shape[0], -1])
  54. x = fluid.layers.dropout(self.fc1(x), self.drop1_ratio)
  55. x = fluid.layers.dropout(self.fc2(x), self.drop2_ratio)
  56. x = self.fc3(x)
  57. return x
  1. with fluid.dygraph.guard():
  2. model = VGG("VGG")
  3. train(model)

通过运行结果可以发现,在眼疾筛查数据集iChallenge-PM上使用VGG,loss能有效的下降,经过5个epoch的训练,在验证集上的准确率可以达到94%左右。