如何在从keras转换的coreml中格式化conv1d/lstm nn的输入数据
How to format input data for an conv1d/lstm nn in coreml converted from keras
我的输入形状(none、40 [时间步长]、12 [特征])的 keras 模型如下所示:
model = Sequential([
Conv1D(nodes_per_layer, filter_length, subsample_length=2, activation='relu', input_shape=(timesteps, data_dim), name='accelerations'),
Conv1D(nodes_per_layer, filter_length, subsample_length=1, activation='relu'),
LSTM(nodes_per_layer, return_sequences=True),
LSTM(nodes_per_layer, return_sequences=False),
Dropout(dropout),
Dense(num_classes),
Activation('softmax', name='scores'),
])
将其转换为 .mlmodel 后,我将其添加到我的 XCodeProject 中:
然后我尝试进行推理并获得预测分数:
func makePredictionRequest(currentScaledMotionArrays: [[Double]]) {
let data = _currentScaledMotionArrays.reduce([], +) //result is of type [Double] with 480 elements
do {
let mlMultiArray = try MLMultiArray(shape:[40,12], dataType:MLMultiArrayDataType.double)
for (index, element) in data.enumerated() {
mlMultiArray[index] = NSNumber(value: element)
}
let input = PredictionModelInput(accelerations: mlMultiArray)
let predictionOutput = try _predictionModel.prediction(input: input)
}
catch {
print(error.localizedDescription)
}
}
但是predictionModel.prediction(input: input) 方法总是失败并抛出以下错误:
"The model expects input feature lstm_1_h_in to be an array, but the input is of type 0."
因此需要初始化 lstm 层的隐藏状态。我不知道这种行为是否符合预期,因为我以前从未遇到过同样的问题。无论是在 keras 本身还是使用 google cloud ml 进行推理时。我也不知道通常选择用于推理的初始值。也许只是零数组?有人遇到过类似的问题吗?
可以找到 .mlmodel 文件 here。
我真的做到了我想做的事情
以下代码片段适用于 swift 4.0、keras 2.0.4 和 coremltools 0.4 .0。
keras 输入形状为 (none, 40 [timesteps], 12 [features])。请注意更改后的参数顺序 (40 [timesteps], none, 12 [features]) 下面。
两个 lstm 层的所有 32 个节点的隐藏统计数据都用零初始化。我必须测试这是否会导致预期的行为,或者我是否必须随机初始化它们。
func makePredictionRequest(evaluationStep: EvaluationStep) {
let data = _currentScaledMotionArrays.reduce([], +) //result is of type [Double] with 480 elements
do {
let accelerationsMultiArray = try MLMultiArray(shape:[40,1,12], dataType:MLMultiArrayDataType.double)
for (index, element) in data.enumerated() {
accelerationsMultiArray[index] = NSNumber(value: element)
}
let hiddenStatesMultiArray = try MLMultiArray(shape: [32], dataType: MLMultiArrayDataType.double)
for index in 0..<32 {
hiddenStatesMultiArray[index] = NSNumber(integerLiteral: 0)
}
let input = PredictionModelInput(accelerations: accelerationsMultiArray, lstm_1_h_in: hiddenStatesMultiArray, lstm_1_c_in: hiddenStatesMultiArray, lstm_2_h_in: hiddenStatesMultiArray, lstm_2_c_in: hiddenStatesMultiArray)
let predictionOutput = try _predictionModel.prediction(input: input)
print(predictionOutput.scores)
}
catch {
print(error.localizedDescription)
}
}
你也可以看到我的full implementation。
如果我的回答解决了你的问题,请在这里给我打个招呼:)
我的输入形状(none、40 [时间步长]、12 [特征])的 keras 模型如下所示:
model = Sequential([
Conv1D(nodes_per_layer, filter_length, subsample_length=2, activation='relu', input_shape=(timesteps, data_dim), name='accelerations'),
Conv1D(nodes_per_layer, filter_length, subsample_length=1, activation='relu'),
LSTM(nodes_per_layer, return_sequences=True),
LSTM(nodes_per_layer, return_sequences=False),
Dropout(dropout),
Dense(num_classes),
Activation('softmax', name='scores'),
])
将其转换为 .mlmodel 后,我将其添加到我的 XCodeProject 中:
然后我尝试进行推理并获得预测分数:
func makePredictionRequest(currentScaledMotionArrays: [[Double]]) {
let data = _currentScaledMotionArrays.reduce([], +) //result is of type [Double] with 480 elements
do {
let mlMultiArray = try MLMultiArray(shape:[40,12], dataType:MLMultiArrayDataType.double)
for (index, element) in data.enumerated() {
mlMultiArray[index] = NSNumber(value: element)
}
let input = PredictionModelInput(accelerations: mlMultiArray)
let predictionOutput = try _predictionModel.prediction(input: input)
}
catch {
print(error.localizedDescription)
}
}
但是predictionModel.prediction(input: input) 方法总是失败并抛出以下错误:
"The model expects input feature lstm_1_h_in to be an array, but the input is of type 0."
因此需要初始化 lstm 层的隐藏状态。我不知道这种行为是否符合预期,因为我以前从未遇到过同样的问题。无论是在 keras 本身还是使用 google cloud ml 进行推理时。我也不知道通常选择用于推理的初始值。也许只是零数组?有人遇到过类似的问题吗?
可以找到 .mlmodel 文件 here。
我真的做到了我想做的事情
以下代码片段适用于 swift 4.0、keras 2.0.4 和 coremltools 0.4 .0。
keras 输入形状为 (none, 40 [timesteps], 12 [features])。请注意更改后的参数顺序 (40 [timesteps], none, 12 [features]) 下面。
两个 lstm 层的所有 32 个节点的隐藏统计数据都用零初始化。我必须测试这是否会导致预期的行为,或者我是否必须随机初始化它们。
func makePredictionRequest(evaluationStep: EvaluationStep) {
let data = _currentScaledMotionArrays.reduce([], +) //result is of type [Double] with 480 elements
do {
let accelerationsMultiArray = try MLMultiArray(shape:[40,1,12], dataType:MLMultiArrayDataType.double)
for (index, element) in data.enumerated() {
accelerationsMultiArray[index] = NSNumber(value: element)
}
let hiddenStatesMultiArray = try MLMultiArray(shape: [32], dataType: MLMultiArrayDataType.double)
for index in 0..<32 {
hiddenStatesMultiArray[index] = NSNumber(integerLiteral: 0)
}
let input = PredictionModelInput(accelerations: accelerationsMultiArray, lstm_1_h_in: hiddenStatesMultiArray, lstm_1_c_in: hiddenStatesMultiArray, lstm_2_h_in: hiddenStatesMultiArray, lstm_2_c_in: hiddenStatesMultiArray)
let predictionOutput = try _predictionModel.prediction(input: input)
print(predictionOutput.scores)
}
catch {
print(error.localizedDescription)
}
}
你也可以看到我的full implementation。
如果我的回答解决了你的问题,请在这里给我打个招呼:)