转换后的 CoreML 模型的输出不同于 Keras
Output of converted CoreML model different than Keras
我正在 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.";
我想这是有道理的,因为输出形状有一个 None 维。
如果我不提供 class_labels
参数,它会很好地转换模型。但是,当 运行 result = coreml_model.predict()
时,我现在得到一个 (40,31)
的输出矩阵,而不是一个包含 31 个字符概率的列表。
结果中的 None 条目与 Keras 模型中的值匹配。只有第一个条目的每个字符都有唯一的值 - 所有后面的条目都具有完全相同的值。
CoreML 模型输出层具有以下元数据:
output {
name: "characters"
shortDescription: "Next predicted character"
type {
multiArrayType {
shape: 31
dataType: DOUBLE
}
}
}
非常感谢您的帮助!
错误在于 CoreML 与多维输入不兼容。我找到了 this blog,这为我指明了正确的方向。
因此,为了修复它,我不得不通过添加重塑层来展平输入,并将输入训练数据调整为单个向量。新模型如下所示:
# 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)
我正在 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.";
我想这是有道理的,因为输出形状有一个 None 维。
如果我不提供 class_labels
参数,它会很好地转换模型。但是,当 运行 result = coreml_model.predict()
时,我现在得到一个 (40,31)
的输出矩阵,而不是一个包含 31 个字符概率的列表。
None 条目与 Keras 模型中的值匹配。只有第一个条目的每个字符都有唯一的值 - 所有后面的条目都具有完全相同的值。
CoreML 模型输出层具有以下元数据:
output {
name: "characters"
shortDescription: "Next predicted character"
type {
multiArrayType {
shape: 31
dataType: DOUBLE
}
}
}
非常感谢您的帮助!
错误在于 CoreML 与多维输入不兼容。我找到了 this blog,这为我指明了正确的方向。
因此,为了修复它,我不得不通过添加重塑层来展平输入,并将输入训练数据调整为单个向量。新模型如下所示:
# 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)