def test_dense(self): """ Test the conversion of Dense layer. """ from keras.layers import Dense # Create a simple Keras model model = Sequential() model.add(Dense(32, input_dim=16)) input_names = ['input'] output_names = ['output'] spec = keras.convert(model, input_names, output_names).get_spec() self.assertIsNotNone(spec) # Test the model class self.assertIsNotNone(spec.description) self.assertTrue(spec.HasField('neuralNetwork')) # Test the inputs and outputs self.assertEquals(len(spec.description.input), len(input_names)) six.assertCountEqual(self, input_names, [x.name for x in spec.description.input]) self.assertEquals(len(spec.description.output), len(output_names)) six.assertCountEqual(self, output_names, [x.name for x in spec.description.output]) # Test the layer parameters. layers = spec.neuralNetwork.layers layer_0 = layers[0] self.assertIsNotNone(layer_0.innerProduct)
def test_permute(self): """ Test the conversion of pooling layer. """ from keras.layers.core import Permute # Create a simple Keras model model = Sequential() model.add(Permute((3, 2, 1), input_shape=(10, 64, 3))) input_names = ['input'] output_names = ['output'] spec = keras.convert(model, input_names, output_names).get_spec() self.assertIsNotNone(spec) # Test the model class self.assertIsNotNone(spec.description) self.assertTrue(spec.HasField('neuralNetwork')) # Test the inputs and outputs self.assertEquals(len(spec.description.input), len(input_names)) six.assertCountEqual(self, input_names, [x.name for x in spec.description.input]) self.assertEquals(len(spec.description.output), len(output_names)) six.assertCountEqual(self, output_names, [x.name for x in spec.description.output]) # Test the layer parameters. layers = spec.neuralNetwork.layers layer_0 = layers[0] self.assertIsNotNone(layer_0.permute)
def test_dropout(self): """ Test the conversion for a Dense + Dropout """ from keras.layers import Dense, Dropout # Create a simple Keras model model = Sequential() model.add(Dense(32, input_dim=16)) model.add(Dropout(0.5)) model.add(Dense(32, input_dim=16)) input_names = ['input'] output_names = ['output'] spec = keras.convert(model, input_names, output_names).get_spec() self.assertIsNotNone(spec) # Test the model class self.assertIsNotNone(spec.description) self.assertTrue(spec.HasField('neuralNetwork')) # Test the inputs and outputs self.assertEquals(len(spec.description.input), len(input_names)) self.assertItemsEqual(input_names, map(lambda x: x.name, spec.description.input)) self.assertEquals(len(spec.description.output), len(output_names)) self.assertItemsEqual(output_names, map(lambda x: x.name, spec.description.output)) # Test the layer parameters. layers = spec.neuralNetwork.layers layer_0 = layers[0] self.assertIsNotNone(layer_0.innerProduct) self.assertEquals(len(layers), 2)
def test_classifier_no_name(self): np.random.seed(1988) input_dim = 5 num_hidden = 12 num_classes = 6 input_length = 3 model = Sequential() model.add( LSTM(num_hidden, input_dim=input_dim, input_length=input_length, return_sequences=False)) model.add(Dense(num_classes, activation='softmax')) model.set_weights( [np.random.rand(*w.shape) for w in model.get_weights()]) input_names = ['input'] output_names = ['zzzz'] class_labels = ['a', 'b', 'c', 'd', 'e', 'f'] predicted_feature_name = 'pf' coremlmodel = keras_converter.convert( model, input_names, output_names, class_labels=class_labels, predicted_feature_name=predicted_feature_name) if is_macos() and macos_version() >= (10, 13): inputs = np.random.rand(input_dim) outputs = coremlmodel.predict({'input': inputs}) # this checks that the dictionary got the right name and type self.assertEquals(type(outputs[output_names[0]]), type({'a': 0.5}))
def test_activation_softmax(self): """ Test the conversion for a Dense + Activation('softmax') """ from keras.layers import Dense, Activation # Create a simple Keras model model = Sequential() model.add(Dense(32, input_dim=16)) model.add(Activation("softmax")) input_names = ["input"] output_names = ["output"] spec = keras.convert(model, input_names, output_names).get_spec() self.assertIsNotNone(spec) # Test the model class self.assertIsNotNone(spec.description) self.assertTrue(spec.HasField("neuralNetwork")) # Test the inputs and outputs self.assertEqual(len(spec.description.input), len(input_names)) six.assertCountEqual(self, input_names, [x.name for x in spec.description.input]) self.assertEqual(len(spec.description.output), len(output_names)) six.assertCountEqual(self, output_names, [x.name for x in spec.description.output]) # Test the layer parameters. layers = spec.neuralNetwork.layers layer_0 = layers[0] self.assertIsNotNone(layer_0.innerProduct) layer_1 = layers[1] self.assertIsNotNone(layer_1.softmax)
def convert_model(architecture): root = os.path.normpath(os.path.join(os.path.dirname(__file__), '..')) labels_path = os.path.join(root, 'model/labels.json') with open(labels_path, 'r') as fp: labels = json.load(fp) if architecture == 'mobilenets': model_path = os.path.join(root, 'model/mobilenets.h5') model = keras.models.load_model(model_path, custom_objects={'relu6': relu6}) elif architecture == 'inception': model_path = os.path.join(root, 'model/inception.h5') model = keras.models.load_model(model_path) else: raise ValueError('architecture must be inception or mobilenets.') coreml_model = convert( model, input_names='image', image_input_names='image', class_labels=labels, image_scale=2. / 255, red_bias=-1, green_bias=-1, blue_bias=-1, ) coreml_model.save("model/%s.mlmodel" % architecture)
def test_make_updatable_with_bilstm(self): from keras.models import Sequential from keras.layers import Dense, LSTM from coremltools.converters import keras as keras_converter from keras.layers.wrappers import Bidirectional import numpy as np num_classes = 6 model = Sequential() model.add( Bidirectional(LSTM(32, input_shape=(10, 32)), input_shape=(10, 32))) model.add(Dense(num_classes, activation="softmax")) model.set_weights( [np.random.rand(*w.shape) for w in model.get_weights()]) input_names = ["input"] output_names = ["zzzz"] class_labels = ["a", "b", "c", "d", "e", "f"] predicted_feature_name = "pf" coremlmodel = keras_converter.convert( model, input_names, output_names, class_labels=class_labels, predicted_feature_name=predicted_feature_name, predicted_probabilities_output=output_names[0], ) spec = coremlmodel.get_spec() builder = NeuralNetworkBuilder(spec=spec) # we could be able to make "dense_1" updatable without any issue builder.make_updatable([spec.neuralNetworkClassifier.layers[1].name])
def test_activation_softmax(self): """ Test the conversion for a Dense + Activation('softmax') """ from keras.layers import Dense, Activation # Create a simple Keras model model = Sequential() model.add(Dense(32, input_dim=16)) model.add(Activation('softmax')) input_names = ['input'] output_names = ['output'] spec = keras.convert(model, input_names, output_names).get_spec() self.assertIsNotNone(spec) # Test the model class self.assertIsNotNone(spec.description) self.assertTrue(spec.HasField('neuralNetwork')) # Test the inputs and outputs self.assertEquals(len(spec.description.input), len(input_names)) self.assertEqual(sorted(input_names), sorted(map(lambda x: x.name, spec.description.input))) self.assertEquals(len(spec.description.output), len(output_names)) self.assertEqual(sorted(output_names), sorted(map(lambda x: x.name, spec.description.output))) # Test the layer parameters. layers = spec.neuralNetwork.layers layer_0 = layers[0] self.assertIsNotNone(layer_0.innerProduct) layer_1 = layers[1] self.assertIsNotNone(layer_1.softmax)
def test_merge_multiply(self): """ Test the following Keras model |- dense-| dense -| |- merge - dense |- dense-| """ input_tensor = Input(shape=(3, )) x1 = Dense(4)(input_tensor) x2 = Dense(5)(x1) x3 = Dense(5)(x1) x4 = merge([x2, x3], mode='mul') x5 = Dense(7)(x4) model = Model(input=[input_tensor], output=[x5]) input_names = ['data'] output_names = ['output'] spec = keras.convert(model, input_names, output_names).get_spec() self.assertIsNotNone(spec) # Test the model class self.assertIsNotNone(spec.description) self.assertTrue(spec.HasField('neuralNetwork')) # Test the inputs and outputs self.assertEqual(len(spec.description.input), len(input_names)) self.assertEqual(sorted(input_names), sorted(map(lambda x: x.name, spec.description.input))) self.assertEqual(len(spec.description.output), len(output_names)) self.assertEqual( sorted(output_names), sorted(map(lambda x: x.name, spec.description.output)))
def test_pooling(self): """ Test the conversion of pooling layer. """ from keras.layers import Conv2D, MaxPooling2D # Create a simple Keras model model = Sequential() model.add(Conv2D(input_shape=(64, 64, 3), filters=32, kernel_size=(5,5), strides=(1,1), activation=None, padding='valid', use_bias=True)) model.add(MaxPooling2D(pool_size=(2,2))) input_names = ['input'] output_names = ['output'] spec = keras.convert(model, input_names, output_names).get_spec() self.assertIsNotNone(spec) # Test the model class self.assertIsNotNone(spec.description) self.assertTrue(spec.HasField('neuralNetwork')) # Test the inputs and outputs self.assertEquals(len(spec.description.input), len(input_names)) self.assertEqual(sorted(input_names), sorted(map(lambda x: x.name, spec.description.input))) self.assertEquals(len(spec.description.output), len(output_names)) self.assertEqual(sorted(output_names), sorted(map(lambda x: x.name, spec.description.output))) # Test the layer parameters. layers = spec.neuralNetwork.layers self.assertIsNotNone(layers[1].pooling)
def test_batchnorm(self): """ Test the conversion for a Convoultion2D + Batchnorm layer """ from keras.layers import Conv2D from keras.layers.normalization import BatchNormalization # Create a simple Keras model model = Sequential() model.add(Conv2D(input_shape=(64, 64, 3), filters=32, kernel_size=(5,5), strides=(1,1), activation=None, padding='valid', use_bias=True)) # epsilon in CoreML is currently fixed at 1e-5 model.add(BatchNormalization(epsilon=1e-5)) input_names = ['input'] output_names = ['output'] spec = keras.convert(model, input_names, output_names).get_spec() self.assertIsNotNone(spec) # Test the model class self.assertIsNotNone(spec.description) self.assertTrue(spec.HasField('neuralNetwork')) # Test the inputs and outputs self.assertEquals(len(spec.description.input), len(input_names)) self.assertEqual(sorted(input_names), sorted(map(lambda x: x.name, spec.description.input))) self.assertEquals(len(spec.description.output), len(output_names)) self.assertEqual(sorted(output_names), sorted(map(lambda x: x.name, spec.description.output))) # Test the layer parameters. layers = spec.neuralNetwork.layers self.assertIsNotNone(layers[0].convolution) self.assertIsNotNone(layers[1].batchnorm)
def test_upsample(self): """ Test the conversion of 2D convolutional layer + upsample """ from keras.layers import Conv2D, UpSampling2D # Create a simple Keras model model = Sequential() model.add( Conv2D(input_shape=(64, 64, 3), filters=32, kernel_size=(5, 5))) model.add(UpSampling2D(size=(2, 2))) input_names = ['input'] output_names = ['output'] spec = keras.convert(model, input_names, output_names).get_spec() self.assertIsNotNone(spec) # Test the model class self.assertIsNotNone(spec.description) self.assertTrue(spec.HasField('neuralNetwork')) # Test the inputs and outputs self.assertEquals(len(spec.description.input), len(input_names)) self.assertEqual(sorted(input_names), sorted(map(lambda x: x.name, spec.description.input))) self.assertEquals(len(spec.description.output), len(output_names)) self.assertEqual( sorted(output_names), sorted(map(lambda x: x.name, spec.description.output))) # Test the layer parameters. layers = spec.neuralNetwork.layers layer_0 = layers[0] self.assertIsNotNone(layer_0.convolution) layer_1 = layers[1] self.assertIsNotNone(layer_1.upsample)
def test_embedding(self): from keras.layers import Embedding model = Sequential() num_inputs = 10 num_outputs = 3 model.add(Embedding(num_inputs, num_outputs, input_length=5)) input_names = ['input'] output_names = ['output'] spec = keras.convert(model, input_names, output_names).get_spec() self.assertIsNotNone(spec) # Test the model class self.assertIsNotNone(spec.description) self.assertTrue(spec.HasField('neuralNetwork')) # Test the inputs and outputs self.assertEquals(len(spec.description.input), len(input_names)) # Test the layer parameters. layers = spec.neuralNetwork.layers layer_0 = layers[0] self.assertIsNotNone(layer_0.embedding) self.assertEquals(layer_0.embedding.inputDim, num_inputs) self.assertEquals(layer_0.embedding.outputChannels, num_outputs) self.assertEquals(len(layer_0.embedding.weights.floatValue), num_inputs * num_outputs)
def test_conv1d_lstm(self): from keras.layers import Convolution1D, LSTM, Dense model = Sequential() # input_shape = (time_step, dimensions) model.add(Convolution1D(32, 3, border_mode='same', input_shape=(10, 8))) # conv1d output shape = (None, 10, 32) model.add(LSTM(24)) model.add(Dense(1, activation='sigmoid')) print('model.layers[1].output_shape=', model.layers[1].output_shape) input_names = ['input'] output_names = ['output'] spec = keras.convert(model, input_names, output_names).get_spec() self.assertIsNotNone(spec) self.assertTrue(spec.HasField('neuralNetwork')) # Test the inputs and outputs self.assertEquals(len(spec.description.input), len(input_names)) six.assertCountEqual(self, input_names, [x.name for x in spec.description.input]) self.assertEquals(len(spec.description.output), len(output_names)) six.assertCountEqual(self, output_names, [x.name for x in spec.description.output]) # Test the layer parameters. layers = spec.neuralNetwork.layers self.assertIsNotNone(layers[0].convolution) self.assertIsNotNone(layers[1].simpleRecurrent) self.assertIsNotNone(layers[2].innerProduct)
def test_default_interface_names(self): from keras.layers import Dense from keras.layers import Activation # Create a simple Keras model model = Sequential() model.add(Dense(32, input_dim=16)) model.add(Activation('softmax')) expected_input_names = ['input1'] expected_output_names = ['output1'] spec = keras.convert(model).get_spec() self.assertIsNotNone(spec) # Test the model class self.assertIsNotNone(spec.description) self.assertTrue(spec.HasField('neuralNetwork')) # Test the inputs and outputs self.assertEquals(len(spec.description.input), len(expected_input_names)) six.assertCountEqual(self, expected_input_names, [x.name for x in spec.description.input]) self.assertEquals(len(spec.description.output), len(expected_output_names)) self.assertEquals(expected_output_names, [x.name for x in spec.description.output])
def test_pooling(self): """ Test the conversion of pooling layer. """ from keras.layers import Convolution2D, MaxPooling2D # Create a simple Keras model model = Sequential() model.add(Convolution2D(input_shape=(64, 64, 3), nb_filter=32, nb_row=5, nb_col=5, init='glorot_uniform', activation=None, weights=None, border_mode='valid', subsample=(1, 1), bias=True)) model.add(MaxPooling2D(pool_size=(2,2))) input_names = ['input'] output_names = ['output'] spec = keras.convert(model, input_names, output_names).get_spec() self.assertIsNotNone(spec) # Test the model class self.assertIsNotNone(spec.description) self.assertTrue(spec.HasField('neuralNetwork')) # Test the inputs and outputs self.assertEquals(len(spec.description.input), len(input_names)) self.assertItemsEqual(input_names, map(lambda x: x.name, spec.description.input)) self.assertEquals(len(spec.description.output), len(output_names)) self.assertItemsEqual(output_names, map(lambda x: x.name, spec.description.output)) # Test the layer parameters. layers = spec.neuralNetwork.layers layer_0 = layers[0] self.assertIsNotNone(layer_0.convolution)
def test_classifier_integer_classes(self): from keras.layers import Dense from keras.layers import Activation # Create a simple Keras model model = Sequential() model.add(Dense(32, input_dim=16)) model.add(Activation("softmax")) classes = list(range(32)) input_names = ["input"] output_names = ["prob_output"] expected_output_names = ["prob_output", "classLabel"] spec = keras.convert(model, input_names, output_names, class_labels=classes).get_spec() self.assertIsNotNone(spec) # Test the model class self.assertIsNotNone(spec.description) self.assertTrue(spec.HasField("neuralNetworkClassifier")) self.assertFalse(spec.HasField("neuralNetwork")) # Test the inputs and outputs self.assertEquals(len(spec.description.input), len(input_names)) six.assertCountEqual(self, input_names, [x.name for x in spec.description.input]) self.assertEquals(len(spec.description.output), len(expected_output_names)) self.assertEquals(expected_output_names, [x.name for x in spec.description.output]) # Check the types self.assertEquals(spec.description.output[0].type.WhichOneof("Type"), "dictionaryType") self.assertEquals( spec.description.output[0].type.dictionaryType.WhichOneof( "KeyType"), "int64KeyType", ) self.assertEquals(spec.description.output[1].type.WhichOneof("Type"), "int64Type") self.assertTrue(spec.description.predictedFeatureName, "classLabel") self.assertTrue(spec.description.predictedProbabilitiesName, "prob_output") # Test the class parameters self.assertEqual( spec.WhichOneof("Type"), "neuralNetworkClassifier", "Expected a NN classifier model", ) self.assertEqual( spec.neuralNetworkClassifier.WhichOneof("ClassLabels"), "int64ClassLabels") class_from_proto = list( spec.neuralNetworkClassifier.int64ClassLabels.vector) six.assertCountEqual(self, classes, class_from_proto)
def _keras_2_mlmodel_image(): """ Converts a Keras h5 model into ML Model for image data and saves it on disk. NOTE: Image configuration must be specified from Explora. NOTE: Currently, only categorical cross entropy loss is supported. """ model = get_keras_model() ios_config = state.state["ios_config"] class_labels = ios_config["class_labels"] mlmodel = keras_converter.convert(model, input_names=['image'], output_names=['output'], class_labels=class_labels, predicted_feature_name='label') mlmodel.save(state.state["mlmodel_path"]) image_config = ios_config["image_config"] spec = coremltools.utils.load_spec(state.state["mlmodel_path"]) builder = coremltools.models.neural_network.NeuralNetworkBuilder(spec=spec) dims = image_config["dims"] spec.description.input[0].type.imageType.width = dims[0] spec.description.input[0].type.imageType.height = dims[1] cs = _FeatureTypes_pb2.ImageFeatureType.ColorSpace.Value(image_config["color_space"]) spec.description.input[0].type.imageType.colorSpace = cs trainable_layer_names = [layer.name for layer in model.layers if layer.get_weights()] builder.make_updatable(trainable_layer_names) builder.set_categorical_cross_entropy_loss(name='loss', input='output') if isinstance(model.optimizer, SGD): params = SgdParams( lr=K.eval(model.optimizer.lr), batch=state.state["hyperparams"]["batch_size"], ) builder.set_sgd_optimizer(params) elif isinstance(model.optimizer, Adam): params = AdamParams( lr=K.eval(model.optimizer.lr), batch_size=state.state["hyperparams"]["batch_size"], beta1=model.optimizer.beta1, beta2=model.optimizer.beta2, eps=model.optimizer.eps, ) builder.set_adam_optimizer(params) else: raise Exception("iOS optimizer must be SGD or Adam!") builder.set_epochs(UNLIMITED_EPOCHS) builder.set_shuffle(state.state["hyperparams"]["shuffle"]) mlmodel_updatable = MLModel(spec) mlmodel_updatable.save(state.state["mlmodel_path"]) K.clear_session()
def _get_coreml_model(model, input_names, output_names): """ Get the coreml model from the Keras model. """ # Convert the model from coremltools.converters import keras as keras_converter model = keras_converter.convert(model, input_names, output_names) return model
def test_classifier_custom_class_name(self): from keras.layers import Dense from keras.layers import Activation # Create a simple Keras model model = Sequential() model.add(Dense(32, input_shape=(16, ))) model.add(Activation('softmax')) classes = ['c%s' % i for i in range(32)] input_names = ['input'] output_names = ['prob_output'] expected_output_names = ['prob_output', 'my_foo_bar_class_output'] spec = keras.convert( model, input_names, output_names, class_labels=classes, predicted_feature_name='my_foo_bar_class_output').get_spec() self.assertIsNotNone(spec) # Test the model class self.assertIsNotNone(spec.description) self.assertTrue(spec.HasField('neuralNetworkClassifier')) self.assertFalse(spec.HasField('neuralNetwork')) # Test the inputs and outputs self.assertEquals(len(spec.description.input), len(input_names)) self.assertEqual(sorted(input_names), sorted(map(lambda x: x.name, spec.description.input))) self.assertEquals(len(spec.description.output), len(expected_output_names)) self.assertEquals(expected_output_names, list(map(lambda x: x.name, spec.description.output))) # Check the types self.assertEquals(spec.description.output[0].type.WhichOneof('Type'), 'dictionaryType') self.assertEquals( spec.description.output[0].type.dictionaryType.WhichOneof( 'KeyType'), 'stringKeyType') self.assertEquals(spec.description.output[1].type.WhichOneof('Type'), 'stringType') self.assertTrue(spec.description.predictedFeatureName, 'my_foo_bar_class_output') self.assertTrue(spec.description.predictedProbabilitiesName, 'prob_output') # Test the class parameters self.assertEqual(spec.WhichOneof('Type'), 'neuralNetworkClassifier', "Expected a NN classifier model") self.assertEqual( spec.neuralNetworkClassifier.WhichOneof('ClassLabels'), 'stringClassLabels') class_from_proto = list( spec.neuralNetworkClassifier.stringClassLabels.vector) self.assertEqual(sorted(classes), sorted(class_from_proto))
def test_activations(self): """ Test the conversion for a Dense + Activation('something') """ from keras.layers import Dense, Activation # Create a simple Keras model keras_activation_options = [ "tanh", "softplus", "softsign", "relu", "sigmoid", "hard_sigmoid", "linear", ] coreml_activation_options = [ "tanh", "softplus", "softsign", "ReLU", "sigmoid", "sigmoidHard", "linear", ] for i, k_act in enumerate(keras_activation_options): c_act = coreml_activation_options[i] model = Sequential() model.add(Dense(32, input_dim=16)) model.add(Activation(k_act)) input_names = ["input"] output_names = ["output"] spec = keras.convert(model, input_names, output_names).get_spec() self.assertIsNotNone(spec) # Test the model class self.assertIsNotNone(spec.description) self.assertTrue(spec.HasField("neuralNetwork")) # Test the inputs and outputs self.assertEqual(len(spec.description.input), len(input_names)) self.assertCountEqual( self, input_names, [x.name for x in spec.description.input] ) self.assertEqual(len(spec.description.output), len(output_names)) self.assertCountEqual( self, output_names, [x.name for x in spec.description.output] ) # Test the layer parameters. layers = spec.neuralNetwork.layers self.assertIsNotNone(layers[0].innerProduct) self.assertIsNotNone(layers[1].activation) self.assertTrue(layers[1].activation.HasField(c_act))
def test_bidir(self): """ Test the conversion of a bidirectional layer """ from keras.layers import LSTM from keras.layers.wrappers import Bidirectional # Create a simple Keras model model = Sequential() model.add( Bidirectional(LSTM(32, input_dim=32, input_length=10), input_shape=(10, 32))) input_names = ["input"] output_names = ["output"] spec = keras.convert(model, input_names, output_names).get_spec() self.assertIsNotNone(spec) # Test the model class self.assertIsNotNone(spec.description) self.assertTrue(spec.HasField("neuralNetwork")) # Test the inputs and outputs self.assertEquals(len(spec.description.input), len(input_names) + 4) self.assertEquals(input_names[0], spec.description.input[0].name) self.assertEquals( 32, spec.description.input[1].type.multiArrayType.shape[0]) self.assertEquals( 32, spec.description.input[2].type.multiArrayType.shape[0]) self.assertEquals( 32, spec.description.input[3].type.multiArrayType.shape[0]) self.assertEquals( 32, spec.description.input[4].type.multiArrayType.shape[0]) self.assertEquals(len(spec.description.output), len(output_names) + 4) self.assertEquals(output_names[0], spec.description.output[0].name) self.assertEquals( 64, spec.description.output[0].type.multiArrayType.shape[0]) self.assertEquals( 32, spec.description.output[1].type.multiArrayType.shape[0]) self.assertEquals( 32, spec.description.output[2].type.multiArrayType.shape[0]) self.assertEquals( 32, spec.description.output[3].type.multiArrayType.shape[0]) self.assertEquals( 32, spec.description.output[4].type.multiArrayType.shape[0]) # Test the layer parameters. layers = spec.neuralNetwork.layers layer_0 = layers[0] self.assertIsNotNone(layer_0.biDirectionalLSTM) self.assertEquals(len(layer_0.input), 5) self.assertEquals(len(layer_0.output), 5)
def test_8bit_symmetric_and_skips(self): from keras.models import Sequential from keras.layers import Conv2D def stable_rel_error(x, ref): err = x - ref denom = np.maximum(np.abs(ref), np.ones_like(ref)) return np.abs(err) / denom np.random.seed(1988) input_dim = 16 num_kernels, kernel_height, kernel_width, input_channels = 64, 3, 3, 32 # Define a model model = Sequential() model.add( Conv2D(input_shape=(input_dim, input_dim, input_channels), filters=num_kernels, kernel_size=(kernel_height, kernel_width))) # Set some random weights weight, bias = model.layers[0].get_weights() num_filters = weight.shape[-1] filter_shape = weight.shape[:-1] new_weight = np.stack([ 4.0 * np.random.rand(*filter_shape) - 2 for i in range(num_filters) ], axis=-1) model.layers[0].set_weights([new_weight, bias]) mlmodel = keras_converter.convert(model, ['data'], ['output_0']) selector = quantization_utils.AdvancedQuantizedLayerSelector( skip_layer_types=['batchnorm', 'bias', 'depthwiseConv'], minimum_conv_kernel_channels=4, minimum_conv_weight_count=4096) q_mlmodel = quantization_utils.quantize_weights(mlmodel, 8, selector=selector) input_shape = (1, 1, input_channels, input_dim, input_dim) input_val = 2 * np.random.rand(*input_shape) - 1 coreml_input = {'data': input_val} coreml_output = mlmodel.predict(coreml_input) q_coreml_output = q_mlmodel.predict(coreml_input) val = coreml_output['output_0'] q_val = q_coreml_output['output_0'] rel_err = stable_rel_error(q_val, val) max_rel_err, mean_rel_err = np.max(rel_err), np.mean(rel_err) self.assertTrue(max_rel_err < 0.25) self.assertTrue(max_rel_err > 0.01) self.assertTrue(mean_rel_err < 0.02)
def test_classifier_integer_classes(self): from keras.layers import Dense from keras.layers import Activation # Create a simple Keras model model = Sequential() model.add(Dense(32, input_dim=16)) model.add(Activation('softmax')) classes = range(32) input_names = ['input'] output_names = ['prob_output'] expected_output_names = ['prob_output', 'classLabel'] spec = keras.convert(model, input_names, output_names, class_labels=classes).get_spec() self.assertIsNotNone(spec) # Test the model class self.assertIsNotNone(spec.description) self.assertTrue(spec.HasField('neuralNetworkClassifier')) self.assertFalse(spec.HasField('neuralNetwork')) # Test the inputs and outputs self.assertEquals(len(spec.description.input), len(input_names)) self.assertItemsEqual(input_names, map(lambda x: x.name, spec.description.input)) self.assertEquals(len(spec.description.output), len(expected_output_names)) self.assertEquals(expected_output_names, map(lambda x: x.name, spec.description.output)) # Check the types self.assertEquals(spec.description.output[0].type.WhichOneof('Type'), 'dictionaryType') self.assertEquals( spec.description.output[0].type.dictionaryType.WhichOneof( 'KeyType'), 'int64KeyType') self.assertEquals(spec.description.output[1].type.WhichOneof('Type'), 'int64Type') self.assertTrue(spec.description.predictedFeatureName, 'classLabel') self.assertTrue(spec.description.predictedProbabilitiesName, 'prob_output') # Test the class parameters self.assertEqual(spec.WhichOneof('Type'), 'neuralNetworkClassifier', "Expected a NN classifier model") self.assertEqual( spec.neuralNetworkClassifier.WhichOneof('ClassLabels'), 'int64ClassLabels') class_from_proto = list( spec.neuralNetworkClassifier.int64ClassLabels.vector) self.assertItemsEqual(classes, class_from_proto)
def test_classifier_file(self): from keras.layers import Dense from keras.layers import Activation import os import tempfile # Create a simple Keras model model = Sequential() model.add(Dense(32, input_dim=16)) model.add(Activation("softmax")) classes = ["c%s" % i for i in range(32)] classes_file = tempfile.mktemp() with open(classes_file, "w") as f: f.write("\n".join(classes)) input_names = ["input"] output_names = ["prob_output"] expected_output_names = ["prob_output", "classLabel"] spec = keras.convert(model, input_names, output_names, class_labels=classes).get_spec() self.assertIsNotNone(spec) # Test the model class self.assertIsNotNone(spec.description) self.assertTrue(spec.HasField("neuralNetworkClassifier")) self.assertFalse(spec.HasField("neuralNetwork")) # Test the inputs and outputs self.assertEquals(len(spec.description.input), len(input_names)) six.assertCountEqual(self, input_names, [x.name for x in spec.description.input]) self.assertEquals(len(spec.description.output), len(expected_output_names)) self.assertEquals(expected_output_names, [x.name for x in spec.description.output]) # Check the types self.assertEquals(spec.description.output[0].type.WhichOneof("Type"), "dictionaryType") self.assertEquals( spec.description.output[0].type.dictionaryType.WhichOneof( "KeyType"), "stringKeyType", ) self.assertEquals(spec.description.output[1].type.WhichOneof("Type"), "stringType") self.assertTrue(spec.description.predictedFeatureName, "classLabel") self.assertTrue(spec.description.predictedProbabilitiesName, "prob_output") # cleanup os.remove(classes_file)
def test_separable_convolution(self, with_dilations=False, activation=None): """ Test the conversion of 2D depthwise separable convolutional layer. """ from keras.layers import SeparableConv2D dilation_rate = [1, 1] if with_dilations: dilation_rate = [2, 2] # Create a simple Keras model model = Sequential() model.add( SeparableConv2D(input_shape=(64, 64, 3), filters=32, kernel_size=(5, 5), activation=activation, padding='valid', strides=(1, 1), use_bias=True, dilation_rate=dilation_rate)) input_names = ['input'] output_names = ['output'] spec = keras.convert(model, input_names, output_names).get_spec() self.assertIsNotNone(spec) # Test the model class self.assertIsNotNone(spec.description) self.assertTrue(spec.HasField('neuralNetwork')) # Test the inputs and outputs self.assertEquals(len(spec.description.input), len(input_names)) self.assertEqual(sorted(input_names), sorted(map(lambda x: x.name, spec.description.input))) self.assertEquals(len(spec.description.output), len(output_names)) self.assertEqual( sorted(output_names), sorted(map(lambda x: x.name, spec.description.output))) # Test the layer parameters. layers = spec.neuralNetwork.layers layer_depthwise, layer_pointwise = layers[0], layers[1] self.assertIsNotNone(layer_depthwise.convolution) self.assertIsNotNone(layer_pointwise.convolution) self.assertEqual(layer_depthwise.convolution.dilationFactor, dilation_rate) if activation is not None: self.assertIsNotNone(layers[2].activation) self.assertTrue(layers[2].activation.HasField('ELU'))
def test_classifier_file(self): from keras.layers import Dense from keras.layers import Activation import os import tempfile # Create a simple Keras model model = Sequential() model.add(Dense(32, input_shape=(16, ))) model.add(Activation('softmax')) classes = ['c%s' % i for i in range(32)] classes_file = tempfile.mktemp() with open(classes_file, 'w') as f: f.write('\n'.join(classes)) input_names = ['input'] output_names = ['prob_output'] expected_output_names = ['prob_output', 'classLabel'] spec = keras.convert(model, input_names, output_names, class_labels=classes).get_spec() self.assertIsNotNone(spec) # Test the model class self.assertIsNotNone(spec.description) self.assertTrue(spec.HasField('neuralNetworkClassifier')) self.assertFalse(spec.HasField('neuralNetwork')) # Test the inputs and outputs self.assertEquals(len(spec.description.input), len(input_names)) self.assertEqual(sorted(input_names), sorted(map(lambda x: x.name, spec.description.input))) self.assertEquals(len(spec.description.output), len(expected_output_names)) self.assertEquals(expected_output_names, list(map(lambda x: x.name, spec.description.output))) # Check the types self.assertEquals(spec.description.output[0].type.WhichOneof('Type'), 'dictionaryType') self.assertEquals( spec.description.output[0].type.dictionaryType.WhichOneof( 'KeyType'), 'stringKeyType') self.assertEquals(spec.description.output[1].type.WhichOneof('Type'), 'stringType') self.assertTrue(spec.description.predictedFeatureName, 'classLabel') self.assertTrue(spec.description.predictedProbabilitiesName, 'prob_output') # cleanup os.remove(classes_file)
def test_keras_1_image_bias(self): # define Keras model and get prediction input_shape = (100, 50, 3) model = Sequential() model.add(Activation("linear", input_shape=input_shape)) data = np.ones(input_shape) keras_input = np.ones(input_shape) data[:, :, 0] = 128.0 data[:, :, 1] = 27.0 data[:, :, 2] = 200.0 red_bias = -12.0 green_bias = -20 blue_bias = -4 keras_input[:, :, 0] = data[:, :, 0] + red_bias keras_input[:, :, 1] = data[:, :, 1] + green_bias keras_input[:, :, 2] = data[:, :, 2] + blue_bias keras_preds = model.predict(np.expand_dims(keras_input, axis=0)) keras_preds = np.transpose(keras_preds, [0, 3, 1, 2]).flatten() # convert to coreml and get predictions model_dir = tempfile.mkdtemp() model_path = os.path.join(model_dir, "keras.mlmodel") from coremltools.converters import keras as keras_converter coreml_model = keras_converter.convert( model, input_names=["data"], output_names=["output"], image_input_names=["data"], red_bias=red_bias, green_bias=green_bias, blue_bias=blue_bias, ) if _is_macos() and _macos_version() >= (10, 13): coreml_input_dict = dict() coreml_input_dict["data"] = PIL.Image.fromarray( data.astype(np.uint8)) coreml_preds = coreml_model.predict( coreml_input_dict)["output"].flatten() self.assertEqual(len(keras_preds), len(coreml_preds)) max_relative_error = compare_models(keras_preds, coreml_preds) self.assertAlmostEqual(max(max_relative_error, 0.001), 0.001, delta=1e-6) if os.path.exists(model_dir): shutil.rmtree(model_dir)
def test_unsupported_variational_deconv(self): from keras.layers import Input, Lambda, Convolution2D, Flatten, Dense x = Input(shape=(8,8,3)) conv_1 = Convolution2D(4, 2, 2, border_mode='same', activation='relu')(x) flat = Flatten()(conv_1) hidden = Dense(10, activation='relu')(flat) z_mean = Dense(10)(hidden) z_log_var = Dense(10)(hidden) def sampling(args): z_mean, z_log_var = args return z_mean + z_log_var z = Lambda(sampling, output_shape=(10,))([z_mean, z_log_var]) model = Model([x], [z]) spec = keras.convert(model, ['input'], ['output']).get_spec()
def test_batchnorm(self): """ Test the conversion for a Convoultion2D + Batchnorm layer """ from keras.layers import Convolution2D from keras.layers.normalization import BatchNormalization # Create a simple Keras model model = Sequential() model.add( Convolution2D( input_shape=(64, 64, 3), nb_filter=32, nb_row=5, nb_col=5, init="glorot_uniform", activation=None, weights=None, border_mode="valid", subsample=(1, 1), bias=True, ) ) # epsilon in CoreML is currently fixed at 1e-5 model.add(BatchNormalization(epsilon=1e-5)) input_names = ["input"] output_names = ["output"] spec = keras.convert(model, input_names, output_names).get_spec() self.assertIsNotNone(spec) # Test the model class self.assertIsNotNone(spec.description) self.assertTrue(spec.HasField("neuralNetwork")) # Test the inputs and outputs self.assertEqual(len(spec.description.input), len(input_names)) self.assertCountEqual( self, input_names, [x.name for x in spec.description.input] ) self.assertEqual(len(spec.description.output), len(output_names)) self.assertCountEqual( self, output_names, [x.name for x in spec.description.output] ) # Test the layer parameters. layers = spec.neuralNetwork.layers self.assertIsNotNone(layers[0].convolution) self.assertIsNotNone(layers[1].batchnorm)