Instantly share code, notes, and snippets.

Embed
What would you like to do?
Resnet-152 pre-trained model in Keras 2.0
# -*- coding: utf-8 -*-
import cv2
import numpy as np
import copy
from keras.layers import Input, Dense, Conv2D, MaxPooling2D, AveragePooling2D, ZeroPadding2D, Flatten, Activation, add
from keras.optimizers import SGD
from keras.layers.normalization import BatchNormalization
from keras.models import Model
from keras import initializers
from keras.engine import Layer, InputSpec
from keras import backend as K
import sys
sys.setrecursionlimit(3000)
class Scale(Layer):
'''Custom Layer for ResNet used for BatchNormalization.
Learns a set of weights and biases used for scaling the input data.
the output consists simply in an element-wise multiplication of the input
and a sum of a set of constants:
out = in * gamma + beta,
where 'gamma' and 'beta' are the weights and biases larned.
# Arguments
axis: integer, axis along which to normalize in mode 0. For instance,
if your input tensor has shape (samples, channels, rows, cols),
set axis to 1 to normalize per feature map (channels axis).
momentum: momentum in the computation of the
exponential average of the mean and standard deviation
of the data, for feature-wise normalization.
weights: Initialization weights.
List of 2 Numpy arrays, with shapes:
`[(input_shape,), (input_shape,)]`
beta_init: name of initialization function for shift parameter
(see [initializers](../initializers.md)), or alternatively,
Theano/TensorFlow function to use for weights initialization.
This parameter is only relevant if you don't pass a `weights` argument.
gamma_init: name of initialization function for scale parameter (see
[initializers](../initializers.md)), or alternatively,
Theano/TensorFlow function to use for weights initialization.
This parameter is only relevant if you don't pass a `weights` argument.
'''
def __init__(self, weights=None, axis=-1, momentum = 0.9, beta_init='zero', gamma_init='one', **kwargs):
self.momentum = momentum
self.axis = axis
self.beta_init = initializers.get(beta_init)
self.gamma_init = initializers.get(gamma_init)
self.initial_weights = weights
super(Scale, self).__init__(**kwargs)
def build(self, input_shape):
self.input_spec = [InputSpec(shape=input_shape)]
shape = (int(input_shape[self.axis]),)
self.gamma = K.variable(self.gamma_init(shape), name='%s_gamma'%self.name)
self.beta = K.variable(self.beta_init(shape), name='%s_beta'%self.name)
self.trainable_weights = [self.gamma, self.beta]
if self.initial_weights is not None:
self.set_weights(self.initial_weights)
del self.initial_weights
def call(self, x, mask=None):
input_shape = self.input_spec[0].shape
broadcast_shape = [1] * len(input_shape)
broadcast_shape[self.axis] = input_shape[self.axis]
out = K.reshape(self.gamma, broadcast_shape) * x + K.reshape(self.beta, broadcast_shape)
return out
def get_config(self):
config = {"momentum": self.momentum, "axis": self.axis}
base_config = super(Scale, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
def identity_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 nb_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
'''
eps = 1.1e-5
nb_filter1, nb_filter2, nb_filter3 = filters
conv_name_base = 'res' + str(stage) + block + '_branch'
bn_name_base = 'bn' + str(stage) + block + '_branch'
scale_name_base = 'scale' + str(stage) + block + '_branch'
x = Conv2D(nb_filter1, (1, 1), name=conv_name_base + '2a', use_bias=False)(input_tensor)
x = BatchNormalization(epsilon=eps, axis=bn_axis, name=bn_name_base + '2a')(x)
x = Scale(axis=bn_axis, name=scale_name_base + '2a')(x)
x = Activation('relu', name=conv_name_base + '2a_relu')(x)
x = ZeroPadding2D((1, 1), name=conv_name_base + '2b_zeropadding')(x)
x = Conv2D(nb_filter2, (kernel_size, kernel_size), name=conv_name_base + '2b', use_bias=False)(x)
x = BatchNormalization(epsilon=eps, axis=bn_axis, name=bn_name_base + '2b')(x)
x = Scale(axis=bn_axis, name=scale_name_base + '2b')(x)
x = Activation('relu', name=conv_name_base + '2b_relu')(x)
x = Conv2D(nb_filter3, (1, 1), name=conv_name_base + '2c', use_bias=False)(x)
x = BatchNormalization(epsilon=eps, axis=bn_axis, name=bn_name_base + '2c')(x)
x = Scale(axis=bn_axis, name=scale_name_base + '2c')(x)
x = add([x, input_tensor], name='res' + str(stage) + block)
x = Activation('relu', name='res' + str(stage) + block + '_relu')(x)
return x
def conv_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 nb_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
Note that from stage 3, the first conv layer at main path is with subsample=(2,2)
And the shortcut should have subsample=(2,2) as well
'''
eps = 1.1e-5
nb_filter1, nb_filter2, nb_filter3 = filters
conv_name_base = 'res' + str(stage) + block + '_branch'
bn_name_base = 'bn' + str(stage) + block + '_branch'
scale_name_base = 'scale' + str(stage) + block + '_branch'
x = Conv2D(nb_filter1, (1, 1), strides=strides, name=conv_name_base + '2a', use_bias=False)(input_tensor)
x = BatchNormalization(epsilon=eps, axis=bn_axis, name=bn_name_base + '2a')(x)
x = Scale(axis=bn_axis, name=scale_name_base + '2a')(x)
x = Activation('relu', name=conv_name_base + '2a_relu')(x)
x = ZeroPadding2D((1, 1), name=conv_name_base + '2b_zeropadding')(x)
x = Conv2D(nb_filter2, (kernel_size, kernel_size),
name=conv_name_base + '2b', use_bias=False)(x)
x = BatchNormalization(epsilon=eps, axis=bn_axis, name=bn_name_base + '2b')(x)
x = Scale(axis=bn_axis, name=scale_name_base + '2b')(x)
x = Activation('relu', name=conv_name_base + '2b_relu')(x)
x = Conv2D(nb_filter3, (1, 1), name=conv_name_base + '2c', use_bias=False)(x)
x = BatchNormalization(epsilon=eps, axis=bn_axis, name=bn_name_base + '2c')(x)
x = Scale(axis=bn_axis, name=scale_name_base + '2c')(x)
shortcut = Conv2D(nb_filter3, (1, 1), strides=strides,
name=conv_name_base + '1', use_bias=False)(input_tensor)
shortcut = BatchNormalization(epsilon=eps, axis=bn_axis, name=bn_name_base + '1')(shortcut)
shortcut = Scale(axis=bn_axis, name=scale_name_base + '1')(shortcut)
x = add([x, shortcut], name='res' + str(stage) + block)
x = Activation('relu', name='res' + str(stage) + block + '_relu')(x)
return x
def resnet152_model(weights_path=None):
'''Instantiate the ResNet152 architecture,
# Arguments
weights_path: path to pretrained weight file
# Returns
A Keras model instance.
'''
eps = 1.1e-5
# Handle Dimension Ordering for different backends
global bn_axis
if K.image_dim_ordering() == 'tf':
bn_axis = 3
img_input = Input(shape=(224, 224, 3), name='data')
else:
bn_axis = 1
img_input = Input(shape=(3, 224, 224), name='data')
x = ZeroPadding2D((3, 3), name='conv1_zeropadding')(img_input)
x = Conv2D(64, (7, 7), strides=(2, 2), name='conv1', use_bias=False)(x)
x = BatchNormalization(epsilon=eps, axis=bn_axis, name='bn_conv1')(x)
x = Scale(axis=bn_axis, name='scale_conv1')(x)
x = Activation('relu', name='conv1_relu')(x)
x = MaxPooling2D((3, 3), strides=(2, 2), name='pool1')(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')
for i in range(1,8):
x = identity_block(x, 3, [128, 128, 512], stage=3, block='b'+str(i))
x = conv_block(x, 3, [256, 256, 1024], stage=4, block='a')
for i in range(1,36):
x = identity_block(x, 3, [256, 256, 1024], stage=4, block='b'+str(i))
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_fc = AveragePooling2D((7, 7), name='avg_pool')(x)
x_fc = Flatten()(x_fc)
x_fc = Dense(1000, activation='softmax', name='fc1000')(x_fc)
model = Model(img_input, x_fc)
# load weights
if weights_path:
model.load_weights(weights_path, by_name=True)
return model
if __name__ == '__main__':
im = cv2.resize(cv2.imread('cat.jpg'), (224, 224)).astype(np.float32)
# Remove train image mean
im[:,:,0] -= 103.939
im[:,:,1] -= 116.779
im[:,:,2] -= 123.68
if K.image_dim_ordering() == 'th':
# Transpose image dimensions (Theano uses the channels as the 1st dimension)
im = im.transpose((2,0,1))
# Use pre-trained weights for Theano backend
weights_path = 'resnet152_weights_th.h5'
else:
# Use pre-trained weights for Tensorflow backend
weights_path = 'resnet152_weights_tf.h5'
# Insert a new dimension for the batch_size
im = np.expand_dims(im, axis=0)
# Test pretrained model
model = resnet152_model(weights_path)
sgd = SGD(lr=1e-2, decay=1e-6, momentum=0.9, nesterov=True)
model.compile(optimizer=sgd, loss='categorical_crossentropy', metrics=['accuracy'])
preds = model.predict(im)
print(np.argmax(preds))
@hbake001

This comment has been minimized.

hbake001 commented Oct 17, 2017

Hi

I got the following error while running the code

Using Theano backend.
Traceback (most recent call last):
  File "resnet152.py", line 249, in <module>
    score = model.evaluate(x_test, ((y_test)))
  File "c:\users\engadmin\anaconda3\lib\site-packages\keras\engine\training.py",
 line 1646, in evaluate
    batch_size=batch_size)
  File "c:\users\engadmin\anaconda3\lib\site-packages\keras\engine\training.py",
 line 1382, in _standardize_user_data
    exception_prefix='target')
  File "c:\users\engadmin\anaconda3\lib\site-packages\keras\engine\training.py",
 line 144, in _standardize_input_data
    str(array.shape))
