8

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.

Lausbert
  • 1,471
  • 2
  • 17
  • 23

2 Answers2

8

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")
}
Lausbert
  • 1,471
  • 2
  • 17
  • 23
  • I'm having the same problem, but I don't know how to start, my input data is an image. So it will be very helpful if anyone how to do it. – drasick Jun 09 '17 at 19:33
  • maybe this [example](https://github.com/yulingtianxia/Core-ML-Sample/blob/master/CoreMLSample/ViewController.swift) could help? – Lausbert Jun 10 '17 at 09:14
4

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!
    }
Cyril
  • 2,783
  • 1
  • 24
  • 35