.h5 keras 模型到 coreml 的分类转换在 IOS 中不起作用

Posted

技术标签:

【中文标题】.h5 keras 模型到 coreml 的分类转换在 IOS 中不起作用【英文标题】:.h5 keras model to coreml conversion for classification does not work in IOS 【发布时间】:2020-11-06 11:55:32 【问题描述】:

我使用 RGB 图像作为输入训练了一个 CNN 分类模型,它产生了 1x7 输出和类标签概率(7 个不同的类)。我已将模型从 keras .h5 转换为 coreML。我见过不同的应用程序,并在定义和不定义类标签的情况下尝试了它们。他们在转换时没有引起任何问题。然而,它们都不能在 ios 中工作。当我调用以下行时,两个模型都崩溃了:

 guard let result = predictionRequest.results as? [VNCoreMLFeatureValueObservation] else 
        fatalError("model failed to process image")
    

我的两个模型的输出定义如下。您能否建议模型输出有什么问题。我是否必须添加类标签?我很困惑如何调用最高可能值。我也添加了整个分类代码。请看下文。由于我是IOS的初学者,非常感谢您的帮助。真的非常感谢。

IOS中的模型输出定义与类标签转换:

/// Identity as dictionary of strings to doubles
lazy var Identity: [String : Double] = 
    [unowned self] in return self.provider.featureValue(for: "Identity")!.dictionaryValue as! [String : Double]
()


/// classLabel as string value
lazy var classLabel: String = 
    [unowned self] in return self.provider.featureValue(for: "classLabel")!.stringValue
()

没有类标签转换的IOS中模型输出定义:

init(Identity: MLMultiArray) 
    self.provider = try! MLDictionaryFeatureProvider(dictionary: ["Identity" : MLFeatureValue(multiArray: Identity)])

分类代码:

class ColorStyleVisionManager: NSObject 
static let shared = ColorStyleVisionManager()
static let MODEL = hair_color_class_labels().model
var colorStyle = String()
var hairColorFlag: Int = 0
private lazy var predictionRequest: VNCoreMLRequest = 
    do
        let model = try VNCoreMLModel(for: ColorStyleVisionManager.MODEL)
       
        let request = VNCoreMLRequest(model: model)
        request.imageCropAndScaleOption = VNImageCropAndScaleOption.centerCrop
        return request
     catch 
        fatalError("can't load Vision ML Model")
    
()


func predict(image:CIImage) -> String 
    

    guard let result = predictionRequest.results as? [VNCoreMLFeatureValueObservation] else 
        fatalError("model failed to process image")
    
    
    let firstResult = result.first


    if firstResult?.featureName == "0" 
            colorStyle = "Plain Coloring"
            hairColorFlag = 1
        
        else if firstResult?.featureName == "1" 
            colorStyle = "Ombre"
            hairColorFlag = 2
        
        else if firstResult?.featureName == "2" 
            colorStyle = "Sombre"
            hairColorFlag = 2
        
        else if firstResult?.featureName == "3" 
            colorStyle = "HighLight"
            hairColorFlag = 3
        
        else if firstResult?.featureName == "4" 
            colorStyle = "LowLight"
            hairColorFlag = 3
        
        else if firstResult?.featureName == "5" 
            colorStyle = "Color Melt"
            hairColorFlag = 5
        
        else if firstResult?.featureName == "6" 
            colorStyle = "Dip Dye"
            hairColorFlag = 4
        

    else 

    let handler = VNImageRequestHandler(ciImage: image)


    do 
            try handler.perform([predictionRequest])
         catch 
            print("error handler")
        

    
    return colorStyle

【问题讨论】:

崩溃的错误信息是什么? 嗨 Matthijs,它说“线程 1:致命错误:模型无法处理图像” 这是您自己来自fatalError 的错误消息。我的意思是 Core ML 给出的错误信息。问题是您没有返回 VNCoreMLFeatureValueObservation 对象。这并不奇怪,因为您实际上从未执行过预测请求。 【参考方案1】:

我在我的代码中发现了两个不同的问题。为了确保我的模型正确转换为 mlmodel,我使用 Apple 的 CreateML 工具创建了一个新的分类 mlmodel。顺便说一句,即使准确度似乎低于我的原始模型,它也很棒。我比较了模型的输出和输入类型,似乎我的 mlmodel 也是正确的。然后我使用了这个模型并再次尝试。它又崩溃了。我不太确定我必须期待“VNClassificationObservation”还是“VNCoreMLFeatureValueObservation”的预测结果。我改为分类观察。它又崩溃了。然后我意识到我的处理程序定义在崩溃线下方,我将它移到了上部。然后是羊毛。有效。我通过更改 FeatureValueObservation 进行了仔细检查,它再次崩溃了。这样两个问题就解决了。请参阅下面的正确代码。

我强烈建议使用 CreateML 工具来确认您的模型转换工作是否正常,以便进行调试。这只是几分钟的工作。

class ColorStyleVisionManager: NSObject 
static let shared = ColorStyleVisionManager()
static let MODEL = hair_color_class_labels().model
var colorStyle = String()
var hairColorFlag: Int = 0
private lazy var predictionRequest: VNCoreMLRequest = 
    do
        let model = try VNCoreMLModel(for: ColorStyleVisionManager.MODEL)
       
        let request = VNCoreMLRequest(model: model)
        request.imageCropAndScaleOption = VNImageCropAndScaleOption.centerCrop
        return request
     catch 
        fatalError("can't load Vision ML Model")
    
()


func predict(image:CIImage) -> String 
    
    let handler = VNImageRequestHandler(ciImage: image)


    do 
            try handler.perform([predictionRequest])
         catch 
            print("error handler")
        

    guard let result = predictionRequest.results as? [VNClassificationObservation] else 
        fatalError("error to process request")
    
    
    let firstResult = result.first
    print(firstResult!)

【讨论】:

以上是关于.h5 keras 模型到 coreml 的分类转换在 IOS 中不起作用的主要内容,如果未能解决你的问题,请参考以下文章

Keras 模型到 Coreml 并使用 OpenCV

tf.keras 模型到 coreml 模型,不支持 BatchNormalization

在 Swift 中设置 CoreML 模型 - 图像分类器

如何将 Turi Create 创建的 CoreML 模型转换为 Keras?

如何在 TensorFlow、Keras 或 PyTorch 中部署 CoreML 模型?

将 keras 模型转换为 coreml 时出错(“InputLayer”对象不可迭代)