| | ''' |
| | Copyright 2017 TensorFlow Authors and Kent Sommer |
| | |
| | Licensed under the Apache License, Version 2.0 (the "License"); |
| | you may not use this file except in compliance with the License. |
| | You may obtain a copy of the License at |
| | |
| | http://www.apache.org/licenses/LICENSE-2.0 |
| | |
| | Unless required by applicable law or agreed to in writing, software |
| | distributed under the License is distributed on an "AS IS" BASIS, |
| | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| | See the License for the specific language governing permissions and |
| | limitations under the License. |
| | ''' |
| | import tensorflow as tf |
| |
|
| | |
| | import warnings |
| | |
| | from keras.layers import MaxPooling2D, Convolution2D, AveragePooling2D |
| | from keras.layers import Input, Dropout, Dense, Flatten, Activation |
| | from keras.layers import BatchNormalization |
| | from keras.layers import concatenate |
| | from keras import regularizers |
| | from keras import initializers |
| | from keras.models import Model |
| | |
| | from keras import backend as K |
| | |
| | from keras.utils import get_file |
| |
|
| |
|
| | |
| | |
| | |
| |
|
| | WEIGHTS_PATH = 'https://github.com/kentsommer/keras-inceptionV4/releases/download/2.1/inception-v4_weights_tf_dim_ordering_tf_kernels.h5' |
| | WEIGHTS_PATH_NO_TOP = 'https://github.com/kentsommer/keras-inceptionV4/releases/download/2.1/inception-v4_weights_tf_dim_ordering_tf_kernels_notop.h5' |
| |
|
| |
|
| | def preprocess_input(x): |
| | x = tf.divide(x, 255.0) |
| | x = tf.subtract(x, 0.5) |
| | x = tf.multiply(x, 2.0) |
| | return x |
| |
|
| |
|
| | def conv2d_bn(x, nb_filter, num_row, num_col, |
| | padding='same', strides=(1, 1), use_bias=False): |
| | """ |
| | Utility function to apply conv + BN. |
| | (Slightly modified from https://github.com/fchollet/keras/blob/master/keras/applications/inception_v3.py) |
| | """ |
| | if K.image_data_format() == 'channels_first': |
| | channel_axis = 1 |
| | else: |
| | channel_axis = -1 |
| | x = Convolution2D(nb_filter, (num_row, num_col), |
| | strides=strides, |
| | padding=padding, |
| | use_bias=use_bias, |
| | kernel_regularizer=regularizers.l2(0.00004), |
| | kernel_initializer=initializers.VarianceScaling(scale=2.0, mode='fan_in', distribution='normal', seed=None))(x) |
| | x = BatchNormalization(axis=channel_axis, momentum=0.9997, scale=False)(x) |
| | x = Activation('relu')(x) |
| | return x |
| |
|
| |
|
| | def block_inception_a(input): |
| | if K.image_data_format() == 'channels_first': |
| | channel_axis = 1 |
| | else: |
| | channel_axis = -1 |
| |
|
| | branch_0 = conv2d_bn(input, 96, 1, 1) |
| |
|
| | branch_1 = conv2d_bn(input, 64, 1, 1) |
| | branch_1 = conv2d_bn(branch_1, 96, 3, 3) |
| |
|
| | branch_2 = conv2d_bn(input, 64, 1, 1) |
| | branch_2 = conv2d_bn(branch_2, 96, 3, 3) |
| | branch_2 = conv2d_bn(branch_2, 96, 3, 3) |
| |
|
| | branch_3 = AveragePooling2D((3,3), strides=(1,1), padding='same')(input) |
| | branch_3 = conv2d_bn(branch_3, 96, 1, 1) |
| |
|
| | x = concatenate([branch_0, branch_1, branch_2, branch_3], axis=channel_axis) |
| | return x |
| |
|
| |
|
| | def block_reduction_a(input): |
| | if K.image_data_format() == 'channels_first': |
| | channel_axis = 1 |
| | else: |
| | channel_axis = -1 |
| |
|
| | branch_0 = conv2d_bn(input, 384, 3, 3, strides=(2,2), padding='valid') |
| |
|
| | branch_1 = conv2d_bn(input, 192, 1, 1) |
| | branch_1 = conv2d_bn(branch_1, 224, 3, 3) |
| | branch_1 = conv2d_bn(branch_1, 256, 3, 3, strides=(2,2), padding='valid') |
| |
|
| | branch_2 = MaxPooling2D((3,3), strides=(2,2), padding='valid')(input) |
| |
|
| | x = concatenate([branch_0, branch_1, branch_2], axis=channel_axis) |
| | return x |
| |
|
| |
|
| | def block_inception_b(input): |
| | if K.image_data_format() == 'channels_first': |
| | channel_axis = 1 |
| | else: |
| | channel_axis = -1 |
| |
|
| | branch_0 = conv2d_bn(input, 384, 1, 1) |
| |
|
| | branch_1 = conv2d_bn(input, 192, 1, 1) |
| | branch_1 = conv2d_bn(branch_1, 224, 1, 7) |
| | branch_1 = conv2d_bn(branch_1, 256, 7, 1) |
| |
|
| | branch_2 = conv2d_bn(input, 192, 1, 1) |
| | branch_2 = conv2d_bn(branch_2, 192, 7, 1) |
| | branch_2 = conv2d_bn(branch_2, 224, 1, 7) |
| | branch_2 = conv2d_bn(branch_2, 224, 7, 1) |
| | branch_2 = conv2d_bn(branch_2, 256, 1, 7) |
| |
|
| | branch_3 = AveragePooling2D((3,3), strides=(1,1), padding='same')(input) |
| | branch_3 = conv2d_bn(branch_3, 128, 1, 1) |
| |
|
| | x = concatenate([branch_0, branch_1, branch_2, branch_3], axis=channel_axis) |
| | return x |
| |
|
| |
|
| | def block_reduction_b(input): |
| | if K.image_data_format() == 'channels_first': |
| | channel_axis = 1 |
| | else: |
| | channel_axis = -1 |
| |
|
| | branch_0 = conv2d_bn(input, 192, 1, 1) |
| | branch_0 = conv2d_bn(branch_0, 192, 3, 3, strides=(2, 2), padding='valid') |
| |
|
| | branch_1 = conv2d_bn(input, 256, 1, 1) |
| | branch_1 = conv2d_bn(branch_1, 256, 1, 7) |
| | branch_1 = conv2d_bn(branch_1, 320, 7, 1) |
| | branch_1 = conv2d_bn(branch_1, 320, 3, 3, strides=(2,2), padding='valid') |
| |
|
| | branch_2 = MaxPooling2D((3, 3), strides=(2, 2), padding='valid')(input) |
| |
|
| | x = concatenate([branch_0, branch_1, branch_2], axis=channel_axis) |
| | return x |
| |
|
| |
|
| | def block_inception_c(input): |
| | if K.image_data_format() == 'channels_first': |
| | channel_axis = 1 |
| | else: |
| | channel_axis = -1 |
| |
|
| | branch_0 = conv2d_bn(input, 256, 1, 1) |
| |
|
| | branch_1 = conv2d_bn(input, 384, 1, 1) |
| | branch_10 = conv2d_bn(branch_1, 256, 1, 3) |
| | branch_11 = conv2d_bn(branch_1, 256, 3, 1) |
| | branch_1 = concatenate([branch_10, branch_11], axis=channel_axis) |
| |
|
| |
|
| | branch_2 = conv2d_bn(input, 384, 1, 1) |
| | branch_2 = conv2d_bn(branch_2, 448, 3, 1) |
| | branch_2 = conv2d_bn(branch_2, 512, 1, 3) |
| | branch_20 = conv2d_bn(branch_2, 256, 1, 3) |
| | branch_21 = conv2d_bn(branch_2, 256, 3, 1) |
| | branch_2 = concatenate([branch_20, branch_21], axis=channel_axis) |
| |
|
| | branch_3 = AveragePooling2D((3, 3), strides=(1, 1), padding='same')(input) |
| | branch_3 = conv2d_bn(branch_3, 256, 1, 1) |
| |
|
| | x = concatenate([branch_0, branch_1, branch_2, branch_3], axis=channel_axis) |
| | return x |
| |
|
| |
|
| | def inception_v4_base(input): |
| | if K.image_data_format() == 'channels_first': |
| | channel_axis = 1 |
| | else: |
| | channel_axis = -1 |
| |
|
| | |
| | net = conv2d_bn(input, 32, 3, 3, strides=(2,2), padding='valid') |
| | net = conv2d_bn(net, 32, 3, 3, padding='valid') |
| | net = conv2d_bn(net, 64, 3, 3) |
| |
|
| | branch_0 = MaxPooling2D((3,3), strides=(2,2), padding='valid')(net) |
| |
|
| | branch_1 = conv2d_bn(net, 96, 3, 3, strides=(2,2), padding='valid') |
| |
|
| | net = concatenate([branch_0, branch_1], axis=channel_axis) |
| |
|
| | branch_0 = conv2d_bn(net, 64, 1, 1) |
| | branch_0 = conv2d_bn(branch_0, 96, 3, 3, padding='valid') |
| |
|
| | branch_1 = conv2d_bn(net, 64, 1, 1) |
| | branch_1 = conv2d_bn(branch_1, 64, 1, 7) |
| | branch_1 = conv2d_bn(branch_1, 64, 7, 1) |
| | branch_1 = conv2d_bn(branch_1, 96, 3, 3, padding='valid') |
| |
|
| | net = concatenate([branch_0, branch_1], axis=channel_axis) |
| |
|
| | branch_0 = conv2d_bn(net, 192, 3, 3, strides=(2,2), padding='valid') |
| | branch_1 = MaxPooling2D((3,3), strides=(2,2), padding='valid')(net) |
| |
|
| | net = concatenate([branch_0, branch_1], axis=channel_axis) |
| |
|
| | |
| | |
| | for idx in range(4): |
| | net = block_inception_a(net) |
| |
|
| | |
| | |
| | net = block_reduction_a(net) |
| |
|
| | |
| | |
| | for idx in range(7): |
| | net = block_inception_b(net) |
| |
|
| | |
| | |
| | net = block_reduction_b(net) |
| |
|
| | |
| | |
| | for idx in range(3): |
| | net = block_inception_c(net) |
| |
|
| | return net |
| |
|
| |
|
| | def inception_v4(num_classes, dropout_keep_prob, weights, include_top, input_shape=(299, 299, 3)): |
| | ''' |
| | Creates the inception v4 network |
| | |
| | Args: |
| | num_classes: number of classes |
| | dropout_keep_prob: float, the fraction to keep before final layer. |
| | |
| | Returns: |
| | logits: the logits outputs of the model. |
| | ''' |
| |
|
| | |
| | if K.image_data_format() == 'channels_first': |
| | inputs = Input((3, input_shape[1], input_shape[2])) |
| | else: |
| | inputs = Input(input_shape) |
| |
|
| | |
| | x = inception_v4_base(inputs) |
| |
|
| |
|
| | |
| | if include_top: |
| | |
| | x = AveragePooling2D((8,8), padding='valid')(x) |
| | x = Dropout(dropout_keep_prob)(x) |
| | x = Flatten()(x) |
| | |
| | x = Dense(units=num_classes, activation='softmax')(x) |
| |
|
| | model = Model(inputs, x, name='inception_v4') |
| |
|
| | |
| | if weights == 'imagenet': |
| | if K.image_data_format() == 'channels_first': |
| | if K.backend() == 'tensorflow': |
| | warnings.warn('You are using the TensorFlow backend, yet you ' |
| | 'are using the Theano ' |
| | 'image data format convention ' |
| | '(`image_data_format="channels_first"`). ' |
| | 'For best performance, set ' |
| | '`image_data_format="channels_last"` in ' |
| | 'your Keras config ' |
| | 'at ~/.keras/keras.json.') |
| | if include_top: |
| | weights_path = get_file( |
| | 'inception-v4_weights_tf_dim_ordering_tf_kernels.h5', |
| | WEIGHTS_PATH, |
| | cache_subdir='models', |
| | md5_hash='9fe79d77f793fe874470d84ca6ba4a3b') |
| | else: |
| | weights_path = get_file( |
| | 'inception-v4_weights_tf_dim_ordering_tf_kernels_notop.h5', |
| | WEIGHTS_PATH_NO_TOP, |
| | cache_subdir='models', |
| | md5_hash='9296b46b5971573064d12e4669110969') |
| | model.load_weights(weights_path) |
| | return model |
| |
|
| |
|
| | def InceptionV4(num_classes=1001, dropout_prob=0.2, weights=None, include_top=True, input_shape=(299, 299, 3)): |
| | return inception_v4(num_classes, dropout_prob, weights, include_top, input_shape=input_shape) |