Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 721
Lausbert Avatar asked Jun 09 '17 14:06

Lausbert


2 Answers

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")
}
like image 58
Lausbert Avatar answered Sep 21 '22 12:09

Lausbert


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!
    }
like image 36
Cyril Avatar answered Sep 21 '22 12:09

Cyril