123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168 |
- # D:/workplace/python
- # -*- coding: utf-8 -*-
- # @File :resnetV1.py
- # @Author:Guido LuXiaohao
- # @Date :2020/4/8
- # @Software:PyCharm
- """
- ResNet v1
- This is a revised implementation from Cifar10 ResNet example in Keras:
- (https://github.com/keras-team/keras/blob/master/examples/cifar10_resnet.py)
- [a] Deep Residual Learning for Image Recognition
- https://arxiv.org/pdf/1512.03385.pdf
- """
- from __future__ import print_function
- import keras
- from keras.layers import Dense, Conv2D, BatchNormalization, Activation
- from keras.layers import AveragePooling2D, Input, Flatten
- from keras.optimizers import Adam
- from keras.callbacks import ModelCheckpoint, LearningRateScheduler
- from keras.callbacks import ReduceLROnPlateau
- from keras.preprocessing.image import ImageDataGenerator
- from keras.regularizers import l2
- from keras import backend as K
- from keras.models import Model
- from nets.attention_module.se_cbam import attach_attention_module
- # 先定义一个神经层,再通过堆叠来完成,分为两个函数
- def resnet_layer(inputs,
- num_filters=16, # 输出通道数/深度
- kernel_size=3,
- strides=1,
- activation='relu',
- batch_normalization=True,
- conv_first=True):
- """2D Convolution-Batch Normalization-Activation stack builder
- # Arguments
- inputs (tensor): input tensor from input image or previous layer图像数据或者前一层神经网络的张量
- num_filters (int): Conv2D number of filters二维卷积核的个数
- kernel_size (int): Conv2D square kernel dimensions卷积核的大小
- strides (int): Conv2D square stride dimensions卷积核的滑动步长
- activation (string): activation name激活函数
- batch_normalization (bool): whether to include batch normalization是否使用批量归一化
- conv_first (bool): conv-bn-activation (True) or
- bn-activation-conv (False)
- # Returns
- x (tensor): tensor as input to the next layer
- """
- # 实例化一个卷积对象
- conv = Conv2D(num_filters,# 输出空间的维度(即卷积中滤波器的输出数量) #conv2d_ ,conv2d_13,conv2d_23
- kernel_size=kernel_size,
- strides=strides,
- padding='same',#padding设置为SAME,则说明输入图片大小和输出图片大小是一致的,如果是VALID则图片经过滤波器后可能会变小
- kernel_initializer='he_normal',
- kernel_regularizer=l2(1e-4))#该层权重矩阵的每个系数都会使网络总损失增加1e-4*weight_coefficient_value
- x = inputs
- # 定义卷积、批量标准化、激活
- if conv_first:
- x = conv(x)
- if batch_normalization:
- x = BatchNormalization()(x)
- if activation is not None:
- x = Activation(activation)(x)
- else:
- if batch_normalization:
- x = BatchNormalization()(x)
- if activation is not None:
- x = Activation(activation)(x)
- x = conv(x)
- return x
- def resnet_v1(input_shape, depth, num_classes=10, attention_module=None):
- """ResNet Version 1 Model builder [a]
- Stacks of 2 x (3 x 3) Conv2D-BN-ReLU
- Last ReLU is after the shortcut connection.
- At the beginning of each stage, the feature map size is halved (downsampled)
- by a convolutional layer with strides=2, while the number of filters is
- doubled. Within each stage, the layers have the same number filters and the
- same number of filters.
- Features maps sizes:
- stage 0: 32x32, 16
- stage 1: 16x16, 32
- stage 2: 8x8, 64
- The Number of parameters is approx the same as Table 6 of [a]:
- ResNet20 0.27M
- ResNet32 0.46M
- ResNet44 0.66M
- ResNet56 0.85M
- ResNet110 1.7M
- # Arguments
- input_shape (tensor): shape of input image tensor
- depth (int): number of core convolutional layers
- num_classes (int): number of classes (CIFAR10 has 10)
- # Returns
- model (Model): Keras model instance
- """
- if (depth - 2) % 6 != 0: #depth=20
- raise ValueError('depth should be 6n+2 (eg 20, 32, 44 in [a])')
- # Start model definition.
- num_filters = 16
- num_res_blocks = int((depth - 2) / 6) # 每个残差堆叠层含有的残差模块3
- inputs = Input(shape=input_shape) # 这部分返回一个张量,形状为input_shape, 要指定input_shape
- x = resnet_layer(inputs=inputs) # 其余都用自定义参数
- # Instantiate the stack of residual units实例化残差单元模块
- for stack in range(3): # 定义了三个残差堆叠层
- for res_block in range(num_res_blocks): # num_res_blocks = 3
- strides = 1
- if stack > 0 and res_block == 0: # first layer but not first stack 每个残差堆叠层的第一个残差模块,但不是第一个堆叠
- strides = 2 # downsample 在conv3_1, conv4_1下采样
- y = resnet_layer(inputs=x,
- num_filters=num_filters,
- strides=strides) # 有activation
- y = resnet_layer(inputs=y,
- num_filters=num_filters,
- activation=None)
- if stack > 0 and res_block == 0: # first layer but not first stack
- # linear projection residual shortcut connection to match
- # changed dims
- x = resnet_layer(inputs=x,
- num_filters=num_filters,
- kernel_size=1,
- strides=strides,#strides=1
- activation=None,
- batch_normalization=False)
- #以上为原来的resnet,下面是添加attention_module
- # attention_module
- if attention_module is not None:
- y = attach_attention_module(y, attention_module) # net:y
- x = keras.layers.add([x, y]) # add_2:Add 将输入feature和经过res_block的feature相加
- x = Activation('relu')(x) # activation_4:Activation
- num_filters *= 2
- # Add classifier on top.
- # v1 does not use BN after last shortcut connection-ReLU
- x = AveragePooling2D(pool_size=8)(x) #average_pooling2d_1:AveragePooling2D
- y = Flatten()(x) #flaten_1:Flatten
- outputs = Dense(num_classes, #dense19:Dense
- activation='softmax',
- kernel_initializer='he_normal')(y)
- #he_normal 它从[-limt,limt]的均匀分布中抽取样本,其中limit=sqrt(6 / fan_in), 其中`fan_in`是权值张量中输入单位个数
- # Instantiate model.
- model = Model(inputs=inputs, outputs=outputs)
- return model
- """
- 一般情况下, 输入的图片矩阵以及后面的卷积核, 特征图矩阵都是方阵, 这里设输入矩阵大小为 w, 卷积核大小为 k, 步幅为 s, 补零层数为 p, 则卷积后产生的特征图大小计算公式为:
- w'=(w+2p-k)/s+1
- """
- """
- resnet
- 每个 stack 中都含有 3 个残差模块res_block,每个模块的卷积核都是 3X3 大小的,pad 为 1,stride 为 1。
- Con4_x 的输出通过 global_average_pooling 映射到 64 个 1X1 大小的 feature map,最后再通过含有 10 个神经元的全连接层输出分类结果。
- """
|