#!/usr/bin/env python3 # -*- coding: utf-8 -*- # # A tf.keras implementation of squeezenet with pretrained weights, # which is ported from https://github.com/rcmalli/keras-squeezenet # from keras_applications.imagenet_utils import _obtain_input_shape from tensorflow.keras.utils import get_source_inputs, get_file from tensorflow.keras.layers import Conv2D, MaxPool2D, GlobalMaxPooling2D, GlobalAveragePooling2D from tensorflow.keras.layers import BatchNormalization, Dropout, Lambda from tensorflow.keras.layers import Input, Activation, concatenate from tensorflow.keras.models import Model from tensorflow.keras import backend as K import warnings sq1x1 = "squeeze1x1" exp1x1 = "expand1x1" exp3x3 = "expand3x3" relu = "relu_" WEIGHTS_PATH = "https://github.com/rcmalli/keras-squeezenet/releases/download/v1.0/squeezenet_weights_tf_dim_ordering_tf_kernels.h5" WEIGHTS_PATH_NO_TOP = "https://github.com/rcmalli/keras-squeezenet/releases/download/v1.0/squeezenet_weights_tf_dim_ordering_tf_kernels_notop.h5" # Modular function for Fire Node def fire_module(x, fire_id, squeeze=16, expand=64): s_id = 'fire' + str(fire_id) + '/' if K.image_data_format() == 'channels_first': channel_axis = 1 else: channel_axis = 3 x = Conv2D(squeeze, (1, 1), padding='valid', name=s_id + sq1x1)(x) x = Activation('relu', name=s_id + relu + sq1x1)(x) left = Conv2D(expand, (1, 1), padding='valid', name=s_id + exp1x1)(x) left = Activation('relu', name=s_id + relu + exp1x1)(left) right = Conv2D(expand, (3, 3), padding='same', name=s_id + exp3x3)(x) right = Activation('relu', name=s_id + relu + exp3x3)(right) x = concatenate([left, right], axis=channel_axis, name=s_id + 'concat') return x # Original SqueezeNet from paper. def SqueezeNet(include_top=True, input_shape=None, weights='imagenet', input_tensor=None, pooling=None, classes=1000, **kwargs): """Instantiates the SqueezeNet architecture. """ if weights not in {'imagenet', None}: raise ValueError('The `weights` argument should be either ' '`None` (random initialization) or `imagenet` ' '(pre-training on ImageNet).') if weights == 'imagenet' and classes != 1000: raise ValueError('If using `weights` as imagenet with `include_top`' ' as true, `classes` should be 1000') input_shape = _obtain_input_shape(input_shape, default_size=227, min_size=48, data_format=K.image_data_format(), require_flatten=include_top) if input_tensor is None: img_input = Input(shape=input_shape) else: #if not K.is_keras_tensor(input_tensor): #img_input = Input(tensor=input_tensor, shape=input_shape) #else: #img_input = input_tensor img_input = input_tensor x = Conv2D(64, (3, 3), strides=(2, 2), padding='valid', name='conv1')(img_input) x = Activation('relu', name='relu_conv1')(x) x = MaxPool2D(pool_size=(3, 3), strides=(2, 2), name='pool1')(x) x = fire_module(x, fire_id=2, squeeze=16, expand=64) x = fire_module(x, fire_id=3, squeeze=16, expand=64) x = MaxPool2D(pool_size=(3, 3), strides=(2, 2), name='pool3')(x) x = fire_module(x, fire_id=4, squeeze=32, expand=128) x = fire_module(x, fire_id=5, squeeze=32, expand=128) x = MaxPool2D(pool_size=(3, 3), strides=(2, 2), name='pool5')(x) x = fire_module(x, fire_id=6, squeeze=48, expand=192) x = fire_module(x, fire_id=7, squeeze=48, expand=192) x = fire_module(x, fire_id=8, squeeze=64, expand=256) x = fire_module(x, fire_id=9, squeeze=64, expand=256) if include_top: # It's not obvious where to cut the network... # Could do the 8th or 9th layer... some work recommends cutting earlier layers. x = Dropout(0.5, name='drop9')(x) x = Conv2D(classes, (1, 1), padding='valid', name='conv10')(x) x = Activation('relu', name='relu_conv10')(x) x = GlobalAveragePooling2D()(x) x = Activation('softmax', name='loss')(x) else: if pooling == 'avg': x = GlobalAveragePooling2D()(x) elif pooling=='max': x = GlobalMaxPooling2D()(x) elif pooling==None: pass else: raise ValueError("Unknown argument for 'pooling'=" + pooling) # Ensure that the model takes into account # any potential predecessors of `input_tensor`. if input_tensor is not None: inputs = get_source_inputs(input_tensor) else: inputs = img_input model = Model(inputs, x, name='squeezenet') # load weights if weights == 'imagenet': if include_top: weights_path = get_file('squeezenet_weights_tf_dim_ordering_tf_kernels.h5', WEIGHTS_PATH, cache_subdir='models') else: weights_path = get_file('squeezenet_weights_tf_dim_ordering_tf_kernels_notop.h5', WEIGHTS_PATH_NO_TOP, cache_subdir='models') model.load_weights(weights_path) 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.') return model if __name__ == '__main__': input_tensor = Input(shape=(None, None, 3), name='image_input') #model = SqueezeNet(include_top=False, input_shape=(416, 416, 3), weights='imagenet') model = SqueezeNet(include_top=True, input_tensor=input_tensor, weights='imagenet') model.summary() import numpy as np #from keras_applications.imagenet_utils import preprocess_input, decode_predictions from tensorflow.keras.applications.resnet50 import preprocess_input, decode_predictions from keras_preprocessing import image model = SqueezeNet() img = image.load_img('../../example/eagle.jpg', target_size=(227, 227)) x = image.img_to_array(img) x = np.expand_dims(x, axis=0) x = preprocess_input(x) preds = model.predict(x) print('Predicted:', decode_predictions(preds))