我已经基于自定义PyTorch CNN模型创建了一个.mlmodel文件,方法是先使用onnx_coreml将PyTorch模型转换为ONNX,然后转换为CoreML。使用虚拟数据(3 x 224 x 224数组,每个值均为1.0),我已经验证了PyTorch模型,ONNX模型(使用Caffe后端运行)和CoreML模型(使用coremltools)都产生相同的结果。
但是,当我将相同的模型导入Xcode并在电话上运行它时,即使使用虚拟数据,模型输出也不匹配。
我使用的设备似乎没有什么不同(我尝试过从XS Max一直到SE的iPhone。)所有人都在运行iOS 12.2,并使用Xcode 10.2.1
这是我用来创建虚拟数据并从我的模型中获得预测的代码(在Swift中):
let pixelsWide = Int(newImg.size.width)
let pixelsHigh = Int(newImg.size.height)
var pixelMLArray = try MLMultiArray(shape: [1, 1, 3, 224, 224], dataType: .float32)
for y in 0 ..< pixelsHigh {
for x in 0 ..< pixelsWide {
pixelMLArray[[0,0,0,x,y] as [NSNumber]] = 1.0
pixelMLArray[[0,0,1,x,y] as [NSNumber]] = 1.0
pixelMLArray[[0,0,2,x,y] as [NSNumber]] = 1.0
}
}
do {
let convModel = CNNModel()
var thisConvOutput = try convModel.prediction(_0: pixelMLArray)._1161
} catch { print("Error") }
我已经验证了输入和输出标签正确,等等。 这可以顺利运行,但是thisConvOutput的前三个值是: [0.000139,0.000219,0.003607]
为了进行比较,运行PyTorch模型的前三个值是: [0.0002148、0.00032246和0.0035419]
和使用coremltools的完全相同的.mlmodel: [0.00021577,0.00031877,0.0035404]
长话短说,因为我不熟悉Swift,所以我想知道我是否在初始化/填充“ pixelMLArray”以通过设备上Xcode的模型运行它时做一些愚蠢的事情,因为.mlmodel是由coremltools非常接近我使用PyTorch获得的结果。有人可以帮忙吗?
答案 0 :(得分:0)
您在设备上的Core ML输出:[0.000139、0.000219、0.003607]
您来自coremltools的输出:[0.00021577、0.00031877、0.0035404]
请注意,这些数字非常小。当Core ML在GPU上运行模型(可能不确定在神经引擎上)时,它将使用16位浮点数。这些精度比32位浮点要小得多。
请注意0.000139和0.00021577的数字不同,但是它们都在1e-4左右。这低于16位浮点数的精度极限。但是0.003607和0.0035404几乎是相同的数字,因为它们大约大10倍,因此不会损失太多精度。
尝试使用CPU在设备上运行Core ML模型(实例化模型时,可以为此传递一个选项)。您可能会发现,现在得到的结果与coremltools版本更加接近(并且可能相同),因为CPU上的Core ML使用32位浮点数。
结论:到目前为止,您的模型看起来像在按预期工作,考虑到由于16位浮点计算而导致的精度下降。