inception_v4.py
Go to the documentation of this file.
1 '''
2 Copyright 2017 TensorFlow Authors and Kent Sommer
3 
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7 
8  http://www.apache.org/licenses/LICENSE-2.0
9 
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 '''
16 import numpy as np
17 
18 # Sys
19 import warnings
20 # Keras Core
21 from keras.layers.convolutional import MaxPooling2D, Convolution2D, AveragePooling2D
22 from keras.layers import Input, Dropout, Dense, Flatten, Activation
23 from keras.layers.normalization import BatchNormalization
24 from keras.layers.merge import concatenate
25 from keras import regularizers
26 from keras import initializers
27 from keras.models import Model
28 # Backend
29 from keras import backend as K
30 # Utils
31 from keras.utils.layer_utils import convert_all_kernels_in_model
32 from keras.utils.data_utils import get_file
33 
34 
35 #########################################################################################
36 # Implements the Inception Network v4 (http://arxiv.org/pdf/1602.07261v1.pdf) in Keras. #
37 #########################################################################################
38 
39 WEIGHTS_PATH = 'https://github.com/kentsommer/keras-inceptionV4/releases/download/2.1/inception-v4_weights_tf_dim_ordering_tf_kernels.h5'
40 WEIGHTS_PATH_NO_TOP = 'https://github.com/kentsommer/keras-inceptionV4/releases/download/2.1/inception-v4_weights_tf_dim_ordering_tf_kernels_notop.h5'
41 
42 
44  x = np.divide(x, 255.0)
45  x = np.subtract(x, 0.5)
46  x = np.multiply(x, 2.0)
47  return x
48 
49 
50 def conv2d_bn(x, nb_filter, num_row, num_col,
51  padding='same', strides=(1, 1), use_bias=False):
52  """
53  Utility function to apply conv + BN.
54  (Slightly modified from https://github.com/fchollet/keras/blob/master/keras/applications/inception_v3.py)
55  """
56  if K.image_data_format() == 'channels_first':
57  channel_axis = 1
58  else:
59  channel_axis = -1
60  x = Convolution2D(nb_filter, (num_row, num_col),
61  strides=strides,
62  padding=padding,
63  use_bias=use_bias,
64  kernel_regularizer=regularizers.l2(0.00004),
65  kernel_initializer=initializers.VarianceScaling(scale=2.0, mode='fan_in', distribution='normal', seed=None))(x)
66  x = BatchNormalization(axis=channel_axis, momentum=0.9997, scale=False)(x)
67  x = Activation('relu')(x)
68  return x
69 
70 
71 def block_inception_a(input):
72  if K.image_data_format() == 'channels_first':
73  channel_axis = 1
74  else:
75  channel_axis = -1
76 
77  branch_0 = conv2d_bn(input, 96, 1, 1)
78 
79  branch_1 = conv2d_bn(input, 64, 1, 1)
80  branch_1 = conv2d_bn(branch_1, 96, 3, 3)
81 
82  branch_2 = conv2d_bn(input, 64, 1, 1)
83  branch_2 = conv2d_bn(branch_2, 96, 3, 3)
84  branch_2 = conv2d_bn(branch_2, 96, 3, 3)
85 
86  branch_3 = AveragePooling2D((3,3), strides=(1,1), padding='same')(input)
87  branch_3 = conv2d_bn(branch_3, 96, 1, 1)
88 
89  x = concatenate([branch_0, branch_1, branch_2, branch_3], axis=channel_axis)
90  return x
91 
92 
93 def block_reduction_a(input):
94  if K.image_data_format() == 'channels_first':
95  channel_axis = 1
96  else:
97  channel_axis = -1
98 
99  branch_0 = conv2d_bn(input, 384, 3, 3, strides=(2,2), padding='valid')
100 
101  branch_1 = conv2d_bn(input, 192, 1, 1)
102  branch_1 = conv2d_bn(branch_1, 224, 3, 3)
103  branch_1 = conv2d_bn(branch_1, 256, 3, 3, strides=(2,2), padding='valid')
104 
105  branch_2 = MaxPooling2D((3,3), strides=(2,2), padding='valid')(input)
106 
107  x = concatenate([branch_0, branch_1, branch_2], axis=channel_axis)
108  return x
109 
110 
111 def block_inception_b(input):
112  if K.image_data_format() == 'channels_first':
113  channel_axis = 1
114  else:
115  channel_axis = -1
116 
117  branch_0 = conv2d_bn(input, 384, 1, 1)
118 
119  branch_1 = conv2d_bn(input, 192, 1, 1)
120  branch_1 = conv2d_bn(branch_1, 224, 1, 7)
121  branch_1 = conv2d_bn(branch_1, 256, 7, 1)
122 
123  branch_2 = conv2d_bn(input, 192, 1, 1)
124  branch_2 = conv2d_bn(branch_2, 192, 7, 1)
125  branch_2 = conv2d_bn(branch_2, 224, 1, 7)
126  branch_2 = conv2d_bn(branch_2, 224, 7, 1)
127  branch_2 = conv2d_bn(branch_2, 256, 1, 7)
128 
129  branch_3 = AveragePooling2D((3,3), strides=(1,1), padding='same')(input)
130  branch_3 = conv2d_bn(branch_3, 128, 1, 1)
131 
132  x = concatenate([branch_0, branch_1, branch_2, branch_3], axis=channel_axis)
133  return x
134 
135 
136 def block_reduction_b(input):
137  if K.image_data_format() == 'channels_first':
138  channel_axis = 1
139  else:
140  channel_axis = -1
141 
142  branch_0 = conv2d_bn(input, 192, 1, 1)
143  branch_0 = conv2d_bn(branch_0, 192, 3, 3, strides=(2, 2), padding='valid')
144 
145  branch_1 = conv2d_bn(input, 256, 1, 1)
146  branch_1 = conv2d_bn(branch_1, 256, 1, 7)
147  branch_1 = conv2d_bn(branch_1, 320, 7, 1)
148  branch_1 = conv2d_bn(branch_1, 320, 3, 3, strides=(2,2), padding='valid')
149 
150  branch_2 = MaxPooling2D((3, 3), strides=(2, 2), padding='valid')(input)
151 
152  x = concatenate([branch_0, branch_1, branch_2], axis=channel_axis)
153  return x
154 
155 
156 def block_inception_c(input):
157  if K.image_data_format() == 'channels_first':
158  channel_axis = 1
159  else:
160  channel_axis = -1
161 
162  branch_0 = conv2d_bn(input, 256, 1, 1)
163 
164  branch_1 = conv2d_bn(input, 384, 1, 1)
165  branch_10 = conv2d_bn(branch_1, 256, 1, 3)
166  branch_11 = conv2d_bn(branch_1, 256, 3, 1)
167  branch_1 = concatenate([branch_10, branch_11], axis=channel_axis)
168 
169 
170  branch_2 = conv2d_bn(input, 384, 1, 1)
171  branch_2 = conv2d_bn(branch_2, 448, 3, 1)
172  branch_2 = conv2d_bn(branch_2, 512, 1, 3)
173  branch_20 = conv2d_bn(branch_2, 256, 1, 3)
174  branch_21 = conv2d_bn(branch_2, 256, 3, 1)
175  branch_2 = concatenate([branch_20, branch_21], axis=channel_axis)
176 
177  branch_3 = AveragePooling2D((3, 3), strides=(1, 1), padding='same')(input)
178  branch_3 = conv2d_bn(branch_3, 256, 1, 1)
179 
180  x = concatenate([branch_0, branch_1, branch_2, branch_3], axis=channel_axis)
181  return x
182 
183 
184 def inception_v4_base(input):
185  if K.image_data_format() == 'channels_first':
186  channel_axis = 1
187  else:
188  channel_axis = -1
189 
190  # Input Shape is 299 x 299 x 3 (th) or 3 x 299 x 299 (th)
191  net = conv2d_bn(input, 32, 3, 3, strides=(2,2), padding='valid')
192  net = conv2d_bn(net, 32, 3, 3, padding='valid')
193  net = conv2d_bn(net, 64, 3, 3)
194 
195  branch_0 = MaxPooling2D((3,3), strides=(2,2), padding='valid')(net)
196 
197  branch_1 = conv2d_bn(net, 96, 3, 3, strides=(2,2), padding='valid')
198 
199  net = concatenate([branch_0, branch_1], axis=channel_axis)
200 
201  branch_0 = conv2d_bn(net, 64, 1, 1)
202  branch_0 = conv2d_bn(branch_0, 96, 3, 3, padding='valid')
203 
204  branch_1 = conv2d_bn(net, 64, 1, 1)
205  branch_1 = conv2d_bn(branch_1, 64, 1, 7)
206  branch_1 = conv2d_bn(branch_1, 64, 7, 1)
207  branch_1 = conv2d_bn(branch_1, 96, 3, 3, padding='valid')
208 
209  net = concatenate([branch_0, branch_1], axis=channel_axis)
210 
211  branch_0 = conv2d_bn(net, 192, 3, 3, strides=(2,2), padding='valid')
212  branch_1 = MaxPooling2D((3,3), strides=(2,2), padding='valid')(net)
213 
214  net = concatenate([branch_0, branch_1], axis=channel_axis)
215 
216  # 35 x 35 x 384
217  # 4 x Inception-A blocks
218  for idx in range(4):
219  net = block_inception_a(net)
220 
221  # 35 x 35 x 384
222  # Reduction-A block
223  net = block_reduction_a(net)
224 
225  # 17 x 17 x 1024
226  # 7 x Inception-B blocks
227  for idx in range(7):
228  net = block_inception_b(net)
229 
230  # 17 x 17 x 1024
231  # Reduction-B block
232  net = block_reduction_b(net)
233 
234  # 8 x 8 x 1536
235  # 3 x Inception-C blocks
236  for idx in range(3):
237  net = block_inception_c(net)
238 
239  return net
240 
241 
242 def inception_v4(num_classes, dropout_keep_prob, weights, input_shape, include_top, transfer_learning=None):
243  '''
244  Creates the inception v4 network
245 
246  Args:
247  num_classes: number of classes
248  dropout_keep_prob: float, the fraction to keep before final layer.
249 
250  Returns:
251  logits: the logits outputs of the model.
252  '''
253 
254  # Input Shape is 299 x 299 x 3 (tf) or 3 x 299 x 299 (th)
255  if K.image_data_format() == 'channels_first':
256  inputs = Input((input_shape[2], input_shape[0], input_shape[1]))
257  else:
258  inputs = Input(input_shape)
259 
260  # Make inception base
261  x = inception_v4_base(inputs)
262 
263 
264  # Final pooling and prediction
265  if include_top:
266  # 1 x 1 x 1536
267  x = AveragePooling2D((8,8), padding='valid')(x)
268  x = Dropout(dropout_keep_prob)(x)
269  x = Flatten()(x)
270  # 1536
271  x = Dense(units=num_classes, activation='softmax')(x)
272 
273  model = Model(inputs, x, name='inception_v4')
274 
275  # load weights
276  if weights == 'imagenet':
277  if K.image_data_format() == 'channels_first':
278  if K.backend() == 'tensorflow':
279  warnings.warn('You are using the TensorFlow backend, yet you '
280  'are using the Theano '
281  'image data format convention '
282  '(`image_data_format="channels_first"`). '
283  'For best performance, set '
284  '`image_data_format="channels_last"` in '
285  'your Keras config '
286  'at ~/.keras/keras.json.')
287  if include_top:
288  weights_path = get_file(
289  'inception-v4_weights_tf_dim_ordering_tf_kernels.h5',
290  WEIGHTS_PATH,
291  cache_subdir='models',
292  md5_hash='9fe79d77f793fe874470d84ca6ba4a3b')
293  else:
294  weights_path = get_file(
295  'inception-v4_weights_tf_dim_ordering_tf_kernels_notop.h5',
296  WEIGHTS_PATH_NO_TOP,
297  cache_subdir='models',
298  md5_hash='9296b46b5971573064d12e4669110969')
299  model.load_weights(weights_path, by_name=True)
300 
301  # transfer learning
302  if transfer_learning == 'pretraining' or transfer_learning == 'finetuning':
303  # 1 x 1 x 1536
304  x = AveragePooling2D((8,8), padding='valid')(x)
305  x = Dropout(dropout_keep_prob)(x)
306  x = Flatten()(x)
307  # 1536
308  x = Dense(units=num_classes, activation='softmax')(x)
309 
310  model = Model(inputs, x, name='inception_v4')
311 
312  if transfer_learning == 'finetuning':
313  for layer in model.layers[:-4]:
314  layer.trainable = False
315 
316  return model
317 
318 
319 def create_model(num_classes=1001, dropout_prob=0.2, weights=None, include_top=True, transfer_learning=None, input_shape=None):
320  return inception_v4(num_classes, dropout_prob, weights, input_shape, include_top, transfer_learning)
def inception_v4(num_classes, dropout_keep_prob, weights, input_shape, include_top, transfer_learning=None)
def inception_v4_base(input)
std::string concatenate(H const &h, T const &...t)
Definition: select.h:138
def preprocess_input(x)
Definition: inception_v4.py:43
def block_reduction_b(input)
def block_reduction_a(input)
Definition: inception_v4.py:93
def create_model(num_classes=1001, dropout_prob=0.2, weights=None, include_top=True, transfer_learning=None, input_shape=None)
def conv2d_bn(x, nb_filter, num_row, num_col, padding='same', strides=(1, 1), use_bias=False)
Definition: inception_v4.py:51
def block_inception_a(input)
Definition: inception_v4.py:71
def block_inception_b(input)
def block_inception_c(input)