VggNet简介

VGG是在2014年由牛津大学著名研究组VGG提出,战火概念ImageNet竞赛中LocalizationTask(定位任务)第一名和Classification Task(分类任务)第二名

关于神经网络中的一些自己还尚不能理解的一些关键步骤的解释

神经网络初始化权重的作用

初始化权重的作用是放置神经网络的正向(前向)传播过程中层激活函数的输出损失梯度出现爆炸或者小时,发生任何一种情况,损失梯度太大或者太小,就无法有效向后反传,即便可以向后反传,网络也需要花费更长的时间来达到收敛。这是十分重要的一部,虽然目前欠缺数学的基础知识,希望这个问题可以在以后的学习过程中得到解决。

对于深度学习代码tensor数据结构的理解

在很多的深度学习的代码中,我们经常见到将数组结构的数组转化为tensor格式的数据的操作
原因是:tensor数据类型是专门为GPU加速而设计的矩阵,而普通的数据结构不行,其实就可理解为是一个专门为GPU设计的数据结构,可以使模型的训练更加迅速。

VggNet网络的结构

感受野的定义

在卷积神经网络中,决定某一层输出结果中一个元素所对应的输入层的区域大小,被称作感受野,通俗来讲就是输出的feature map上的一个单元对应输出层上的区域大小

卷积层的基本的运算公式

image.png

  • out为输出的神经元的大小
  • in为输入神经元的大小
  • F表示卷积核的大小
  • P表示padding参数的大小
  • S表示stride步长参数的大小

    感受野的计算公式

    image.png

  • F(i)表示第i层的感受野的大小

  • Stride为第i层的步距的大小
  • Ksize表示卷积核或池化核的大小

根据该公式可以推导出每一层的感受野的大小

在VGG网络中卷积核的默认的布局是1
使用多个卷积核的感受野的堆叠来代替一个大的感受野的参数,是为了减少网络的训练参数的个数

关于一些参数的作用效果的表示

image.png
根据改图可以很清除的看出来,在卷积层的stride和padding参数都设置为1的时候,输出的数据的大小是与原来输出的大小相一致的,深度为卷积核的数目大小
maxpooling最大下采样的层数的size和stride的参数均设置为2的时候的输出的数据的长和宽都会变成原来的一半,深度变为最大下采样层的采样核的大小
有利于初学者对于卷积层和最大下采样层的参数有更加详细的理解

关于VGG卷积神经网络的每一层

image.png

VGG网络结构搭建的代码展示

  1. import torch.nn as nn
  2. import torch
  3. # official pretrain weights
  4. model_urls = {
  5. 'vgg11': 'https://download.pytorch.org/models/vgg11-bbd30ac9.pth',
  6. 'vgg13': 'https://download.pytorch.org/models/vgg13-c768596a.pth',
  7. 'vgg16': 'https://download.pytorch.org/models/vgg16-397923af.pth',
  8. 'vgg19': 'https://download.pytorch.org/models/vgg19-dcbb9e9d.pth'
  9. }
  10. #VGG类的定义
  11. class VGG(nn.Module):
  12. def __init__(self, features, num_classes=1000, init_weights=False):
  13. super(VGG, self).__init__()
  14. self.features = features
  15. self.classifier = nn.Sequential(
  16. nn.Linear(512*7*7, 4096),
  17. nn.ReLU(True),
  18. nn.Dropout(p=0.5),
  19. nn.Linear(4096, 4096),
  20. nn.ReLU(True),
  21. nn.Dropout(p=0.5),
  22. nn.Linear(4096, num_classes)
  23. )
  24. if init_weights:
  25. self._initialize_weights()
  26. #定义数据的传播方向
  27. def forward(self, x):
  28. # N x 3 x 224 x 224
  29. x = self.features(x)
  30. # N x 512 x 7 x 7
  31. x = torch.flatten(x, start_dim=1)
  32. # N x 512*7*7
  33. x = self.classifier(x)
  34. return x
  35. #初始化权重函数
  36. def _initialize_weights(self):
  37. for m in self.modules():
  38. if isinstance(m, nn.Conv2d):
  39. # nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
  40. nn.init.xavier_uniform_(m.weight)
  41. if m.bias is not None:
  42. nn.init.constant_(m.bias, 0)
  43. elif isinstance(m, nn.Linear):
  44. nn.init.xavier_uniform_(m.weight)
  45. # nn.init.normal_(m.weight, 0, 0.01)
  46. nn.init.constant_(m.bias, 0)
  47. #特征提取模块的函数的定义
  48. def make_features(cfg: list):
  49. layers = []
  50. in_channels = 3
  51. for v in cfg:
  52. if v == "M":
  53. layers += [nn.MaxPool2d(kernel_size=2, stride=2)]
  54. else:
  55. conv2d = nn.Conv2d(in_channels, v, kernel_size=3, padding=1)
  56. layers += [conv2d, nn.ReLU(True)]
  57. in_channels = v
  58. return nn.Sequential(*layers)
  59. #特征提取模型的每一层的参数
  60. cfgs = {
  61. 'vgg11': [64, 'M', 128, 'M', 256, 256, 'M', 512, 512, 'M', 512, 512, 'M'],
  62. 'vgg13': [64, 64, 'M', 128, 128, 'M', 256, 256, 'M', 512, 512, 'M', 512, 512, 'M'],
  63. 'vgg16': [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 'M', 512, 512, 512, 'M', 512, 512, 512, 'M'],
  64. 'vgg19': [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 256, 'M', 512, 512, 512, 512, 'M', 512, 512, 512, 512, 'M'],
  65. }
  66. #vgg模型的选择函数
  67. def vgg(model_name="vgg16", **kwargs):
  68. assert model_name in cfgs, "Warning: model number {} not in cfgs dict!".format(model_name)
  69. cfg = cfgs[model_name]
  70. model = VGG(make_features(cfg), **kwargs)
  71. return model

学习到现在,神经网络的每一层的每一个参数都至少见过和使用过两次了,都至少介绍过一次,已经对神经网络的基本构架有了不错的理解。