如何在从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.0keras 2.0.4coremltools 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

如果我的回答解决了你的问题,请在这里给我打个招呼:)