# -*- coding: utf-8 -*-'''ResNet50 model for Keras.
# Reference:
- [Deep Residual Learning for Image Recognition](https://arxiv.org/abs/1512.03385)
'''from keras.layers import Input
from keras import layers
from keras.layers import Dense
from keras.layers import Activation
from keras.layers import Flatten
from keras.layers import Conv2D
from keras.layers import MaxPooling2D
from keras.layers import GlobalMaxPooling2D
from keras.layers import ZeroPadding2D
from keras.layers import AveragePooling2D
from keras.layers import GlobalAveragePooling2D
from keras.layers import BatchNormalization
from keras.models import Model
import keras.backend as K
#不变的blockdefidentity_block(input_tensor, kernel_size, filters, stage, block):"""The identity block is the block that has no conv layer at shortcut.
# Arguments
input_tensor: input tensor
kernel_size: defualt 3, the kernel size of middle conv layer at main path
filters: list of integers, the filters of 3 conv layer at main path
stage: integer, current stage label, used for generating layer names
block: 'a','b'..., current block label, used for generating layer names
# Returns
Output tensor for the block.
"""
filters1, filters2, filters3 = filters
if K.image_data_format()=='channels_last':
bn_axis =3else:
bn_axis =1
conv_name_base ='res'+str(stage)+ block +'_branch'
bn_name_base ='bn'+str(stage)+ block +'_branch'# 对input——tensor不做处理,直接做ADD
x = Conv2D(filters1,(1,1), name=conv_name_base +'2a')(input_tensor)
x = BatchNormalization(axis=bn_axis, name=bn_name_base +'2a')(x)
x = Activation('relu')(x)
x = Conv2D(filters2, kernel_size,
padding='same', name=conv_name_base +'2b')(x)
x = BatchNormalization(axis=bn_axis, name=bn_name_base +'2b')(x)
x = Activation('relu')(x)
x = Conv2D(filters3,(1,1), name=conv_name_base +'2c')(x)
x = BatchNormalization(axis=bn_axis, name=bn_name_base +'2c')(x)# 对input——tensor不做处理,直接做ADD
x = layers.add([x, input_tensor])
x = Activation('relu')(x)return x
# conv操作的blockdefconv_block(input_tensor, kernel_size, filters, stage, block, strides=(2,2)):"""conv_block is the block that has a conv layer at shortcut
# Arguments
input_tensor: input tensor
kernel_size: defualt 3, the kernel size of middle conv layer at main path
filters: list of integers, the filterss of 3 conv layer at main path
stage: integer, current stage label, used for generating layer names
block: 'a','b'..., current block label, used for generating layer names
# Returns
Output tensor for the block.
Note that from stage 3, the first conv layer at main path is with strides=(2,2)
And the shortcut should have strides=(2,2) as well
"""
filters1, filters2, filters3 = filters
if K.image_data_format()=='channels_last':
bn_axis =3else:
bn_axis =1
conv_name_base ='res'+str(stage)+ block +'_branch'
bn_name_base ='bn'+str(stage)+ block +'_branch'
x = Conv2D(filters1,(1,1), strides=strides,
name=conv_name_base +'2a')(input_tensor)
x = BatchNormalization(axis=bn_axis, name=bn_name_base +'2a')(x)
x = Activation('relu')(x)
x = Conv2D(filters2, kernel_size, padding='same',
name=conv_name_base +'2b')(x)
x = BatchNormalization(axis=bn_axis, name=bn_name_base +'2b')(x)
x = Activation('relu')(x)
x = Conv2D(filters3,(1,1), name=conv_name_base +'2c')(x)
x = BatchNormalization(axis=bn_axis, name=bn_name_base +'2c')(x)# 对input——tensor做处理,得到shortcut
shortcut = Conv2D(filters3,(1,1), strides=strides,
name=conv_name_base +'1')(input_tensor)
shortcut = BatchNormalization(axis=bn_axis, name=bn_name_base +'1')(shortcut)
x = layers.add([x, shortcut])
x = Activation('relu')(x)return x
# 总的ResnetdefResNet50(input_shape, classes=1000):"""Instantiates the ResNet50 architecture.
# Arguments
input_shape: the input shape has to be `(224, 224, 3)` (with `channels_last` data format).
classes: optional number of classes to classify images into
# Returns
A Keras model instance.
"""# 输入层
img_input = Input(shape=input_shape)# 处理通道if K.image_data_format()=='channels_last':
bn_axis =3else:
bn_axis =1
x = ZeroPadding2D((3,3))(img_input)
x = Conv2D(64,(7,7), strides=(2,2), name='conv1')(x)
x = BatchNormalization(axis=bn_axis, name='bn_conv1')(x)
x = Activation('relu')(x)
x = MaxPooling2D((3,3), strides=(2,2))(x)
x = conv_block(x,3,[64,64,256], stage=2, block='a', strides=(1,1))
x = identity_block(x,3,[64,64,256], stage=2, block='b')
x = identity_block(x,3,[64,64,256], stage=2, block='c')
x = conv_block(x,3,[128,128,512], stage=3, block='a')
x = identity_block(x,3,[128,128,512], stage=3, block='b')
x = identity_block(x,3,[128,128,512], stage=3, block='c')
x = identity_block(x,3,[128,128,512], stage=3, block='d')
x = conv_block(x,3,[256,256,1024], stage=4, block='a')
x = identity_block(x,3,[256,256,1024], stage=4, block='b')
x = identity_block(x,3,[256,256,1024], stage=4, block='c')
x = identity_block(x,3,[256,256,1024], stage=4, block='d')
x = identity_block(x,3,[256,256,1024], stage=4, block='e')
x = identity_block(x,3,[256,256,1024], stage=4, block='f')
x = conv_block(x,3,[512,512,2048], stage=5, block='a')
x = identity_block(x,3,[512,512,2048], stage=5, block='b')
x = identity_block(x,3,[512,512,2048], stage=5, block='c')
x = AveragePooling2D((7,7), name='avg_pool')(x)
x = Flatten()(x)
x = Dense(classes, activation='softmax', name='fc1000')(x)# Create model.
model = Model(img_input, x, name='resnet50')return model