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

.h5 keras model to coreml conversion for classification does not work in IOS

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

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

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

IOS 中的模型输出定义,带有 class 个标签转换:

/// 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 中的模型输出定义没有 class 标签转换:

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
}

}

我在我的代码中发现了两个不同的问题。为了确保我的模型正确转换为 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!)