resnetV1.py 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. # D:/workplace/python
  2. # -*- coding: utf-8 -*-
  3. # @File :resnetV1.py
  4. # @Author:Guido LuXiaohao
  5. # @Date :2020/4/8
  6. # @Software:PyCharm
  7. """
  8. ResNet v1
  9. This is a revised implementation from Cifar10 ResNet example in Keras:
  10. (https://github.com/keras-team/keras/blob/master/examples/cifar10_resnet.py)
  11. [a] Deep Residual Learning for Image Recognition
  12. https://arxiv.org/pdf/1512.03385.pdf
  13. """
  14. from __future__ import print_function
  15. import keras
  16. from keras.layers import Dense, Conv2D, BatchNormalization, Activation
  17. from keras.layers import AveragePooling2D, Input, Flatten
  18. from keras.optimizers import Adam
  19. from keras.callbacks import ModelCheckpoint, LearningRateScheduler
  20. from keras.callbacks import ReduceLROnPlateau
  21. from keras.preprocessing.image import ImageDataGenerator
  22. from keras.regularizers import l2
  23. from keras import backend as K
  24. from keras.models import Model
  25. from nets.attention_module.se_cbam import attach_attention_module
  26. # 先定义一个神经层,再通过堆叠来完成,分为两个函数
  27. def resnet_layer(inputs,
  28. num_filters=16, # 输出通道数/深度
  29. kernel_size=3,
  30. strides=1,
  31. activation='relu',
  32. batch_normalization=True,
  33. conv_first=True):
  34. """2D Convolution-Batch Normalization-Activation stack builder
  35. # Arguments
  36. inputs (tensor): input tensor from input image or previous layer图像数据或者前一层神经网络的张量
  37. num_filters (int): Conv2D number of filters二维卷积核的个数
  38. kernel_size (int): Conv2D square kernel dimensions卷积核的大小
  39. strides (int): Conv2D square stride dimensions卷积核的滑动步长
  40. activation (string): activation name激活函数
  41. batch_normalization (bool): whether to include batch normalization是否使用批量归一化
  42. conv_first (bool): conv-bn-activation (True) or
  43. bn-activation-conv (False)
  44. # Returns
  45. x (tensor): tensor as input to the next layer
  46. """
  47. # 实例化一个卷积对象
  48. conv = Conv2D(num_filters,# 输出空间的维度(即卷积中滤波器的输出数量) #conv2d_ ,conv2d_13,conv2d_23
  49. kernel_size=kernel_size,
  50. strides=strides,
  51. padding='same',#padding设置为SAME,则说明输入图片大小和输出图片大小是一致的,如果是VALID则图片经过滤波器后可能会变小
  52. kernel_initializer='he_normal',
  53. kernel_regularizer=l2(1e-4))#该层权重矩阵的每个系数都会使网络总损失增加1e-4*weight_coefficient_value
  54. x = inputs
  55. # 定义卷积、批量标准化、激活
  56. if conv_first:
  57. x = conv(x)
  58. if batch_normalization:
  59. x = BatchNormalization()(x)
  60. if activation is not None:
  61. x = Activation(activation)(x)
  62. else:
  63. if batch_normalization:
  64. x = BatchNormalization()(x)
  65. if activation is not None:
  66. x = Activation(activation)(x)
  67. x = conv(x)
  68. return x
  69. def resnet_v1(input_shape, depth, num_classes=10, attention_module=None):
  70. """ResNet Version 1 Model builder [a]
  71. Stacks of 2 x (3 x 3) Conv2D-BN-ReLU
  72. Last ReLU is after the shortcut connection.
  73. At the beginning of each stage, the feature map size is halved (downsampled)
  74. by a convolutional layer with strides=2, while the number of filters is
  75. doubled. Within each stage, the layers have the same number filters and the
  76. same number of filters.
  77. Features maps sizes:
  78. stage 0: 32x32, 16
  79. stage 1: 16x16, 32
  80. stage 2: 8x8, 64
  81. The Number of parameters is approx the same as Table 6 of [a]:
  82. ResNet20 0.27M
  83. ResNet32 0.46M
  84. ResNet44 0.66M
  85. ResNet56 0.85M
  86. ResNet110 1.7M
  87. # Arguments
  88. input_shape (tensor): shape of input image tensor
  89. depth (int): number of core convolutional layers
  90. num_classes (int): number of classes (CIFAR10 has 10)
  91. # Returns
  92. model (Model): Keras model instance
  93. """
  94. if (depth - 2) % 6 != 0: #depth=20
  95. raise ValueError('depth should be 6n+2 (eg 20, 32, 44 in [a])')
  96. # Start model definition.
  97. num_filters = 16
  98. num_res_blocks = int((depth - 2) / 6) # 每个残差堆叠层含有的残差模块3
  99. inputs = Input(shape=input_shape) # 这部分返回一个张量,形状为input_shape, 要指定input_shape
  100. x = resnet_layer(inputs=inputs) # 其余都用自定义参数
  101. # Instantiate the stack of residual units实例化残差单元模块
  102. for stack in range(3): # 定义了三个残差堆叠层
  103. for res_block in range(num_res_blocks): # num_res_blocks = 3
  104. strides = 1
  105. if stack > 0 and res_block == 0: # first layer but not first stack 每个残差堆叠层的第一个残差模块,但不是第一个堆叠
  106. strides = 2 # downsample 在conv3_1, conv4_1下采样
  107. y = resnet_layer(inputs=x,
  108. num_filters=num_filters,
  109. strides=strides) # 有activation
  110. y = resnet_layer(inputs=y,
  111. num_filters=num_filters,
  112. activation=None)
  113. if stack > 0 and res_block == 0: # first layer but not first stack
  114. # linear projection residual shortcut connection to match
  115. # changed dims
  116. x = resnet_layer(inputs=x,
  117. num_filters=num_filters,
  118. kernel_size=1,
  119. strides=strides,#strides=1
  120. activation=None,
  121. batch_normalization=False)
  122. #以上为原来的resnet,下面是添加attention_module
  123. # attention_module
  124. if attention_module is not None:
  125. y = attach_attention_module(y, attention_module) # net:y
  126. x = keras.layers.add([x, y]) # add_2:Add 将输入feature和经过res_block的feature相加
  127. x = Activation('relu')(x) # activation_4:Activation
  128. num_filters *= 2
  129. # Add classifier on top.
  130. # v1 does not use BN after last shortcut connection-ReLU
  131. x = AveragePooling2D(pool_size=8)(x) #average_pooling2d_1:AveragePooling2D
  132. y = Flatten()(x) #flaten_1:Flatten
  133. outputs = Dense(num_classes, #dense19:Dense
  134. activation='softmax',
  135. kernel_initializer='he_normal')(y)
  136. #he_normal 它从[-limt,limt]的均匀分布中抽取样本,其中limit=sqrt(6 / fan_in), 其中`fan_in`是权值张量中输入单位个数
  137. # Instantiate model.
  138. model = Model(inputs=inputs, outputs=outputs)
  139. return model
  140. """
  141. 一般情况下, 输入的图片矩阵以及后面的卷积核, 特征图矩阵都是方阵, 这里设输入矩阵大小为 w, 卷积核大小为 k, 步幅为 s, 补零层数为 p, 则卷积后产生的特征图大小计算公式为:
  142. w'=(w+2p-k)/s+1
  143. """
  144. """
  145. resnet
  146. 每个 stack 中都含有 3 个残差模块res_block,每个模块的卷积核都是 3X3 大小的,pad 为 1,stride 为 1。
  147. Con4_x 的输出通过 global_average_pooling 映射到 64 个 1X1 大小的 feature map,最后再通过含有 10 个神经元的全连接层输出分类结果。
  148. """