如何在iOS(或Android)应用程序中使用keras h5模型

时间:2018-02-14 10:12:04

标签: keras coreml

我用keras retinanet 50训练了一个模型,现在我有一个h5文件,当用静态图像测试它时效果很好。

我很想在iOS(和/或Android)应用中使用它,但我无法将其转换为例如coreml:

import coremltools
coreml_model = coremltools.converters.keras.convert(model) # => error occurs
coreml_model.save('my_model.mlmodel')

错误是

    ---------------------------------------------------------------------------
    ValueError                                Traceback (most recent call last)
  <ipython-input-7-ba230c07a72c> in <module>()
      1 import coremltools
----> 2 coreml_model = coremltools.converters.keras.convert(model)
      3 # Saving the Core ML model to a file.
      4 coreml_model.save('my_model.mlmodel')

/home/jonas/projects/keras/keras-env/local/lib/python2.7/site-packages/coremltools/converters/keras/_keras_converter.pyc in convert(model, input_names, output_names, image_input_names, is_bgr, red_bias, green_bias, blue_bias, gray_bias, image_scale, class_labels, predicted_feature_name, model_precision, predicted_probabilities_output, add_custom_layers, custom_conversion_functions)
    743                       predicted_probabilities_output,
    744                       add_custom_layers,
--> 745                       custom_conversion_functions=custom_conversion_functions)
    746 
    747     return _MLModel(spec)

/home/jonas/projects/keras/keras-env/local/lib/python2.7/site-packages/coremltools/converters/keras/_keras_converter.pyc in convertToSpec(model, input_names, output_names, image_input_names, is_bgr, red_bias, green_bias, blue_bias, gray_bias, image_scale, class_labels, predicted_feature_name, model_precision, predicted_probabilities_output, add_custom_layers, custom_conversion_functions, custom_objects)
    541                                            add_custom_layers=add_custom_layers,
    542                                            custom_conversion_functions=custom_conversion_functions,
--> 543                                            custom_objects=custom_objects)
    544     else:
    545         raise RuntimeError(

/home/jonas/projects/keras/keras-env/local/lib/python2.7/site-packages/coremltools/converters/keras/_keras2_converter.pyc in _convert(model, input_names, output_names, image_input_names, is_bgr, red_bias, green_bias, blue_bias, gray_bias, image_scale, class_labels, predicted_feature_name, predicted_probabilities_output, add_custom_layers, custom_conversion_functions, custom_objects)
    185 
    186     # Check valid versions
--> 187     _check_unsupported_layers(model, add_custom_layers)
    188 
    189     # Build network graph to represent Keras model

/home/jonas/projects/keras/keras-env/local/lib/python2.7/site-packages/coremltools/converters/keras/_keras2_converter.pyc in _check_unsupported_layers(model, add_custom_layers)
     98         else:
     99             if type(layer) not in _KERAS_LAYER_REGISTRY:
--> 100                 raise ValueError("Keras layer '%s' not supported. " % str(type(layer)))
    101             if isinstance(layer, _keras.layers.wrappers.TimeDistributed):
    102                 if type(layer.layer) not in _KERAS_LAYER_REGISTRY:

ValueError: Keras layer '<class 'keras_resnet.layers._batch_normalization.BatchNormalization'>' not supported. 

我也试过导出权重和体系结构(json)并再次加载模型,但错误保持不变。

根据最后的答案(https://www.quora.com/Does-Residual-Learning-work-without-batch-normalization)我明白batchnormalization仅用于训练,所以有没有办法将其转换为coreml?

修改

感谢Matthjis的评论,我尝试了以下内容:

import keras

class BatchNormalization(keras.layers.BatchNormalization):
    """
    Identical to keras.layers.BatchNormalization, but adds the option to freeze parameters.
    """
    def __init__(self, freeze, *args, **kwargs):
        print("here we are")
        self.freeze = freeze
        super(BatchNormalization, self).__init__(*args, **kwargs)

        # set to non-trainable if freeze is true
        self.trainable = not self.freeze

    def call(self, *args, **kwargs):
        # return super.call, but set training
        print("here we are")
        return super(BatchNormalization, self).call(training=(not self.freeze), *args, **kwargs)

    def get_config(self):
        print("here we are")
        config = super(BatchNormalization, self).get_config()
        config.update({'freeze': self.freeze})
        return config

然后

import coremltools
coreml_model = coremltools.converters.keras.convert(model, custom_conversion_functions={"BatchNormalization": BatchNormalization})

但我仍然得到同样的错误......

1 个答案:

答案 0 :(得分:1)

在推理期间也使用批量标准化,Core ML支持它。

但是,keras_resnet.layers._batch_normalization.BatchNormalization不是Keras的标准BatchNormalization图层,因此coremltools不了解如何处理它。

好消息:这个新的BatchNormalization层扩展了Keras标准BatchNormalization层,因此可以使您的模型与Core ML一起使用。 https://github.com/broadinstitute/keras-resnet/blob/master/keras_resnet/layers/_batch_normalization.py

三个选项:

  1. 您可以告诉coremltools这是一个自定义图层,然后在处理自定义图层的函数中返回一个BatchnormLayerParams对象。有关如何处理coremltools中自定义图层的更多信息:http://machinethink.net/blog/coreml-custom-layers/
  2. 您可以使用keras_resnet.layers._batch_normalization.BatchNormalization图层替换模型中的keras.layers.BatchNormalization图层,然后照常运行coremltools。

  3. 找出你的coremltools的安装位置,然后在 _keras2_converter.py 中,为keras_resnet.layers._batch_normalization.BatchNormalization添加一行,如下所示:

    keras_resnet.layers._batch_normalization.BatchNormalization:  _layers2.convert_batchnorm,
    

    就像这里:https://github.com/apple/coremltools/blob/052446a0b8925a019096cdc5529b7793d1e9bf30/coremltools/converters/keras/_keras2_converter.py#L49

    您还必须将keras_resnet导入此文件,否则coremltools将无法找到此模块。然后像往常一样运行coremltools。