Keras Coremltools:使最简单卷积模型工作的错误

Keras Coremltools:使最简单卷积模型工作的错误,keras,coreml,coremltools,Keras,Coreml,Coremltools,假设我在Keras中创建了最简单的模型: from keras.layers import * from keras import Input, Model import coremltools def MyModel(inputs_shape=(None,None,3), channels=64): inpt = Input(shape=inputs_shape) # channels skip = Conv2D(channels, (

假设我在Keras中创建了最简单的模型:

from keras.layers import *
from keras import Input, Model

import coremltools


def MyModel(inputs_shape=(None,None,3), channels=64):

        inpt = Input(shape=inputs_shape)

        # channels
        skip = Conv2D(channels, (3, 3), strides=1, activation=None, padding='same', name='conv_in')(inpt)
        out = Conv2D(3, (3, 3), strides=1, padding='same', activation='tanh',name='out')(skip)

        return Model(inputs=inpt, outputs=out)


model = MyModel()


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


spec = coreml_model._spec


print(spec.description.input[0])

print(spec.description.input[0].type.multiArrayType.shape)

print(spec.description.output[0])


coremltools.utils.save_spec(spec, "test.mlmodel")

输出为:

2 : out, <keras.layers.convolutional.Conv2D object at 0x7f08ca491470>
3 : out__activation__, <keras.layers.core.Activation object at 0x7f08ca4b0b70>
name: "inp1"
type {
  multiArrayType {
    shape: 3
    shape: 384
    shape: 384
    dataType: FLOAT32
  }
}

[3, 384, 384]
name: "out1"
type {
  multiArrayType {
    shape: 3
    dataType: FLOAT32
  }
}

所以它想要NHWC

推理尝试产生:

“卷积”类型的层“conv_in”的输入秩为3,但要求秩至少为4

当我尝试向输入添加额外维度时:

spec.description.input[0].type.multiArrayType.shape.extend([1, 3, 384, 384])
del spec.description.input[0].type.multiArrayType.shape[0]
del spec.description.input[0].type.multiArrayType.shape[0]
del spec.description.input[0].type.multiArrayType.shape[0]
我得到的推论是:

形状(1 x 384 x 384 x 3)不在允许的形状枚举集中

跟随并生成输入形状
(1,1384384,3)
没有帮助

如何使其工作并产生正确的输出

推论:

From PIL import Image

model_cml = coremltools.models.MLModel('my.mlmodel')

# load image
img = np.array(Image.open('patch4.png').convert('RGB'))[np.newaxis,...]/127.5 - 1

# Make predictions
predictions = model_cml.predict({'inp1':img})

# save result
res = predictions['out1']
res = np.clip((res[0]+1)*127.5,0,255).astype(np.uint8)

Image.fromarray(res).save('out32.png')
更新:

我能够使用输入运行此模型
(3,1384384)
,结果是
(1,3,3384384)
,这对我来说没有任何意义

更新2:

在Keras中设置固定形状

def MyModel(inputs_shape=(384,384,3), channels=64):

        inpt = Input(shape=inputs_shape)
修复了输出形状问题,但我仍然无法运行该模型(“卷积”类型的层“conv_in”具有输入秩3,但至少需要秩4)

更新:

下面的工作可以消除形状不匹配中的输入和conv_

1) 。降级到
coremltools==3.0
。版本3.3(型号版本4)似乎已损坏

2.)在keras模型中使用固定形状,在coreml模型中使用无输入形状和可变形状

from keras.layers import *
from keras import Input, Model

import coremltools


def MyModel(inputs_shape=(384,384,3), channels=64):

        inpt = Input(shape=inputs_shape)

        # channels
        skip = Conv2D(channels, (3, 3), strides=1, activation=None, padding='same', name='conv_in')(inpt)
        out = Conv2D(3, (3, 3), strides=1, padding='same', activation='tanh',name='out')(skip)

        return Model(inputs=inpt, outputs=out)


model = MyModel()

model.save('test.model')

print(model.summary())

