简体   繁体   中英

How to save a downloaded CoreML Model with CoreData?

I have downloaded the new trained model from python backend, with this code:

    import Foundation
    import Alamofire
    import AlamofireObjectMapper
    import ObjectMapper
    import CoreML

    class func downloadModel(modelUrl: String) {

        let destenation = Support.getDestenationForModel(modelUrl: modelUrl)

        AF.download(modelUrl, to: destenation).downloadProgress { progress in
            print("Download Progress: \(progress.fractionCompleted)")
        }
            .response { response in
                switch response.result {
                case .success(let success):
                    if let url = success?.absoluteURL {
                        FTApi.compileNewModel(url: url)
                    }
                    break
                case .failure(let err):
                    print(err)
                    break
                }
        }
    }

where in Support class the getDestenationForModel is the following:

    class func getDestenationForModel(modelUrl: String) -> DownloadRequest.Destination {
        let destenation: DownloadRequest.Destination =  { url, options in
            guard let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first ,
                let modelUrl = URL(string: modelUrl) else {
                    preconditionFailure("unable to use documents directory")
            }

            let fileURL = documentsURL.appendingPathComponent(modelUrl.lastPathComponent)

            AppPrefrences.pathOfModel = modelUrl.lastPathComponent
            return (fileURL, [.removePreviousFile, .createIntermediateDirectories])
        }
        return destenation
    }

when the download is finished I try to save the model to CoreData (I didn't find any other way, maybe you could recommend something else) using the following code:

    private class func compileNewModel(url: URL) {
        do {
            let compiledUrl = try MLModel.compileModel(at: url)
            guard let model = try? MLModel(contentsOf: compiledUrl)
                else {
                    print("cannot get content of model")
                    return
            }

            let coreMlModel = CML(context: PersistanceService.context)
            print(type(of: model)) // => MLNeuralNetworkEngine
            coreMlModel.model = (model as NSObject)
            PersistanceService.saveContext() // here I have an error
        } catch {
            print("cannot download the model!")
        }
    }

the error is: *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[MLNeuralNetworkEngine encodeWithCoder:]: unrecognized selector sent to instance 0x104d38280'

where this is my CoreData entity class:

import Foundation
import CoreData


extension CML {

    @nonobjc public class func fetchRequest() -> NSFetchRequest<CML> {
        return NSFetchRequest<CML>(entityName: "CML")
    }

    @NSManaged public var model: NSObject?

}

I tried to change the type from NSObject to MLModel , but the result is the same.

Why would you even try this? It's not the sort of thing CoreData is designed for.

The correct solution is to copy the folder from compiledURL to a location in your app's Application Support folder. Then when you create the MLModel object, use the URL from the Application Support folder.

Read "Downloading and Compiling a Model on the User's Device" in the Core ML documentation to see how to do this.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM