From 99f564e9724d3456fc5b48b9dcd6254c83611242 Mon Sep 17 00:00:00 2001 From: Francois Chollet Date: Wed, 3 Aug 2016 11:08:48 -0700 Subject: [PATCH] Style fixes and small bug fixes --- examples/mnist_mlp.py | 15 ++++- examples/resnet_50.py | 101 +++++++++++++++++----------------- keras/backend/__init__.py | 8 +++ keras/backend/common.py | 7 +++ keras/engine/topology.py | 24 ++++---- keras/layers/convolutional.py | 35 +++++++++--- keras/layers/local.py | 8 ++- keras/layers/pooling.py | 16 ++++-- keras/models.py | 3 +- keras/preprocessing/image.py | 20 +++++-- keras/utils/data_utils.py | 5 +- keras/utils/layer_utils.py | 20 +++++++ keras/utils/np_utils.py | 1 + 13 files changed, 177 insertions(+), 86 deletions(-) diff --git a/examples/mnist_mlp.py b/examples/mnist_mlp.py index c7f654d4a..a31d3e5b0 100644 --- a/examples/mnist_mlp.py +++ b/examples/mnist_mlp.py @@ -53,8 +53,21 @@ model.compile(loss='categorical_crossentropy', metrics=['accuracy']) history = model.fit(X_train, Y_train, - batch_size=batch_size, nb_epoch=nb_epoch, + batch_size=batch_size, nb_epoch=3, verbose=1, validation_data=(X_test, Y_test)) score = model.evaluate(X_test, Y_test, verbose=0) print('Test score:', score[0]) print('Test accuracy:', score[1]) + +model.save('tmp.h5') + +from keras.models import load_model +model = load_model('tmp.h5') + +score = model.evaluate(X_test, Y_test, verbose=0) +print('Test score:', score[0]) +print('Test accuracy:', score[1]) + +model.fit(X_train, Y_train, + batch_size=batch_size, nb_epoch=3, + verbose=1, validation_data=(X_test, Y_test)) diff --git a/examples/resnet_50.py b/examples/resnet_50.py index d865b078c..f2fe88afa 100644 --- a/examples/resnet_50.py +++ b/examples/resnet_50.py @@ -1,14 +1,14 @@ '''This script demonstrates how to build a deep residual network using the Keras functional API. -get_resne50 returns the deep residual network model (50 layers) +get_resnet50() returns the deep residual network model (50 layers) Please visit Kaiming He's GitHub homepage: https://github.com/KaimingHe for more information. The related paper is -"Deep Residual Learning for Image Recognition" +'Deep Residual Learning for Image Recognition' Kaiming He, Xiangyu Zhang, Shaoqing Ren, Jian Sun http://arxiv.org/abs/1512.03385 @@ -17,12 +17,14 @@ Pretrained weights were converted from Kaiming He's caffe model directly. For now we provide weights for the tensorflow backend only, thus use 'tf' dim_ordering (e.g. input_shape=(224, 224, 3) for 224*224 color image) would accelerate the computation, but we also provide weights for 'th' dim_ordering for compatibility. -please donwload them at: -http://pan.baidu.com/s/1o8pO2q2 ('th' dim ordering, For China) -http://pan.baidu.com/s/1pLanuTt ('tf' dim ordering, For China) +You can set your default dim ordering in your Keras config file at ~/.keras/keras.json -https://drive.google.com/open?id=0B4ChsjFJvew3NVQ2U041Q0xHRHM ('th' dim ordering, For other countries) -https://drive.google.com/open?id=0B4ChsjFJvew3NWN5THdxcTdSWmc ('tf' dim ordering, For other countries) +please donwload them at: +http://pan.baidu.com/s/1o8pO2q2 ('th' dim ordering, for China) +http://pan.baidu.com/s/1pLanuTt ('tf' dim ordering, for China) + +https://drive.google.com/open?id=0B4ChsjFJvew3NVQ2U041Q0xHRHM ('th' dim ordering, for other countries) +https://drive.google.com/open?id=0B4ChsjFJvew3NWN5THdxcTdSWmc ('tf' dim ordering, for other countries) @author: BigMoyan, University of Electronic Science and Technology of China ''' @@ -44,36 +46,37 @@ import numpy as np # branch: '1' for shortcut and '2' for main path # layer: 'a','b','c'... for different layers in a block + def identity_block(input_tensor, kernel_size, filters, stage, block): - """ - the identity_block is the block that has no conv layer at shortcut - params: + '''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 - """ + ''' dim_ordering = K.image_dim_ordering() nb_filter1, nb_filter2, nb_filter3 = filters if dim_ordering == 'tf': - axis = 3 + bn_axis = 3 else: - axis = 1 + bn_axis = 1 conv_name_base = 'res' + str(stage) + block + '_branch' bn_name_base = 'bn' + str(stage) + block + '_branch' out = Convolution2D(nb_filter1, 1, 1, dim_ordering=dim_ordering, name=conv_name_base + '2a')(input_tensor) - out = BatchNormalization(axis=axis, name=bn_name_base + '2a')(out) + out = BatchNormalization(axis=bn_axis, name=bn_name_base + '2a')(out) out = Activation('relu')(out) out = out = Convolution2D(nb_filter2, kernel_size, kernel_size, border_mode='same', dim_ordering=dim_ordering, name=conv_name_base + '2b')(out) - out = BatchNormalization(axis=axis, name=bn_name_base + '2b')(out) + out = BatchNormalization(axis=bn_axis, name=bn_name_base + '2b')(out) out = Activation('relu')(out) out = Convolution2D(nb_filter3, 1, 1, dim_ordering=dim_ordering, name=conv_name_base + '2c')(out) - out = BatchNormalization(axis=axis, name=bn_name_base + '2c')(out) + out = BatchNormalization(axis=bn_axis, name=bn_name_base + '2c')(out) out = merge([out, input_tensor], mode='sum') out = Activation('relu')(out) @@ -81,9 +84,9 @@ def identity_block(input_tensor, kernel_size, filters, stage, block): 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 - params: + '''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 @@ -92,32 +95,32 @@ def conv_block(input_tensor, kernel_size, filters, stage, block, strides=(2, 2)) Note that from stage 3, the first conv layer at main path is with subsample=(2,2) And the shortcut should has subsample=(2,2) as well - """ + ''' nb_filter1, nb_filter2, nb_filter3 = filters dim_ordering = K.image_dim_ordering() if dim_ordering == 'tf': - axis = 3 + bn_axis = 3 else: - axis = 1 + bn_axis = 1 conv_name_base = 'res' + str(stage) + block + '_branch' bn_name_base = 'bn' + str(stage) + block + '_branch' out = Convolution2D(nb_filter1, 1, 1, subsample=strides, dim_ordering=dim_ordering, name=conv_name_base + '2a')(input_tensor) - out = BatchNormalization(axis=axis, name=bn_name_base + '2a')(out) + out = BatchNormalization(axis=bn_axis, name=bn_name_base + '2a')(out) out = Activation('relu')(out) out = Convolution2D(nb_filter2, kernel_size, kernel_size, border_mode='same', dim_ordering=dim_ordering, name=conv_name_base + '2b')(out) - out = BatchNormalization(axis=axis, name=bn_name_base + '2b')(out) + out = BatchNormalization(axis=bn_axis, name=bn_name_base + '2b')(out) out = Activation('relu')(out) out = Convolution2D(nb_filter3, 1, 1, dim_ordering=dim_ordering, name=conv_name_base + '2c')(out) - out = BatchNormalization(axis=axis, name=bn_name_base + '2c')(out) + out = BatchNormalization(axis=bn_axis, name=bn_name_base + '2c')(out) shortcut = Convolution2D(nb_filter3, 1, 1, subsample=strides, dim_ordering=dim_ordering, name=conv_name_base + '1')(input_tensor) - shortcut = BatchNormalization(axis=axis, name=bn_name_base + '1')(shortcut) + shortcut = BatchNormalization(axis=bn_axis, name=bn_name_base + '1')(shortcut) out = merge([out, shortcut], mode='sum') out = Activation('relu')(out) @@ -125,48 +128,46 @@ def conv_block(input_tensor, kernel_size, filters, stage, block, strides=(2, 2)) def read_img(img_path): - """ - this function returns preprocessed image - """ + '''This function returns a preprocessed image + ''' dim_ordering = K.image_dim_ordering() mean = (103.939, 116.779, 123.68) img = load_img(img_path, target_size=(224, 224)) img = img_to_array(img, dim_ordering=dim_ordering) - # decenterize - img[0, :, :] -= mean[0] - img[1, :, :] -= mean[1] - img[2, :, :] -= mean[2] - - # 'RGB'->'BGR' if dim_ordering == 'th': + img[0, :, :] -= mean[0] + img[1, :, :] -= mean[1] + img[2, :, :] -= mean[2] + # 'RGB'->'BGR' img = img[::-1, :, :] else: + img[:, :, 0] -= mean[0] + img[:, :, 1] -= mean[1] + img[:, :, 2] -= mean[2] img = img[:, :, ::-1] - # expand dim for test img = np.expand_dims(img, axis=0) return img def get_resnet50(): - """ - this function returns the 50-layer residual network model + '''This function returns the 50-layer residual network model you should load pretrained weights if you want to use it directly. Note that since the pretrained weights is converted from caffemodel the order of channels for input image should be 'BGR' (the channel order of caffe) - """ + ''' if K.image_dim_ordering() == 'tf': inp = Input(shape=(224, 224, 3)) - axis = 3 + bn_axis = 3 else: inp = Input(shape=(3, 224, 224)) - axis = 1 + bn_axis = 1 dim_ordering = K.image_dim_ordering() out = ZeroPadding2D((3, 3), dim_ordering=dim_ordering)(inp) out = Convolution2D(64, 7, 7, subsample=(2, 2), dim_ordering=dim_ordering, name='conv1')(out) - out = BatchNormalization(axis=axis, name='bn_conv1')(out) + out = BatchNormalization(axis=bn_axis, name='bn_conv1')(out) out = Activation('relu')(out) out = MaxPooling2D((3, 3), strides=(2, 2), dim_ordering=dim_ordering)(out) @@ -200,17 +201,19 @@ def get_resnet50(): if __name__ == '__main__': - K.set_image_dim_ordering('tf') weights_file = K.image_dim_ordering() + '_dim_ordering_resnet50.h5' resnet_model = get_resnet50() resnet_model.load_weights(weights_file) - test_img1 = read_img('cat.jpg') - test_img2 = read_img('airplane.jpg') - # you may download synset_words from address given at the begining of this file - class_table = open('synset_words', 'r') + + # you may download synset_words from the address given at the begining of this file + class_table = open('synset_words.txt', 'r') lines = class_table.readlines() - print "result for test 1 is" + + test_img1 = read_img('cat.jpg') + print 'result for test 1 is' print lines[np.argmax(resnet_model.predict(test_img1)[0])] - print "result for test 2 is" + + test_img2 = read_img('elephant.jpg') + print 'result for test 2 is' print lines[np.argmax(resnet_model.predict(test_img2)[0])] class_table.close() diff --git a/keras/backend/__init__.py b/keras/backend/__init__.py index d5fb841b6..08685b735 100644 --- a/keras/backend/__init__.py +++ b/keras/backend/__init__.py @@ -11,6 +11,7 @@ from .common import get_uid from .common import cast_to_floatx from .common import image_dim_ordering from .common import set_image_dim_ordering +from .common import is_keras_tensor _keras_base_dir = os.path.expanduser('~') if not os.access(_keras_base_dir, os.W_OK): @@ -60,3 +61,10 @@ elif _BACKEND == 'tensorflow': from .tensorflow_backend import * else: raise Exception('Unknown backend: ' + str(_BACKEND)) + + +def backend(): + '''Publicly accessible method + for determining the current backend. + ''' + return _BACKEND diff --git a/keras/backend/common.py b/keras/backend/common.py index 074d474fc..fdf7a04e3 100644 --- a/keras/backend/common.py +++ b/keras/backend/common.py @@ -69,3 +69,10 @@ def get_uid(prefix=''): def reset_uids(): global _UID_PREFIXES _UID_PREFIXES = defaultdict(int) + + +def is_keras_tensor(x): + if hasattr(x, '_keras_shape'): + return True + else: + return False diff --git a/keras/engine/topology.py b/keras/engine/topology.py index 1000c0ba3..5a5cd1532 100644 --- a/keras/engine/topology.py +++ b/keras/engine/topology.py @@ -696,15 +696,15 @@ class Layer(object): ' outbound layers. ' 'This will cause part of your model ' 'to be disconnected.') - if not shape: - if hasattr(K, 'int_shape'): - shape = K.int_shape(input_tensor) - else: - raise Exception('`set_input` needs to know the shape ' - 'of the `input_tensor` it receives, but ' - 'Keras was not able to infer it automatically.' - ' Specify it via: ' - '`model.set_input(input_tensor, shape)`') + if hasattr(K, 'int_shape'): + # auto-infered shape takes priority + shape = K.int_shape(input_tensor) + elif not shape: + raise Exception('`set_input` needs to know the shape ' + 'of the `input_tensor` it receives, but ' + 'Keras was not able to infer it automatically.' + ' Specify it via: ' + '`model.set_input(input_tensor, shape)`') # reset layer connections self.inbound_nodes = [] self.outbound_nodes = [] @@ -830,6 +830,10 @@ class Layer(object): 'ill-defined for the layer. ' + 'Use `get_output_shape_at(node_index)` instead.') + @property + def weights(self): + return self.trainable_weights + self.non_trainable_weights + def set_weights(self, weights): '''Sets the weights of the layer, from Numpy arrays. @@ -845,7 +849,7 @@ class Layer(object): raise Exception('You called `set_weights(weights)` on layer "' + self.name + '" with a weight list of length ' + str(len(weights)) + ', but the layer was expecting ' + str(len(params)) + - ' weights. Provided weights: ' + str(weights)) + ' weights. Provided weights: ' + str(weights)[:50] + '...') if not params: return weight_value_tuples = [] diff --git a/keras/layers/convolutional.py b/keras/layers/convolutional.py index 66beb6561..019b66d14 100644 --- a/keras/layers/convolutional.py +++ b/keras/layers/convolutional.py @@ -254,11 +254,12 @@ class Convolution2D(Layer): ''' def __init__(self, nb_filter, nb_row, nb_col, init='glorot_uniform', activation='linear', weights=None, - border_mode='valid', subsample=(1, 1), dim_ordering=K.image_dim_ordering(), + border_mode='valid', subsample=(1, 1), dim_ordering='default', W_regularizer=None, b_regularizer=None, activity_regularizer=None, W_constraint=None, b_constraint=None, bias=True, **kwargs): - + if dim_ordering == 'default': + dim_ordering = K.image_dim_ordering() if border_mode not in {'valid', 'same'}: raise Exception('Invalid border mode for Convolution2D:', border_mode) self.nb_filter = nb_filter @@ -526,10 +527,12 @@ class AtrousConvolution2D(Convolution2D): def __init__(self, nb_filter, nb_row, nb_col, init='glorot_uniform', activation='linear', weights=None, border_mode='valid', subsample=(1, 1), - atrous_rate=(1, 1), dim_ordering=K.image_dim_ordering(), + atrous_rate=(1, 1), dim_ordering='default', W_regularizer=None, b_regularizer=None, activity_regularizer=None, W_constraint=None, b_constraint=None, bias=True, **kwargs): + if dim_ordering == 'default': + dim_ordering = K.image_dim_ordering() if border_mode not in {'valid', 'same'}: raise Exception('Invalid border mode for AtrousConv2D:', border_mode) @@ -668,7 +671,7 @@ class SeparableConvolution2D(Layer): def __init__(self, nb_filter, nb_row, nb_col, init='glorot_uniform', activation='linear', weights=None, border_mode='valid', subsample=(1, 1), - depth_multiplier=1, dim_ordering=K.image_dim_ordering(), + depth_multiplier=1, dim_ordering='default', depthwise_regularizer=None, pointwise_regularizer=None, b_regularizer=None, activity_regularizer=None, depthwise_constraint=None, pointwise_constraint=None, @@ -679,6 +682,9 @@ class SeparableConvolution2D(Layer): raise Exception('SeparableConv2D is only available ' 'with TensorFlow for the time being.') + if dim_ordering == 'default': + dim_ordering = K.image_dim_ordering() + if border_mode not in {'valid', 'same'}: raise Exception('Invalid border mode for SeparableConv2D:', border_mode) @@ -879,10 +885,13 @@ class Convolution3D(Layer): def __init__(self, nb_filter, kernel_dim1, kernel_dim2, kernel_dim3, init='glorot_uniform', activation='linear', weights=None, - border_mode='valid', subsample=(1, 1, 1), dim_ordering=K.image_dim_ordering(), + border_mode='valid', subsample=(1, 1, 1), dim_ordering='default', W_regularizer=None, b_regularizer=None, activity_regularizer=None, W_constraint=None, b_constraint=None, bias=True, **kwargs): + if dim_ordering == 'default': + dim_ordering = K.image_dim_ordering() + if border_mode not in {'valid', 'same'}: raise Exception('Invalid border mode for Convolution3D:', border_mode) self.nb_filter = nb_filter @@ -1074,7 +1083,9 @@ class UpSampling2D(Layer): `(samples, upsampled_rows, upsampled_cols, channels)` if dim_ordering='tf'. ''' - def __init__(self, size=(2, 2), dim_ordering=K.image_dim_ordering(), **kwargs): + def __init__(self, size=(2, 2), dim_ordering='default', **kwargs): + if dim_ordering == 'default': + dim_ordering = K.image_dim_ordering() self.size = tuple(size) assert dim_ordering in {'tf', 'th'}, 'dim_ordering must be in {tf, th}' self.dim_ordering = dim_ordering @@ -1131,7 +1142,9 @@ class UpSampling3D(Layer): `(samples, upsampled_dim1, upsampled_dim2, upsampled_dim3, channels)` if dim_ordering='tf'. ''' - def __init__(self, size=(2, 2, 2), dim_ordering=K.image_dim_ordering(), **kwargs): + def __init__(self, size=(2, 2, 2), dim_ordering='default', **kwargs): + if dim_ordering == 'default': + dim_ordering = K.image_dim_ordering() self.size = tuple(size) assert dim_ordering in {'tf', 'th'}, 'dim_ordering must be in {tf, th}' self.dim_ordering = dim_ordering @@ -1222,8 +1235,10 @@ class ZeroPadding2D(Layer): (samples, depth, first_padded_axis, second_padded_axis) ''' - def __init__(self, padding=(1, 1), dim_ordering=K.image_dim_ordering(), **kwargs): + def __init__(self, padding=(1, 1), dim_ordering='default', **kwargs): super(ZeroPadding2D, self).__init__(**kwargs) + if dim_ordering == 'default': + dim_ordering = K.image_dim_ordering() self.padding = tuple(padding) assert dim_ordering in {'tf', 'th'}, 'dim_ordering must be in {tf, th}' self.dim_ordering = dim_ordering @@ -1280,8 +1295,10 @@ class ZeroPadding3D(Layer): (samples, depth, first_padded_axis, second_padded_axis, third_axis_to_pad) ''' - def __init__(self, padding=(1, 1, 1), dim_ordering=K.image_dim_ordering(), **kwargs): + def __init__(self, padding=(1, 1, 1), dim_ordering='default', **kwargs): super(ZeroPadding3D, self).__init__(**kwargs) + if dim_ordering == 'default': + dim_ordering = K.image_dim_ordering() self.padding = tuple(padding) assert dim_ordering in {'tf', 'th'}, 'dim_ordering must be in {tf, th}' self.dim_ordering = dim_ordering diff --git a/keras/layers/local.py b/keras/layers/local.py index 265bd844f..046632439 100644 --- a/keras/layers/local.py +++ b/keras/layers/local.py @@ -75,7 +75,7 @@ class LocallyConnected1D(Layer): W_constraint=None, b_constraint=None, bias=True, input_dim=None, input_length=None, **kwargs): if border_mode != 'valid': - raise Exception('Invalid border mode for Convolution2D ' + raise Exception('Invalid border mode for LocallyConnected1D ' '(only "valid" is supported):', border_mode) self.nb_filter = nb_filter self.filter_length = filter_length @@ -251,12 +251,14 @@ class LocallyConnected2D(Layer): def __init__(self, nb_filter, nb_row, nb_col, init='glorot_uniform', activation='linear', weights=None, border_mode='valid', subsample=(1, 1), - dim_ordering=K.image_dim_ordering(), + dim_ordering='default', W_regularizer=None, b_regularizer=None, activity_regularizer=None, W_constraint=None, b_constraint=None, bias=True, **kwargs): + if dim_ordering == 'default': + dim_ordering = K.image_dim_ordering() if border_mode != 'valid': - raise Exception('Invalid border mode for Convolution2D ' + raise Exception('Invalid border mode for LocallyConnected2D ' '(only "valid" is supported):', border_mode) self.nb_filter = nb_filter self.nb_row = nb_row diff --git a/keras/layers/pooling.py b/keras/layers/pooling.py index c92e4dc65..b317a2d4d 100644 --- a/keras/layers/pooling.py +++ b/keras/layers/pooling.py @@ -114,8 +114,10 @@ class _Pooling2D(Layer): ''' def __init__(self, pool_size=(2, 2), strides=None, border_mode='valid', - dim_ordering=K.image_dim_ordering(), **kwargs): + dim_ordering='default', **kwargs): super(_Pooling2D, self).__init__(**kwargs) + if dim_ordering == 'default': + dim_ordering = K.image_dim_ordering() self.pool_size = tuple(pool_size) if strides is None: strides = self.pool_size @@ -199,7 +201,7 @@ class MaxPooling2D(_Pooling2D): ''' def __init__(self, pool_size=(2, 2), strides=None, border_mode='valid', - dim_ordering=K.image_dim_ordering(), **kwargs): + dim_ordering='default', **kwargs): super(MaxPooling2D, self).__init__(pool_size, strides, border_mode, dim_ordering, **kwargs) @@ -241,7 +243,7 @@ class AveragePooling2D(_Pooling2D): ''' def __init__(self, pool_size=(2, 2), strides=None, border_mode='valid', - dim_ordering=K.image_dim_ordering(), **kwargs): + dim_ordering='default', **kwargs): super(AveragePooling2D, self).__init__(pool_size, strides, border_mode, dim_ordering, **kwargs) @@ -257,8 +259,10 @@ class _Pooling3D(Layer): ''' def __init__(self, pool_size=(2, 2, 2), strides=None, border_mode='valid', - dim_ordering=K.image_dim_ordering(), **kwargs): + dim_ordering='default', **kwargs): super(_Pooling3D, self).__init__(**kwargs) + if dim_ordering == 'default': + dim_ordering = K.image_dim_ordering() self.pool_size = tuple(pool_size) if strides is None: strides = self.pool_size @@ -344,7 +348,7 @@ class MaxPooling3D(_Pooling3D): ''' def __init__(self, pool_size=(2, 2, 2), strides=None, border_mode='valid', - dim_ordering=K.image_dim_ordering(), **kwargs): + dim_ordering='default', **kwargs): super(MaxPooling3D, self).__init__(pool_size, strides, border_mode, dim_ordering, **kwargs) @@ -384,7 +388,7 @@ class AveragePooling3D(_Pooling3D): ''' def __init__(self, pool_size=(2, 2, 2), strides=None, border_mode='valid', - dim_ordering=K.image_dim_ordering(), **kwargs): + dim_ordering='default', **kwargs): super(AveragePooling3D, self).__init__(pool_size, strides, border_mode, dim_ordering, **kwargs) diff --git a/keras/models.py b/keras/models.py index c7049d247..a44b1e069 100644 --- a/keras/models.py +++ b/keras/models.py @@ -337,6 +337,7 @@ class Sequential(Model): self.inbound_nodes[0].output_tensors = self.outputs self.inbound_nodes[0].output_shapes = [self.outputs[0]._keras_shape] self.built = False + self._flattened_layers = None def call(self, x, mask=None): if not self.built: @@ -467,7 +468,7 @@ class Sequential(Model): ''' # support for legacy behavior for layer in self.flattened_layers: - nb_param = len(layer.get_weights()) + nb_param = len(layer.weights) layer.set_weights(weights[:nb_param]) weights = weights[nb_param:] diff --git a/keras/preprocessing/image.py b/keras/preprocessing/image.py index bf3ad18e3..ccf762a3e 100644 --- a/keras/preprocessing/image.py +++ b/keras/preprocessing/image.py @@ -118,8 +118,10 @@ def flip_axis(x, axis): return x -def array_to_img(x, dim_ordering=K.image_dim_ordering(), scale=True): +def array_to_img(x, dim_ordering='default', scale=True): from PIL import Image + if dim_ordering == 'default': + dim_ordering = K.image_dim_ordering() if dim_ordering == 'th': x = x.transpose(1, 2, 0) if scale: @@ -136,7 +138,9 @@ def array_to_img(x, dim_ordering=K.image_dim_ordering(), scale=True): raise Exception('Unsupported channel number: ', x.shape[2]) -def img_to_array(img, dim_ordering=K.image_dim_ordering()): +def img_to_array(img, dim_ordering='default'): + if dim_ordering == 'default': + dim_ordering = K.image_dim_ordering() if dim_ordering not in ['th', 'tf']: raise Exception('Unknown dim_ordering: ', dim_ordering) # image has dim_ordering (height, width, channel) @@ -222,7 +226,9 @@ class ImageDataGenerator(object): horizontal_flip=False, vertical_flip=False, rescale=None, - dim_ordering=K.image_dim_ordering()): + dim_ordering='default'): + if dim_ordering == 'default': + dim_ordering = K.image_dim_ordering() self.__dict__.update(locals()) self.mean = None self.std = None @@ -446,12 +452,14 @@ class NumpyArrayIterator(Iterator): def __init__(self, X, y, image_data_generator, batch_size=32, shuffle=False, seed=None, - dim_ordering=K.image_dim_ordering(), + dim_ordering='default', save_to_dir=None, save_prefix='', save_format='jpeg'): if y is not None and len(X) != len(y): raise Exception('X (images tensor) and y (labels) ' 'should have the same length. ' 'Found: X.shape = %s, y.shape = %s' % (np.asarray(X).shape, np.asarray(y).shape)) + if dim_ordering == 'default': + dim_ordering = K.image_dim_ordering() self.X = X self.y = y self.image_data_generator = image_data_generator @@ -493,10 +501,12 @@ class DirectoryIterator(Iterator): def __init__(self, directory, image_data_generator, target_size=(256, 256), color_mode='rgb', - dim_ordering=K.image_dim_ordering, + dim_ordering='default', classes=None, class_mode='categorical', batch_size=32, shuffle=True, seed=None, save_to_dir=None, save_prefix='', save_format='jpeg'): + if dim_ordering == 'default': + dim_ordering = K.image_dim_ordering() self.directory = directory self.image_data_generator = image_data_generator self.target_size = tuple(target_size) diff --git a/keras/utils/data_utils.py b/keras/utils/data_utils.py index 43bacc093..f8df99cef 100644 --- a/keras/utils/data_utils.py +++ b/keras/utils/data_utils.py @@ -37,11 +37,12 @@ else: from six.moves.urllib.request import urlretrieve -def get_file(fname, origin, untar=False, md5_hash=None): +def get_file(fname, origin, untar=False, + md5_hash=None, cache_subdir='datasets'): datadir_base = os.path.expanduser(os.path.join('~', '.keras')) if not os.access(datadir_base, os.W_OK): datadir_base = os.path.join('/tmp', '.keras') - datadir = os.path.join(datadir_base, 'datasets') + datadir = os.path.join(datadir_base, cache_subdir) if not os.path.exists(datadir): os.makedirs(datadir) diff --git a/keras/utils/layer_utils.py b/keras/utils/layer_utils.py index 7f1c09dbf..77d51fcce 100644 --- a/keras/utils/layer_utils.py +++ b/keras/utils/layer_utils.py @@ -1,6 +1,7 @@ from __future__ import print_function from .generic_utils import get_from_module +from .np_utils import convert_kernel from ..layers import * from ..models import Model, Sequential, Graph from .. import backend as K @@ -97,3 +98,22 @@ def print_summary(layers, relevant_nodes=None, line_length=100, positions=[.33, print('Total params: %s' % total_params) print('_' * line_length) + + +def convert_all_kernels_in_model(model): + # Note: SeparableConvolution not included + # since only supported by TF. + conv_classes = { + 'Convolution1D', + 'Convolution2D', + 'Convolution3D', + 'AtrousConvolution2D', + 'Deconvolution2D', + } + to_assign = [] + for layer in model.layers: + if layer.__class__.__name__ in conv_classes: + original_w = K.get_value(layer.W) + converted_w = convert_kernel(original_w) + to_assign.append((layer.W, converted_w)) + K.batch_set_value(to_assign) diff --git a/keras/utils/np_utils.py b/keras/utils/np_utils.py index 687f1d2f8..6243f91be 100644 --- a/keras/utils/np_utils.py +++ b/keras/utils/np_utils.py @@ -121,6 +121,7 @@ def conv_output_length(input_length, filter_size, border_mode, stride, dilation= output_length = input_length - dilated_filter_size + 1 return (output_length + stride - 1) // stride + def conv_input_length(output_length, filter_size, border_mode, stride): if output_length is None: return None