'''
# v.3.3
coreml_model = coremltools.converters.keras.convert(model,
    input_names=["image"],
    output_names="out1",
    image_scale=1.0,
    model_precision='float32',
    use_float_arraytype=True,
    input_name_shape_dict={'inp1': [None, 384, 384, 3]}
    )
'''

coreml_model = coremltools.converters.keras.convert(model,
    input_names=["image"],
    output_names="out1",
    image_scale=1.0,
    model_precision='float32',

    )


spec = coreml_model._spec


from coremltools.models.neural_network import flexible_shape_utils
shape_range = flexible_shape_utils.NeuralNetworkMultiArrayShapeRange()
shape_range.add_channel_range((3,3))
shape_range.add_height_range((64, 384))
shape_range.add_width_range((64, 384))
flexible_shape_utils.update_multiarray_shape_range(spec, feature_name='image', shape_range=shape_range)


print(spec.description.input)

print(spec.description.input[0].type.multiArrayType.shape)

print(spec.description.output)


coremltools.utils.save_spec(spec, "my.mlmodel")
在推理脚本中,输入形状的数组
(1,1,3384384)


如果输出形状中的mlmodel文件不正确,则可以忽略该文件。这更像是一个元数据问题,也就是说,模型仍然可以很好地工作,并且做正确的事情。转换器并不总是能够找出正确的输出形状(不确定原因)。

我还发现coremltools==3.3似乎已损坏。我通过1)切换到3.0版本2)不提供
输入\u name\u shape\u dict
3)在keras模型中使用固定输入大小4)使用通道优先数据排序和馈送
(1,1,3384384)
作为输入,消除了卷积层形状问题。。。这让我至少可以毫无错误地推断出这个简单的模型,但我忘了——它仍然会发出错误
shape(3384384)“不在允许的形状列表中
,因此您需要从coremltools.models.neural\u network导入flexible\u shape\u utils shape\u range=flexible\u shape\u utils.NeuralNetworkMultiArrayShaperage()shape\u range.添加通道范围((3,3))形状范围。添加高度范围((64384))形状范围。添加宽度范围((64384))灵活的形状实用程序。更新多阵列形状范围(规格、特征名称、图像、形状范围=形状范围)
def MyModel(inputs_shape=(384,384,3), channels=64):

        inpt = Input(shape=inputs_shape)
from keras.layers import *
from keras import Input, Model

import coremltools


def MyModel(inputs_shape=(384,384,3), channels=64):

        inpt = Input(shape=inputs_shape)

        # channels
        skip = Conv2D(channels, (3, 3), strides=1, activation=None, padding='same', name='conv_in')(inpt)
        out = Conv2D(3, (3, 3), strides=1, padding='same', activation='tanh',name='out')(skip)

        return Model(inputs=inpt, outputs=out)


model = MyModel()

model.save('test.model')

print(model.summary())

'''
# v.3.3
coreml_model = coremltools.converters.keras.convert(model,
    input_names=["image"],
    output_names="out1",
    image_scale=1.0,
    model_precision='float32',
    use_float_arraytype=True,
    input_name_shape_dict={'inp1': [None, 384, 384, 3]}
    )
'''

coreml_model = coremltools.converters.keras.convert(model,
    input_names=["image"],
    output_names="out1",
    image_scale=1.0,
    model_precision='float32',

    )


spec = coreml_model._spec


from coremltools.models.neural_network import flexible_shape_utils
shape_range = flexible_shape_utils.NeuralNetworkMultiArrayShapeRange()
shape_range.add_channel_range((3,3))
shape_range.add_height_range((64, 384))
shape_range.add_width_range((64, 384))
flexible_shape_utils.update_multiarray_shape_range(spec, feature_name='image', shape_range=shape_range)


print(spec.description.input)

print(spec.description.input[0].type.multiArrayType.shape)

print(spec.description.output)


coremltools.utils.save_spec(spec, "my.mlmodel")
img = np.zeros((1,1,3,384,384))

# Make predictions
predictions = model_cml.predict({'inp1':img})
res = predictions['out1'] # (3, 384,384)