如何将 CoreML 模型添加到 Swift 包中?
How to add a CoreML model into a Swift package?
我正在尝试编写一个使用 CoreML 模型的 Swift 包。
我对 Swift 包的创建不是很熟悉,我无法让它工作。
以下是我根据迄今为止阅读的不同帖子所做的工作:
- 创建一个空包
$ mkdir MyPackage
$ cd MyPackage
$ swift package init
$ swift build
$ swift test
用XCode
打开Package.swift
文件
将 MyModel.mlmodel
文件拖放到 Sources/MyPackage
文件夹中
当我单击 XCode 中的 MyModel.mlmodel
文件时,class 名称下显示以下消息:
Model is not part of any target. Add the model to a target to enable generation of the model class.
同样,如果我在终端中使用命令 swift build
,我会收到以下消息:
warning: found 1 file(s) which are unhandled; explicitly declare them as resources or exclude from the target
/Path/To/MyPackage/Sources/MyPackage/MyModel.mlmodel
- 为了解决这个问题,我在文件
Package.swift
: 的目标资源中添加了 MyModel
.target(
name: "MyPackage",
dependencies: [],
resources: [.process("MyModel.mlmodel")]),
如果我现在使用命令 $ swift build
,我将不再收到警告,并且收到消息:
[3/3] Merging module MyPackage
但是当我检查 XCode 中的 MyModel.mlmodel
文件时,我在 class 名称下显示了以下消息:
Model class has not been generated yet.
- 为了解决这个问题,我在终端中使用了以下命令:
$ cd Sources/MyPackage
$ xcrun coremlcompiler generate MyModel.mlmodel --language Swift .
这在 mlmodel 文件旁边生成了一个 MyModel.swift
文件。
- 我在代码中插入了模型
MyPackage.swift
:
import CoreML
@available(iOS 12.0, *)
struct MyPackage {
var model = try! MyModel(configuration: MLModelConfiguration())
}
- 最后,在测试文件
MyPackageTests.swift
中,我创建了一个 MyPackage 实例:
import XCTest
@testable import MyPackage
final class MyPackageTests: XCTestCase {
func testExample() {
if #available(iOS 12.0, *) {
let foo = MyPackage()
} else {
// Fallback on earlier versions
}
}
static var allTests = [
("testExample", testExample),
]
}
我收到以下错误(似乎没有找到 CoreML 模型):
Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value
我一定是漏掉了什么...
我希望我的描述足够清楚和详细。
感谢您的帮助!
这一行可能是错误的地方:var model = try! MyModel(configuration: MLModelConfiguration())
由于您已将 mlmodel 文件添加到包中,因此尚未编译。我不是 Swift 包方面的专家,但我不相信 Xcode 现在会自动编译这个模型。当您打开编译后的应用程序包时,您可以自己看到这一点——它是否包含 mlmodel 文件或 mlmodelc 文件夹?
您可能需要将 mlmodelc 添加到包中,而不是 mlmodel。您可以通过以下方式创建它:
$ xcrun coremlcompiler compile MyModel.mlmodel .
接下来,在您的应用中,您需要按如下方式加载模型:
let url = YourBundle.url(forResource: "MyModel", withExtension: "mlmodelc")!
let model = try! MyModel(contentsOf: url, configuration: MLModelConfiguration())
其中 YourBundle
是对包含 mlmodelc 文件的包的引用(我猜这是 Swift 包的包)。
下面描述的解决方案对我有用。我希望它是正确的。
转换 MLModel
MLModel 不能直接在 Swift 包中使用。首先需要转换。
$ cd /path/to/folder/containg/mlmodel
$ xcrun coremlcompiler compile MyModel.mlmodel .
$ xcrun coremlcompiler generate MyModel.mlmodel . --language Swift
第一个 xcrun
命令将编译模型并创建一个名为 MyModel.mlmodelc
的文件夹。
第二个 xcrun
命令将生成一个 MyModel.swift
文件。
将模型添加到 Swift 包
我们认为 Swift 包已经存在并且位于 /path/to/MyPackage/
。
- 将
MyModel.mlmodelc
文件夹和 MyModel.swift
文件复制到 /path/to/MyPackage/Sources/MyPackage
文件夹中
- 在目标资源中添加
MyModel.mlmodelc
文件Package.swift
:
.target(
name: "MyPackage",
dependencies: [],
resources: [.process("MyModel.mlmodelc")]),
实例化 MyModel
在Swift代码中,简单地创建一个MyModel的实例:
let model = try? MyModel(configuration: MLModelConfiguration())
或:
let url = Bundle.module.url(forResource: "MyModel", withExtension: "mlmodelc")!
let model = try? MyModel(contentsOf: url, configuration: MLModelConfiguration())
疑难解答
一开始我遇到了 Type 'MLModel' has no member '__loadContents'
错误。
这似乎是与 XCode 12 有关的错误。
我简单评论了导致问题的2个函数。
有关详细信息,请参阅 and here。
我正在尝试编写一个使用 CoreML 模型的 Swift 包。 我对 Swift 包的创建不是很熟悉,我无法让它工作。 以下是我根据迄今为止阅读的不同帖子所做的工作:
- 创建一个空包
$ mkdir MyPackage
$ cd MyPackage
$ swift package init
$ swift build
$ swift test
用XCode
打开Package.swift
文件将
文件夹中MyModel.mlmodel
文件拖放到Sources/MyPackage
当我单击 XCode 中的 MyModel.mlmodel
文件时,class 名称下显示以下消息:
Model is not part of any target. Add the model to a target to enable generation of the model class.
同样,如果我在终端中使用命令 swift build
,我会收到以下消息:
warning: found 1 file(s) which are unhandled; explicitly declare them as resources or exclude from the target
/Path/To/MyPackage/Sources/MyPackage/MyModel.mlmodel
- 为了解决这个问题,我在文件
Package.swift
: 的目标资源中添加了
MyModel
.target(
name: "MyPackage",
dependencies: [],
resources: [.process("MyModel.mlmodel")]),
如果我现在使用命令 $ swift build
,我将不再收到警告,并且收到消息:
[3/3] Merging module MyPackage
但是当我检查 XCode 中的 MyModel.mlmodel
文件时,我在 class 名称下显示了以下消息:
Model class has not been generated yet.
- 为了解决这个问题,我在终端中使用了以下命令:
$ cd Sources/MyPackage
$ xcrun coremlcompiler generate MyModel.mlmodel --language Swift .
这在 mlmodel 文件旁边生成了一个 MyModel.swift
文件。
- 我在代码中插入了模型
MyPackage.swift
:
import CoreML
@available(iOS 12.0, *)
struct MyPackage {
var model = try! MyModel(configuration: MLModelConfiguration())
}
- 最后,在测试文件
MyPackageTests.swift
中,我创建了一个 MyPackage 实例:
import XCTest
@testable import MyPackage
final class MyPackageTests: XCTestCase {
func testExample() {
if #available(iOS 12.0, *) {
let foo = MyPackage()
} else {
// Fallback on earlier versions
}
}
static var allTests = [
("testExample", testExample),
]
}
我收到以下错误(似乎没有找到 CoreML 模型):
Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value
我一定是漏掉了什么... 我希望我的描述足够清楚和详细。 感谢您的帮助!
这一行可能是错误的地方:var model = try! MyModel(configuration: MLModelConfiguration())
由于您已将 mlmodel 文件添加到包中,因此尚未编译。我不是 Swift 包方面的专家,但我不相信 Xcode 现在会自动编译这个模型。当您打开编译后的应用程序包时,您可以自己看到这一点——它是否包含 mlmodel 文件或 mlmodelc 文件夹?
您可能需要将 mlmodelc 添加到包中,而不是 mlmodel。您可以通过以下方式创建它:
$ xcrun coremlcompiler compile MyModel.mlmodel .
接下来,在您的应用中,您需要按如下方式加载模型:
let url = YourBundle.url(forResource: "MyModel", withExtension: "mlmodelc")!
let model = try! MyModel(contentsOf: url, configuration: MLModelConfiguration())
其中 YourBundle
是对包含 mlmodelc 文件的包的引用(我猜这是 Swift 包的包)。
下面描述的解决方案对我有用。我希望它是正确的。
转换 MLModel
MLModel 不能直接在 Swift 包中使用。首先需要转换。
$ cd /path/to/folder/containg/mlmodel
$ xcrun coremlcompiler compile MyModel.mlmodel .
$ xcrun coremlcompiler generate MyModel.mlmodel . --language Swift
第一个 xcrun
命令将编译模型并创建一个名为 MyModel.mlmodelc
的文件夹。
第二个 xcrun
命令将生成一个 MyModel.swift
文件。
将模型添加到 Swift 包
我们认为 Swift 包已经存在并且位于 /path/to/MyPackage/
。
- 将
MyModel.mlmodelc
文件夹和MyModel.swift
文件复制到/path/to/MyPackage/Sources/MyPackage
文件夹中
- 在目标资源中添加
MyModel.mlmodelc
文件Package.swift
:
.target(
name: "MyPackage",
dependencies: [],
resources: [.process("MyModel.mlmodelc")]),
实例化 MyModel
在Swift代码中,简单地创建一个MyModel的实例:
let model = try? MyModel(configuration: MLModelConfiguration())
或:
let url = Bundle.module.url(forResource: "MyModel", withExtension: "mlmodelc")!
let model = try? MyModel(contentsOf: url, configuration: MLModelConfiguration())
疑难解答
一开始我遇到了 Type 'MLModel' has no member '__loadContents'
错误。
这似乎是与 XCode 12 有关的错误。
我简单评论了导致问题的2个函数。
有关详细信息,请参阅