首页 > 解决方案 > 初始化 MLUpdateTask 导致信号 SIGABRT:加载文件时出错:*.mlmodelc/model.espresso.weights

问题描述

(我是 ML 新手,所以请原谅我在说/做废话......)

我想做的是:

我试图创建一个用于探索 ML 的应用程序(以便进入 SwiftUI 和 CoreML)。该应用程序旨在教某种神经元网络使用强化学习来玩井字游戏。为此,您可以AIPlayer与 a RandomPlayer、 an AlgorithmicPlayer、本身或您自己对战。应该通过AIPlayer使用游戏的结果和它在游戏中做出的选择来更新底层模型,从而从它所玩的每一场游戏中学习。

问题

问题是,MLUpdateTask在使用信号 SIGABRT 进行特定数量的更新后初始化失败。因此,应用程序崩溃。确切的数量取决于设备。在我的 iPhone 6s 上运行它时,第 240 次初始化MLUpdateTask失败,在模拟器上,它是第 243 次初始化。

我得到的错误信息:

libc++abi.dylib: terminating with uncaught exception of type std::runtime_error: Error loading file: /private/var/containers/Bundle/Application/714E7417-B792-4F80-8EAE-A2855E138A95/TicTacToe.app/UpdatableNNClassifier.mlmodelc/model.espresso.weights

我将错误追溯到那一行……整个代码都在 GitHub 上。 https://github.com/theMomax/TicTacToe/blob/0182db0af27498d504fb5dcfd0556267e23c063b/TicTacToe/MLBase.swift#L132

我试图解决的问题:

我试图减少模型中的层数。没有效果。

我试图一次只有一个更新任务。没有效果。

我将整个应用程序移植到 macOS。这“解决了”问题。

模型

这个笔记本是我用来制作 CoreML 模型的笔记本的基础。我只更改了使模型适应我的 I/O 格式所必需的部分。由于其结构,我现在拥有的模型可能无法真正学习/变得更好,但我认为这与现在无关。

系统

Mac:10.15 测试版 (19A582a)

iPhone:13.1.2 (17A860)

Xcode: 11.1 (11A1027)

更新代码

是 GitHub 上的文件。我在这里的参考是来自 WWDC的这段视频。我试图删除下面不必要的部分并添加一些注释来描述何时调用每个函数......


// is initialized once on startup
class MLWrapper {

    let bundle = Bundle(for: UpdatableNNClassifier.self)

    let updatableModelURL: URL

    var model = UpdatableNNClassifier()

    var trainingData: [(gameboard: [Position: FieldState], pick: Position)] = []

    init() {
        self.updatableModelURL = bundle.url(forResource: "UpdatableNNClassifier", withExtension: "mlmodelc")!
    }

    // Returns a randomly selected alternative to pick. 
    private func other(than pick: Position, in gameboard: [Position: FieldState?]) -> Position? {
        // ...
    }

    private func convertInput(gameboard: [Position: FieldState]) -> MLMultiArray {
        // ...
    }

    private func convertOutput(output: UpdatableNNClassifierOutput) -> Position? {
        // ...
    }

    // is called each time the `AIPlayer` is supposed to make a pick
    func predict(on gameboard: [Position: FieldState]) -> Position? {
        let input = convertInput(gameboard: gameboard)
        if let output = try? model.prediction(gameboard: input) {
            if let result = convertOutput(output: output) {

                // record input and output, so that it can be used to train
                // train the model, when the game's outcome is known
                trainingData.append((gameboard, result))
                return result
            } else {
                return nil
            }
        } else {
            print("Unexpected runtime error in \(model).")
            return nil
        }
    }

    // is called after a game is completed
    func reflect(on outcome: Outcome) {
        do {            
            let bp: MLBatchProvider = try MLArrayBatchProvider(dictionary: ["gameboard": trainingData.compactMap { i in
                return convertInput(gameboard: i.gameboard)
            }, "pick": trainingData.compactMap({ I in

                // in case the `AIPlayer` won or achieved a draw, its pick was good, otherwise, try any other pick next time
                outcome != .defeat ? i.pick.description() : other(than: i.pick, in: i.gameboard)?.description() ?? i.pick.description()
            })])
            // reset trainingData
            trainingData = []            

            // the line below is the one that fails
            let updateTask = try MLUpdateTask(forModelAt: updatableModelURL, trainingData: bp, configuration: self.model.model.configuration, completionHandler: { ctx in
                if ctx.task.error == nil {
                    self.model.model = ctx.model
                } else {
                    print(ctx.task.error!)
                }
            })

            updateTask.resume()
        } catch {
            print(error)
        }
    }

}

问题

所以,我的基本问题是:我的更新代码有问题吗?或者这很可能是一个 beta 错误?您对我可以尝试解决的问题有什么建议吗?

上面的所有代码都是从Controller.swift. 这会是个问题吗?

标签: iosswiftkerasxcode11coreml

解决方案


推荐阅读