Search code examples
swiftcoreml

Converting MLMultiArray to [Double] causes NaN


I'm converting the return of prediction() in CoreML (4 b1) from MLMultiArray to [Double] and the result is creating NaNs, and generally not making any sense to me. What might be going on?

Here's the conversion function I'm using:

static func toDoubleArray(_ o: MLMultiArray) -> [Double] {
        let length = o.count
        let doublePtr =  o.dataPointer.bindMemory(to: Double.self, capacity: length)
        let doubleBuffer = UnsafeBufferPointer(start: doublePtr, count: length)
        let output = Array(doubleBuffer)
        return output
    }

And here is a sample output, with the mysterious NaNs:

original:
zn: Float32 1 x 30 matrix
[1.082742,-0.6218173,0.4097924,0.7741141,0.3768867,0.1923163,-0.6453421,-1.51211,0.9758957,-0.01491163,0.3188823,0.6816303,-0.3234658,-0.1413545,-0.3082153,-0.3349644,0.6796142,0.0495025,1.436066,-1.348089,0.2413646,-0.931259,-0.1012118,0.849587,-0.1338869,-0.5497701,-0.5438929,1.653574,-0.6829579,-0.539122]

converted: [-0.0001189622124778386, 0.0006766730199516765, 9.747163042077938e-09, -0.13711044152516036, -1.7618037121610124e-17, 0.00023267642183680645, -9.748075633049926e-10, -8.196165002097733e-07, 1.901572700078848e-13, -0.05577234175498982, -0.003711220331500651, 0.0015560479289331661, -5.481938547240449e-05, 0.3071476808226601, -4.9620131810906736e-05, 3.793063e-317, 2.220121165e-314, 1.5e-323, -nan(0x3ffff89abcdef), 5.312137469e-314, 0.0, 0.0, 0.0, 4.4490612551694285e-308, 7.99e-321, 2.2200499266e-314, 5e-324, 5.417665788e-314, 0.0, 0.0]

It almost seems like I'm just getting garbage memory from somewhere... but then again, that shouldn't contain NaNs. Very confused.

UPDATE: Okay, so as Matthijs pointed out, the underlying memory is Float32. If I just want an MLMultiArray containing Doubles as a Swift Array, then the toDoubleArray() function is fine. But in my case I want both a conversion to Double and a Swift Array. This version provides that, and appears to give the expected output:

static func castToDoubleArray(_ o: MLMultiArray) -> [Double] {
        var result: [Double] = Array(repeating: 0.0, count: o.count)
        for i in 0 ..< o.count {
            result[i] = o[i].doubleValue
        }
        return result
    }

Solution

  • The original is an array of Float32 values, so you should convert to an array of Float, not Double.