Skip to content

Commit 1381958

Browse files
authored
Add files via upload
1 parent 572e0e7 commit 1381958

File tree

3 files changed

+513
-0
lines changed

3 files changed

+513
-0
lines changed

resnet50.py

Lines changed: 286 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,286 @@
1+
# -*- coding: utf-8 -*-
2+
'''ResNet50 model for Keras.
3+
# Reference:
4+
- [Deep Residual Learning for Image Recognition](https://arxiv.org/abs/1512.03385)
5+
Adapted from code contributed by BigMoyan.
6+
'''
7+
from __future__ import print_function
8+
9+
import numpy as np
10+
import warnings
11+
12+
from keras.layers import Input
13+
from keras import layers
14+
from keras.layers import Dense
15+
from keras.layers import Activation
16+
from keras.layers import Flatten
17+
from keras.layers import Conv2D
18+
from keras.layers import MaxPooling2D
19+
from keras.layers import GlobalMaxPooling2D
20+
from keras.layers import ZeroPadding2D
21+
from keras.layers import AveragePooling2D
22+
from keras.layers import GlobalAveragePooling2D
23+
from keras.layers import BatchNormalization
24+
from keras.models import Model
25+
from keras.preprocessing import image
26+
import keras.backend as K
27+
from keras.utils import layer_utils
28+
from keras.utils.data_utils import get_file
29+
from keras.applications.imagenet_utils import decode_predictions
30+
from keras.applications.imagenet_utils import preprocess_input
31+
from keras.applications.imagenet_utils import _obtain_input_shape
32+
from keras.engine.topology import get_source_inputs
33+
34+
35+
WEIGHTS_PATH = 'https://github.com/fchollet/deep-learning-models/releases/download/v0.2/resnet50_weights_tf_dim_ordering_tf_kernels.h5'
36+
WEIGHTS_PATH_NO_TOP = 'https://github.com/fchollet/deep-learning-models/releases/download/v0.2/resnet50_weights_tf_dim_ordering_tf_kernels_notop.h5'
37+
38+
39+
def identity_block(input_tensor, kernel_size, filters, stage, block):
40+
"""The identity block is the block that has no conv layer at shortcut.
41+
# Arguments
42+
input_tensor: input tensor
43+
kernel_size: defualt 3, the kernel size of middle conv layer at main path
44+
filters: list of integers, the filterss of 3 conv layer at main path
45+
stage: integer, current stage label, used for generating layer names
46+
block: 'a','b'..., current block label, used for generating layer names
47+
# Returns
48+
Output tensor for the block.
49+
"""
50+
filters1, filters2, filters3 = filters
51+
if K.image_data_format() == 'channels_last':
52+
bn_axis = 3
53+
else:
54+
bn_axis = 1
55+
conv_name_base = 'res' + str(stage) + block + '_branch'
56+
bn_name_base = 'bn' + str(stage) + block + '_branch'
57+
58+
x = Conv2D(filters1, (1, 1), name=conv_name_base + '2a')(input_tensor)
59+
x = BatchNormalization(axis=bn_axis, name=bn_name_base + '2a')(x)
60+
x = Activation('relu')(x)
61+
62+
x = Conv2D(filters2, kernel_size,
63+
padding='same', name=conv_name_base + '2b')(x)
64+
x = BatchNormalization(axis=bn_axis, name=bn_name_base + '2b')(x)
65+
x = Activation('relu')(x)
66+
67+
x = Conv2D(filters3, (1, 1), name=conv_name_base + '2c')(x)
68+
x = BatchNormalization(axis=bn_axis, name=bn_name_base + '2c')(x)
69+
70+
x = layers.add([x, input_tensor])
71+
x = Activation('relu')(x)
72+
return x
73+
74+
75+
def conv_block(input_tensor, kernel_size, filters, stage, block, strides=(2, 2)):
76+
"""conv_block is the block that has a conv layer at shortcut
77+
# Arguments
78+
input_tensor: input tensor
79+
kernel_size: defualt 3, the kernel size of middle conv layer at main path
80+
filters: list of integers, the filterss of 3 conv layer at main path
81+
stage: integer, current stage label, used for generating layer names
82+
block: 'a','b'..., current block label, used for generating layer names
83+
# Returns
84+
Output tensor for the block.
85+
Note that from stage 3, the first conv layer at main path is with strides=(2,2)
86+
And the shortcut should have strides=(2,2) as well
87+
"""
88+
filters1, filters2, filters3 = filters
89+
if K.image_data_format() == 'channels_last':
90+
bn_axis = 3
91+
else:
92+
bn_axis = 1
93+
conv_name_base = 'res' + str(stage) + block + '_branch'
94+
bn_name_base = 'bn' + str(stage) + block + '_branch'
95+
96+
x = Conv2D(filters1, (1, 1), strides=strides,
97+
name=conv_name_base + '2a')(input_tensor)
98+
x = BatchNormalization(axis=bn_axis, name=bn_name_base + '2a')(x)
99+
x = Activation('relu')(x)
100+
101+
x = Conv2D(filters2, kernel_size, padding='same',
102+
name=conv_name_base + '2b')(x)
103+
x = BatchNormalization(axis=bn_axis, name=bn_name_base + '2b')(x)
104+
x = Activation('relu')(x)
105+
106+
x = Conv2D(filters3, (1, 1), name=conv_name_base + '2c')(x)
107+
x = BatchNormalization(axis=bn_axis, name=bn_name_base + '2c')(x)
108+
109+
shortcut = Conv2D(filters3, (1, 1), strides=strides,
110+
name=conv_name_base + '1')(input_tensor)
111+
shortcut = BatchNormalization(axis=bn_axis, name=bn_name_base + '1')(shortcut)
112+
113+
x = layers.add([x, shortcut])
114+
x = Activation('relu')(x)
115+
return x
116+
117+
118+
def ResNet50(include_top=True, weights='imagenet',
119+
input_tensor=None, input_shape=None,
120+
pooling=None,
121+
classes=1000):
122+
"""Instantiates the ResNet50 architecture.
123+
Optionally loads weights pre-trained
124+
on ImageNet. Note that when using TensorFlow,
125+
for best performance you should set
126+
`image_data_format="channels_last"` in your Keras config
127+
at ~/.keras/keras.json.
128+
The model and the weights are compatible with both
129+
TensorFlow and Theano. The data format
130+
convention used by the model is the one
131+
specified in your Keras config file.
132+
# Arguments
133+
include_top: whether to include the fully-connected
134+
layer at the top of the network.
135+
weights: one of `None` (random initialization)
136+
or "imagenet" (pre-training on ImageNet).
137+
input_tensor: optional Keras tensor (i.e. output of `layers.Input()`)
138+
to use as image input for the model.
139+
input_shape: optional shape tuple, only to be specified
140+
if `include_top` is False (otherwise the input shape
141+
has to be `(224, 224, 3)` (with `channels_last` data format)
142+
or `(3, 224, 244)` (with `channels_first` data format).
143+
It should have exactly 3 inputs channels,
144+
and width and height should be no smaller than 197.
145+
E.g. `(200, 200, 3)` would be one valid value.
146+
pooling: Optional pooling mode for feature extraction
147+
when `include_top` is `False`.
148+
- `None` means that the output of the model will be
149+
the 4D tensor output of the
150+
last convolutional layer.
151+
- `avg` means that global average pooling
152+
will be applied to the output of the
153+
last convolutional layer, and thus
154+
the output of the model will be a 2D tensor.
155+
- `max` means that global max pooling will
156+
be applied.
157+
classes: optional number of classes to classify images
158+
into, only to be specified if `include_top` is True, and
159+
if no `weights` argument is specified.
160+
# Returns
161+
A Keras model instance.
162+
# Raises
163+
ValueError: in case of invalid argument for `weights`,
164+
or invalid input shape.
165+
"""
166+
if weights not in {'imagenet', None}:
167+
raise ValueError('The `weights` argument should be either '
168+
'`None` (random initialization) or `imagenet` '
169+
'(pre-training on ImageNet).')
170+
171+
if weights == 'imagenet' and include_top and classes != 1000:
172+
raise ValueError('If using `weights` as imagenet with `include_top`'
173+
' as true, `classes` should be 1000')
174+
175+
# Determine proper input shape
176+
input_shape = _obtain_input_shape(input_shape,
177+
default_size=224,
178+
min_size=197,
179+
data_format=K.image_data_format(),
180+
include_top=include_top)
181+
182+
if input_tensor is None:
183+
img_input = Input(shape=input_shape)
184+
else:
185+
if not K.is_keras_tensor(input_tensor):
186+
img_input = Input(tensor=input_tensor, shape=input_shape)
187+
else:
188+
img_input = input_tensor
189+
if K.image_data_format() == 'channels_last':
190+
bn_axis = 3
191+
else:
192+
bn_axis = 1
193+
194+
x = ZeroPadding2D((3, 3))(img_input)
195+
x = Conv2D(64, (7, 7), strides=(2, 2), name='conv1')(x)
196+
x = BatchNormalization(axis=bn_axis, name='bn_conv1')(x)
197+
x = Activation('relu')(x)
198+
x = MaxPooling2D((3, 3), strides=(2, 2))(x)
199+
200+
x = conv_block(x, 3, [64, 64, 256], stage=2, block='a', strides=(1, 1))
201+
x = identity_block(x, 3, [64, 64, 256], stage=2, block='b')
202+
x = identity_block(x, 3, [64, 64, 256], stage=2, block='c')
203+
204+
x = conv_block(x, 3, [128, 128, 512], stage=3, block='a')
205+
x = identity_block(x, 3, [128, 128, 512], stage=3, block='b')
206+
x = identity_block(x, 3, [128, 128, 512], stage=3, block='c')
207+
x = identity_block(x, 3, [128, 128, 512], stage=3, block='d')
208+
209+
x = conv_block(x, 3, [256, 256, 1024], stage=4, block='a')
210+
x = identity_block(x, 3, [256, 256, 1024], stage=4, block='b')
211+
x = identity_block(x, 3, [256, 256, 1024], stage=4, block='c')
212+
x = identity_block(x, 3, [256, 256, 1024], stage=4, block='d')
213+
x = identity_block(x, 3, [256, 256, 1024], stage=4, block='e')
214+
x = identity_block(x, 3, [256, 256, 1024], stage=4, block='f')
215+
216+
x = conv_block(x, 3, [512, 512, 2048], stage=5, block='a')
217+
x = identity_block(x, 3, [512, 512, 2048], stage=5, block='b')
218+
x = identity_block(x, 3, [512, 512, 2048], stage=5, block='c')
219+
220+
x = AveragePooling2D((7, 7), name='avg_pool')(x)
221+
222+
if include_top:
223+
x = Flatten()(x)
224+
x = Dense(classes, activation='softmax', name='fc1000')(x)
225+
else:
226+
if pooling == 'avg':
227+
x = GlobalAveragePooling2D()(x)
228+
elif pooling == 'max':
229+
x = GlobalMaxPooling2D()(x)
230+
231+
# Ensure that the model takes into account
232+
# any potential predecessors of `input_tensor`.
233+
if input_tensor is not None:
234+
inputs = get_source_inputs(input_tensor)
235+
else:
236+
inputs = img_input
237+
# Create model.
238+
model = Model(inputs, x, name='resnet50')
239+
240+
# load weights
241+
if weights == 'imagenet':
242+
if include_top:
243+
weights_path = get_file('resnet50_weights_tf_dim_ordering_tf_kernels.h5',
244+
WEIGHTS_PATH,
245+
cache_subdir='models',
246+
md5_hash='a7b3fe01876f51b976af0dea6bc144eb')
247+
else:
248+
weights_path = get_file('resnet50_weights_tf_dim_ordering_tf_kernels_notop.h5',
249+
WEIGHTS_PATH_NO_TOP,
250+
cache_subdir='models',
251+
md5_hash='a268eb855778b3df3c7506639542a6af')
252+
model.load_weights(weights_path)
253+
if K.backend() == 'theano':
254+
layer_utils.convert_all_kernels_in_model(model)
255+
256+
if K.image_data_format() == 'channels_first':
257+
if include_top:
258+
maxpool = model.get_layer(name='avg_pool')
259+
shape = maxpool.output_shape[1:]
260+
dense = model.get_layer(name='fc1000')
261+
layer_utils.convert_dense_weights_data_format(dense, shape, 'channels_first')
262+
263+
if K.backend() == 'tensorflow':
264+
warnings.warn('You are using the TensorFlow backend, yet you '
265+
'are using the Theano '
266+
'image data format convention '
267+
'(`image_data_format="channels_first"`). '
268+
'For best performance, set '
269+
'`image_data_format="channels_last"` in '
270+
'your Keras config '
271+
'at ~/.keras/keras.json.')
272+
return model
273+
274+
275+
if __name__ == '__main__':
276+
model = ResNet50(include_top=True, weights='imagenet')
277+
278+
img_path = 'elephant.jpg'
279+
img = image.load_img(img_path, target_size=(224, 224))
280+
x = image.img_to_array(img)
281+
x = np.expand_dims(x, axis=0)
282+
x = preprocess_input(x)
283+
print('Input image shape:', x.shape)
284+
285+
preds = model.predict(x)
286+
print('Predicted:', decode_predictions(preds))

0 commit comments

Comments
 (0)