如何使用在 Swift 中返回 MultiArray(Double) 的模型进行预测

Posted

技术标签:

【中文标题】如何使用在 Swift 中返回 MultiArray(Double) 的模型进行预测【英文标题】:How to make a prediction with model that returns MultiArray(Double) in Swift 【发布时间】:2020-04-19 13:21:15 【问题描述】:

我使用 Keras 训练了一个模型,并使用 CoreMLTools 将其转换为 CoreML。您可以在此处查看有关模型的详细信息:

如何使用此模型进行预测?当我尝试时出现此错误:

2019-12-30 13:07:01.564792-0800 agricultural-helper[16042:6014777] [espresso] [Espresso::handle_ex_plan] exception=Espresso exception: "Invalid argument": generic_reshape_kernel: Invalid bottom shape (512 28 -3 1 1) for reshape to (512 -1 1 1 1) status=-6
2019-12-30 13:07:01.565447-0800 agricultural-helper[16042:6014777] [coreml] Error computing NN outputs -6
Error Domain=com.apple.CoreML Code=0 "Error computing NN outputs." UserInfo=NSLocalizedDescription=Error computing NN outputs.

这是我的代码:

override init() 
    super.init()
    let options = MLPredictionOptions()
    options.usesCPUOnly = true
    let model = CropDisease()
    let uiImage = UIImage(named: "test.png")!
    let pixelBuffer = buffer(from: uiImage)!
    let modelInput = CropDiseaseInput(conv2d_input: pixelBuffer)

    do 
        let output = try model.prediction(input: modelInput, options: options)
        print(output)
     catch 
        print(error)
    


func buffer(from image: UIImage) -> CVPixelBuffer? 
  let attrs = [kCVPixelBufferCGImageCompatibilityKey: kCFBooleanTrue, kCVPixelBufferCGBitmapContextCompatibilityKey: kCFBooleanTrue] as CFDictionary
  var pixelBuffer : CVPixelBuffer?
  let status = CVPixelBufferCreate(kCFAllocatorDefault, Int(image.size.width), Int(image.size.height), kCVPixelFormatType_32ARGB, attrs, &pixelBuffer)
  guard (status == kCVReturnSuccess) else 
    return nil
  

  CVPixelBufferLockBaseAddress(pixelBuffer!, CVPixelBufferLockFlags(rawValue: 0))
  let pixelData = CVPixelBufferGetBaseAddress(pixelBuffer!)

  let rgbColorSpace = CGColorSpaceCreateDeviceRGB()
  let context = CGContext(data: pixelData, width: Int(image.size.width), height: Int(image.size.height), bitsPerComponent: 8, bytesPerRow: CVPixelBufferGetBytesPerRow(pixelBuffer!), space: rgbColorSpace, bitmapInfo: CGImageAlphaInfo.noneSkipFirst.rawValue)

  context?.translateBy(x: 0, y: image.size.height)
  context?.scaleBy(x: 1.0, y: -1.0)

  UIGraphicsPushContext(context!)
  image.draw(in: CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height))
  UIGraphicsPopContext()
  CVPixelBufferUnlockBaseAddress(pixelBuffer!, CVPixelBufferLockFlags(rawValue: 0))

  return pixelBuffer

任何帮助。谢谢!

【问题讨论】:

【参考方案1】:

您的 Core ML 模型似乎存在内部问题。尝试使用 coremltools 从 Python 进行预测。我猜你会得到同样的错误信息。

如果情况确实如此,那么解决方案是找出问题在模型中的确切位置。错误信息已经给出了相当大的提示:

generic_reshape_kernel: Invalid bottom shape (512 28 -3 1 1) 
for reshape to (512 -1 1 1 1)

某处的某个层正在获得一个形状为 (512, 28, -3, 1, 1) 但预期为 (512, -1, 1, 1, 1) 的张量。请注意,-1 不一定是问题(通常这意味着“自动计算此维度的大小”),但 -3 看起来有问题...

【讨论】:

感谢您的建议。现在就试试吧! 很遗憾,找不到太多。灰度图像与彩色图像是否存在问题? 如果你传入了错误的图像(像素不够等),那么 Core ML 会给出不同的错误,所以我怀疑是这样。你用什么框架来训练这个模型,也许是 TF 2.0? 我明白了。是的,我用过 TF2.0 对 TF 2.0 的支持是最近才添加到 coremltools 中的,所以毫无疑问它仍然存在错误。您可能会在这里遇到其中之一。没有看到实际的 mlmodel 文件就很难说。

以上是关于如何使用在 Swift 中返回 MultiArray(Double) 的模型进行预测的主要内容,如果未能解决你的问题,请参考以下文章

Swift:如何在异步 urlsession 函数中返回一个值?

Swift:如何在异步 urlsession 函数中返回一个值?

Alamofire 4 请求返回 NSArray,无法弄清楚如何在 Swift 3 中使用 SwiftyJSON 进行解析

如何在 Swift 的完成处理程序中返回布尔值

如何在Swift中返回Realm列表?

Swift Vapor 服务器:如何在获取请求中返回嵌套字典?