【问题标题】:Output of converted CoreML model different than Keras转换后的 CoreML 模型的输出与 Keras 不同
【发布时间】:2019-08-30 14:37:05
【问题描述】:

我正在 Keras 中训练 LSTM 下一个字符/单词预测器,并希望将其包含在 iOS 项目中。当我将其转换为 CoreML 时,输出的形状和值与我原来的 Keras 模型不匹配。

总结一下我的问题:

  • 为什么转换后的模型与原始模型的输出形状不同,如何确保它们匹配?
  • 为什么我从转换后的模型中得到不同的预测值?

我训练的模型有如下布局:

model = Sequential()
model.add(LSTM(128, input_shape=(SEQUENCE_LENGTH, len(chars))))
model.add(Dense(len(chars), activation = 'softmax'))
model.add(Activation('softmax'))

其中序列是长度为 40 (sequence_length) 的字符列表,chars 是可能字符的列表。在本例中为 31。因此,模型的输出形状为 (None,31)

如果我尝试使用

转换模型
coreml_model = coremltools.converters.keras.convert(
               'keras_model.h5', 
               input_names=['sentence'], 
               output_names=['chars'], 
               class_labels = chars)

我收到以下错误:

NSLocalizedDescription = "The size of the output layer 'characters' in the neural network does not match the number of classes in the classifier.";

我想这是有道理的,因为输出形状有一个无维度。

如果我不提供 class_labels 参数,它会很好地转换模型。然而,当运行result = coreml_model.predict() 时,我现在得到一个(40,31) 的输出矩阵,而不是一个包含31 个字符概率的列表。

结果中没有一个条目与 Keras 模型中的值匹配。唯一的第一个条目对每个字符都有唯一的值 - 所有后面的条目都具有完全相同的值。

CoreML 模型输出层具有以下元数据:

output {
  name: "characters"
  shortDescription: "Next predicted character"
  type {
    multiArrayType {
      shape: 31
      dataType: DOUBLE
    }
  }
}

非常感谢您的帮助!

【问题讨论】:

  • 如果在转换模型时将input_shape中的SEQUENCE_LENGTH设置为1会怎样?
  • @MatthijsHollemans 如果我这样做,它实际上会添加类标签。但这当然对实际使用没有用。我怀疑这与 CoreML 处理模型中的多维输入/输出有关。我会尝试在模型中将它们展平。

标签: python keras coreml


【解决方案1】:

错误在于 CoreML 与多维输入不兼容。我找到了this blog,它指引我朝着正确的方向前进。

因此,为了解决这个问题,我必须通过添加一个 Reshape 层来展平输入,并将输入训练数据的大小调整为单个向量。新模型如下所示:

# Input is now a single vector of length 1240
input_shape = (SEQUENCE_LENGTH*len(chars))
model = Sequential()
# The reshape layer makes sure that I don't have to change anything inside the layers.
model.add(Reshape((SEQUENCE_LENGTH, len(chars)), input_shape=(input_shape,)))
model.add(LSTM(128, input_shape=(SEQUENCE_LENGTH, len(chars))))
model.add(Dense(len(chars)))
model.add(Activation('softmax'))

所有输入向量都必须以相同的方式调整大小:

x = x.reshape(x.shape[0], input_shape)

【讨论】:

    猜你喜欢
    • 2018-05-13
    • 2017-12-10
    • 2020-01-24
    • 1970-01-01
    • 2017-11-12
    • 1970-01-01
    • 2021-03-28
    • 2018-01-10
    • 2020-05-21
    相关资源
    最近更新 更多