ValueError: Error when checking target: expected fc1000 to have shape (None, 10)
 but got array with shape (10000, 1)

(C:\Users\engadmin\Anaconda3) C:\Users\engadmin\.spyder-py3>
(C:\Users\engadmin\Anaconda3) C:\Users\engadmin\.spyder-py3>
(C:\Users\engadmin\Anaconda3) C:\Users\engadmin\.spyder-py3>python resnet152.py
Using Theano backend.
Traceback (most recent call last):
  File "c:\users\engadmin\anaconda3\lib\site-packages\theano\compile\function_mo
dule.py", line 884, in __call__
    self.fn() if output_subset is None else\
ValueError: Input dimension mis-match. (input[0].shape[1] = 10, input[1].shape[1
] = 1000)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "resnet152.py", line 249, in <module>
    score = model.evaluate(x_test, (np_utils.to_categorical(y_test)))
  File "c:\users\engadmin\anaconda3\lib\site-packages\keras\engine\training.py",
 line 1657, in evaluate
    steps=steps)
  File "c:\users\engadmin\anaconda3\lib\site-packages\keras\engine\training.py",
 line 1339, in _test_loop
    batch_outs = f(ins_batch)
  File "c:\users\engadmin\anaconda3\lib\site-packages\keras\backend\theano_backe
