首页 > 解决方案 > 是否可以用原生 CoreML 替换 keras Lambda 层来转换模型?

问题描述

我第一次需要将 mu keras 模型转换为 coreml。这可以通过coremltools包来完成,

import coremltools
import keras

model = Model(...) # keras

coreml_model = coremltools.converters.keras.convert(model,
    input_names="input_image_NHWC",
    output_names="output_image_NHWC",
    image_scale=1.0,
    model_precision='float32',
    use_float_arraytype=True,
    custom_conversion_functions={ "Lambda": convert_lambda },
    input_name_shape_dict={'input_image_NHWC': [None, 384, 384, 3]}
    )

但是,我有两个 lambda 层,其中第一个是深度到空间(pixelshuffle),另一个是缩放器:

def tf_upsampler(x):
    return tf.nn.depth_to_space(x, 4)

def mulfunc(x, beta=0.2):
    return beta*x

...

x = Lambda(tf_upsampler)(x)
...
x = Lambda(mulfunc)(x)

据我所知,我发现的唯一建议是使用自定义层,稍后需要在 Swift 代码中实现我的层。像这样的东西,MyPixelShuffleMyScaleLayer以某种方式实现为 XCode 项目中的类(?):

def convert_lambda(layer):
    # Only convert this Lambda layer if it is for our swish function.
    if layer.function == tf_upsampler:
        params = NeuralNetwork_pb2.CustomLayerParams()

        # The name of the Swift or Obj-C class that implements this layer.
        params.className = "MyPixelShuffle"

        # The desciption is shown in Xcode's mlmodel viewer.
        params.description = "pixelshuffle"

        params.parameters["blockSize"].intValue = 4



        return params
    elif layer.function == mulfunc:
        # https://stackoverflow.com/questions/47987777/custom-layer-with-two-parameters-function-on-core-ml
        params = NeuralNetwork_pb2.CustomLayerParams()

        # The name of the Swift or Obj-C class that implements this layer.
        params.className = "MyScaleLayer"
        params.description = "scaling input"

        # HERE!! This is important.
        params.parameters["scale"].doubleValue = 0.2


        # The desciption is shown in Xcode's mlmodel viewer.
        params.description = "multiplication by constant"

        return params

ScaleLayer但是,我发现 CoreML 实际上有我需要的层,它们可以找到ReorganizeDataLayer

如何使用这些原生层来替换 keras 模型中的 lambda?是否可以为网络编辑 coreML protobuf?或者如果它们有 Swift/OBj-C 类,它们是如何被调用的?

可以通过删除/添加图层来完成coremltools.models.neural_network.NeuralNetworkBuilder吗?

更新:

我发现keras 转换器实际上调用了神经网络构建器来添加不同的层。Builder 有builder.add_reorganize_data我需要的层。现在是如何替换模型中的自定义层的问题。我可以将它加载到 builder 和 ispect 层中:

coreml_model_path = 'mymodel.mlmodel'

spec = coremltools.models.utils.load_spec(coreml_model_path)
builder = coremltools.models.neural_network.NeuralNetworkBuilder(spec=spec)
builder.inspect_layers(last=10)
[Id: 417], Name: lambda_10 (Type: custom)
          Updatable: False
          Input blobs: ['up1_output']
          Output blobs: ['lambda_10_output']

标签: kerascoremlcoremltools

解决方案


做这样的事情要简单得多:

def convert_lambda(layer):
    if layer.function == tf_upsampler:
        params = NeuralNetwork_pb2.ReorganizeDataLayerParams()

        params.fillInTheOtherPropertiesHere = someValue

        return params
    ...etc..

换句话说,如果某些现有图层类型已经满足您的需求,您不必返回自定义图层。


推荐阅读