转换后的CoreML模型的输出与Keras不同

时间:2019-04-09 10:19:03

标签: python keras coreml

我正在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
    }
  }
}

非常感谢您的帮助!

1 个答案:

答案 0 :(得分:0)

错误在于CoreML与多维输入不兼容。我发现Thread引导着我朝着正确的方向前进。

因此,要解决此问题,我必须通过添加一个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)