nd.py", line 1222, in __call__
    return self.function(*inputs)
  File "c:\users\engadmin\anaconda3\lib\site-packages\theano\compile\function_mo
dule.py", line 898, in __call__
    storage_map=getattr(self.fn, 'storage_map', None))
  File "c:\users\engadmin\anaconda3\lib\site-packages\theano\gof\link.py", line
325, in raise_with_op
    reraise(exc_type, exc_value, exc_trace)
  File "c:\users\engadmin\anaconda3\lib\site-packages\six.py", line 685, in rera
ise
    raise value.with_traceback(tb)
  File "c:\users\engadmin\anaconda3\lib\site-packages\theano\compile\function_mo
dule.py", line 884, in __call__
    self.fn() if output_subset is None else\
ValueError: Input dimension mis-match. (input[0].shape[1] = 10, input[1].shape[1
] = 1000)
Apply node that caused the error: Elemwise{Composite{(i0 * log(clip((i1 / i2), i
3, i4)))}}[(0, 1)](/fc1000_target, SoftmaxWithBias.0, InplaceDimShuffle{0,x}.0,
TensorConstant{(1, 1) of 1e-07}, TensorConstant{(1, 1) of 1.0})
Toposort index: 6318
Inputs types: [TensorType(float32, matrix), TensorType(float32, matrix), TensorT
ype(float32, col), TensorType(float32, (True, True)), TensorType(float32, (True,
 True))]
Inputs shapes: [(32, 10), (32, 1000), (32, 1), (1, 1), (1, 1)]
Inputs strides: [(40, 4), (4000, 4), (4, 4), (4, 4), (4, 4)]
Inputs values: ['not shown', 'not shown', 'not shown', array([[  1.00000001e-07]
], dtype=float32), array([[ 0.99999988]], dtype=float32)]
Outputs clients: [[Sum{axis=[1], acc_dtype=float64}(Elemwise{Composite{(i0 * log
(clip((i1 / i2), i3, i4)))}}[(0, 1)].0)]]

HINT: Re-running with most Theano optimization disabled could give you a back-tr
ace of when this node was created. This can be done with by setting the Theano f
lag 'optimizer=fast_compile'. If that does not work, Theano optimizations can be
 disabled with 'optimizer=None'.
HINT: Use the Theano flag 'exception_verbosity=high' for a debugprint and storag
e map footprint of this apply node.
@mvoelk

This comment has been minimized.

Owner

mvoelk commented Jan 19, 2018

@hbake001 Could you fix it? I only used tensorflow backend...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment