Lausbert
Lausbert

Reputation: 1590

How to initialize a MLMultiArray in CoreML

I've got an array of 40 arrays with 12 double features, so the type is [[double]]. Currently I'm sending this data to Google Cloud ML API to get a related prediction.

Since Apple recently introduced CoreML and coremltools, I converted my model from keras to .mlmodel to avoid thousand of google cloud api calls and do inference directly on my iPhone:

coreml_model = coremltools.converters.keras.convert(new_Model, input_names=['accelerations'],
                                                    output_names=['scores'])
coreml_model.save('PredictionModel.mlmodel')

After adding the model to my Xcode Project, it looks like: enter image description here

I have no idea, where these others inputs and outputs are comming from. To get a prediction, I need to convert my Array of Arrays of 12 doubles to an MLMultiArray, but I don't know how to do this. Has anyone faced a similar problem? Here is my current unfinished approach:

_predictionModel = PredictionModel()
guard let mlMultiArray = try? MLMultiArray(dataPointer: <#T##UnsafeMutableRawPointer#>, shape: <#T##[NSNumber]#>, dataType: <#T##MLMultiArrayDataType#>, strides: <#T##[NSNumber]#>, deallocator: <#T##((UnsafeMutableRawPointer) -> Void)?##((UnsafeMutableRawPointer) -> Void)?##(UnsafeMutableRawPointer) -> Void#>) else {
        fatalError("Unexpected runtime error.")
    }
guard let predictionOutput = try? _predictionModel.prediction(accelerations: mlMultiArray, lstm_1_h_in: nil, lstm_1_c_in: nil, lstm_2_h_in: nil, lstm_2_c_in: nil) else {
        fatalError("Unexpected runtime error.")
    }

The related documentation can be found here.

Upvotes: 8

Views: 12545

Answers (2)

Cyril
Cyril

Reputation: 2818

This is how I did it. Probably not the best way to handle optionals but gets the job done for testing

Create an instance of the MLMultiArray object with shape and data type

let mlArray = try? MLMultiArray(shape: [3], dataType: MLMultiArrayDataType.float32)

mlArray does not have an append function so you literally have to iterate through it and add values

for i in 0..<array.count {
     mlArray?[i] = NSNumber(value: input[i])
}

Full function

    func convertToMLArray(_ input: [Int]) -> MLMultiArray {

        let mlArray = try? MLMultiArray(shape: [3], dataType: MLMultiArrayDataType.float32)


        for i in 0..<array.count {
            mlArray?[i] = NSNumber(value: input[i])
        }


        return arr!
    }

Upvotes: 4

Lausbert
Lausbert

Reputation: 1590

I achieved it by reading this blog :)

let data = _currentScaledMotionArrays.reduce([], +) //result is of type [Double] with 480 elements
guard let mlMultiArray = try? MLMultiArray(shape:[40,12], dataType:MLMultiArrayDataType.double) else {
    fatalError("Unexpected runtime error. MLMultiArray")
}
for (index, element) in data.enumerated() {
    mlMultiArray[index] = NSNumber(floatLiteral: element)
}
let input = PredictionModelInput(accelerations: mlMultiArray)
guard let predictionOutput = try? _predictionModel.prediction(input: input) else {
        fatalError("Unexpected runtime error. model.prediction")
}

Upvotes: 8

Related Questions