关于 coreml
面向 iOS 开发者的 Swift Core ML 集成技能,涵盖模型加载、配置、推理与部署,并强调异步加载、模型复用和性能检查。
主要功能
- 01加载与配置 Core ML 模型
- 02执行单次与批量预测
- 03使用 MLTensor 与 MLMultiArray
- 04通过 Vision 处理图像输入
- 05分析性能与计算设备
- 06部署及管理模型内存
适用场景
- 01在 iOS 应用中运行本地模型
- 02处理图像分类或视觉推理
- 03为多个输入执行批量推理
- 04检查模型延迟与设备分配
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ dpearson2699/ swift-ios-skills --skill coreml安装后在 Claude Code 中输入/coreml确认已加载。
附带文件evals/evals.jsonreferences/coreml-swift-integration.md
详细介绍
Core ML Swift 集成
在 iOS 应用中加载、配置和运行 Core ML 模型。本技能涵盖 Swift 侧的内容:模型加载、预测、MLTensor、性能分析和部署。
范围边界: Python 侧的模型转换、优化(量化、调色板化、剪枝)和框架选择由
apple-on-device-ai技能负责。本技能仅负责 Swift 集成。
请参阅 references/coreml-swift-integration.md,了解完整的代码模式,包括基于 actor 的缓存、批量推理、图像预处理和测试。
目录
- 加载模型
- 模型配置
- 进行预测
- MLTensor(iOS 18+)
- 使用 MLMultiArray
- 图像预处理
- 多模型流水线
- Vision 集成
- 性能分析
- 模型部署
- 内存管理
- 常见错误
- 审核清单
- 参考资料
加载模型
自动生成的类
将 .mlmodel 或 .mlpackage 添加到应用目标时,Xcode 会生成带有类型化输入/输出的 Swift 类。尽可能使用这种方式。
import CoreML
let config = MLModelConfiguration()
config.computeUnits = .all
let model = try MyImageClassifier(configuration: config)
手动加载
当模型在运行时下载或存储在包外时,请从 URL 加载。
let modelURL = Bundle.main.url(
forResource: "MyModel", withExtension: "mlmodelc"
)!
let model = try MLModel(contentsOf: modelURL, configuration: config)
异步加载(iOS 15+)
加载模型而不阻塞主线程。大型模型优先使用此方式。
let model = try await MLModel.load(
contentsOf: modelURL,
configuration: config
)
在运行时编译(iOS 16+)
在设备上将 .mlpackage 或 .mlmodel 编译为 .mlmodelc。适用于从服务下载的模型。每个模型版本只需编译一次,而不是每次启动都编译。
let compiledURL = try await MLModel.compileModel(at: packageURL)
let model = try await MLModel.load(contentsOf: compiledURL, configuration: config)
缓存编译后的 URL——每次启动都重新编译是一个错误。将 compiledURL 复制到持久化位置(例如,Application Support)。审核运行时加载的模型时,请一并指出以下两点:异步 MLModel.compileModel(at:) 仅适用于 iOS 16+,且必须缓存编译后的模型,以免应用每次启动时都重新编译。
模型配置
MLModelConfiguration 用于控制计算单元、GPU 访问和模型参数。
计算单元决策表
| 值 | 用途 | 选择时机 |
|---|---|---|
.all | CPU + GPU + Neural Engine | 默认值。由系统决定。 |
.cpuOnly | CPU | 用于确定性测试、仅 CPU 的回退方案,或在性能分析表明加速器策略、资源争用、热状态或能耗预算构成限制因素后,处理受约束的工作。 |
.cpuAndGPU | CPU + GPU | 需要 GPU,但模型包含 ANE 不支持的运算。 |
.cpuAndNeuralEngine(iOS 16+) | CPU + Neural Engine | 对兼容模型而言,能效最佳。 |
let config = MLModelConfiguration()
config.computeUnits = .cpuAndNeuralEngine
// Optional fallback for constrained work after profiling and policy review
config.computeUnits = .cpuOnly
配置属性
let config = MLModelConfiguration()
config.computeUnits = .all
config.allowLowPrecisionAccumulationOnGPU = true // faster, slight precision loss
进行预测
使用自动生成的类
生成的类提供类型化的输入/输出结构体。
let model = try MyImageClassifier(configuration: config)
let input = MyImageClassifierInput(image: pixelBuffer)
let output = try model.prediction(input: input)
print(output.classLabel) // "golden_retriever"
print(output.classLabelProbs) // ["golden_retriever": 0.95, ...]
使用 MLDictionaryFeatureProvider
当输入是动态的或在编译时未知时使用。
let inputFeatures = try MLDictionaryFeatureProvider(dictionary: [
"image": MLFeatureValue(pixelBuffer: pixelBuffer),
"confidence_threshold": MLFeatureValue(double: 0.5),
])
let output = try model.prediction(from: inputFeatures)
let label = output.featureValue(for: "classLabel")?.stringValue
在异步工作流中进行预测
MLModel.prediction(...) 是同步的。在异步流水线中,保持模型加载为异步操作,然后从 actor 或非主线程任务中运行预测,不要在预测调用上添加 await。
let output = try model.prediction(from: inputFeatures)
批量预测
在一次调用中处理多个输入,以提高吞吐量。
let batchInputs = try MLArrayBatchProvider(array: inputs.map { input in
try MLDictionaryFeatureProvider(dictionary: ["image": MLFeatureValue(pixelBuffer: input)])
})
let batchOutput = try model.predictions(fromBatch: batchInputs)
for i in 0..<batchOutput.count {
let result = batchOutput.features(at: i)
print(result.featureValue(for: "classLabel")?.stringValue ?? "unknown")
}
批量处理时,如果不使用显式的 MLPredictionOptions,请使用 predictions(fromBatch:)。只有同时传入 MLBatchProvider 和 MLPredictionOptions 时,才使用 predictions(from:options:);单独调用 predictions(from:) 并不是不带选项的批量 API。
批量处理前,先验证一个具有代表性的单个输入。然后验证批量输出的数量/顺序、特征类型、领域不变量,以及与单输入结果的一致性。如果失败,应先修复确定性的输入、形状、模型或配置问题,再重新运行测试样例和实体设备性能分析。
有状态预测(iOS 18+)
对于需要在多次预测之间保持状态的模型(序列模型、
大模型、音频累加器),请使用 MLState。创建一次状态,并将其传递给每次预测调用。
let state = model.makeState()
// Each synchronous prediction carries forward the internal model state
for frame in audioFrames {
let input = try MLDictionaryFeatureProvider(dictionary: [
"audio_features": MLFeatureValue(multiArray: frame)
])
let output = try model.prediction(from: input, using: state)
let classification = output.featureValue(for: "label")?.stringValue
}
MLState 遵循 Sendable,但 Sendable 并不意味着同一状态可安全地用于并发推理。使用同一状态的预测必须串行执行;预测进行期间不要读取或写入状态缓冲区。对于每个独立的并发流,请调用
model.makeState()。如果需要 MLPredictionOptions,iOS 18+ 也提供了异步
prediction(from:using:options:) 重载;仍须遵循每个状态同一时间只能有一次预测在执行的规则。
MLTensor(iOS 18+)
MLTensor 是用于预处理和后处理的 Swift 原生多维数组。运算采用惰性执行——调用 await tensor.shapedArray(of:) 可将结果物化。
import CoreML
// Creation
let tensor = MLTensor([1.0, 2.0, 3.0, 4.0])
let zeros = MLTensor(zeros: [3, 224, 224], scalarType: Float.self)
// Reshaping
let reshaped = tensor.reshaped(to: [2, 2])
// Math operations
let softmaxed = tensor.softmax(alongAxis: -1)
let centered = tensor - tensor.mean()
// Interop with MLShapedArray / MLMultiArray
let shaped = await tensor.shapedArray(of: Float.self)
let multiArray = try MLMultiArray(shaped)
let shapedAgain = MLShapedArray<Float>(multiArray)
不要臆造用于统计或桥接的 MLTensor API。避免使用 MLTensor(multiArray)、tensor.std()、tensor.standardDeviation()、直接访问惰性缓冲区或同步提取结果等示例;请在张量流水线之外,或使用经源代码确认支持的张量运算,执行不受支持的 DSP/统计操作。
使用 MLMultiArray
MLMultiArray 是非图像模型输入和输出的主要数据交换类型。自动生成的类需要数组类型特征时,请使用它。
// Create a 3D array: [batch, sequence, features]
let array = try MLMultiArray(shape: [1, 128, 768], dataType: .float32)
// Write values
for i in 0..<128 {
array[[0, i, 0] as [NSNumber]] = NSNumber(value: Float(i))
}
// Read values
let value = array[[0, 0, 0] as [NSNumber]].floatValue
let data: [Float] = [1.0, 2.0, 3.0]
let shaped = MLShapedArray(scalars: data, shape: [3])
let fromShaped = try MLMultiArray(shaped)
高级 MLMultiArray 用法(包括 NLP 词元化和音频特征提取),请参阅 references/coreml-swift-integration.md。
图像预处理
图像模型需要 CVPixelBuffer 输入。对于来自相机或照片图库的照片,请使用 CGImage 转换。Vision 的 VNCoreMLRequest 会自动处理此过程;只有直接使用 MLModel 进行预测时才需要手动转换。
如需完整且经过验证的 CVPixelBuffer 转换方法,以及其他归一化或裁剪模式,请加载图像预处理。
多模型流水线
当预处理或后处理需要单独的模型时,请串联模型。
// Sequential inference: preprocessor -> main model -> postprocessor
let preprocessed = try preprocessor.prediction(from: rawInput)
let mainOutput = try mainModel.prediction(from: preprocessed)
let finalOutput = try postprocessor.prediction(from: mainOutput)
对于由 Xcode 管理的流水线,请使用 .mlpackage 中的流水线模型类型。每个子模型都会在其最适合的计算单元上运行。
Vision 集成
使用 Vision 运行 Core ML 图像模型,可自动进行图像预处理(调整大小、归一化、色彩空间转换和方向校正)。
现代方式:CoreMLRequest(iOS 18+)
import Vision
import CoreML
let model = try MLModel(contentsOf: modelURL, configuration: config)
let request = CoreMLRequest(model: .init(model))
let results = try await request.perform(on: cgImage)
if let classification = results.first as? ClassificationObservation {
print("\(classification.identifier): \(classification.confidence)")
}
旧版方式:VNCoreMLRequest
let vnModel = try VNCoreMLModel(for: model)
let request = VNCoreMLRequest(model: vnModel) { request, error in
guard let results = request.results as? [VNRecognizedObjectObservation] else { return }
for observation in results {
let label = observation.labels.first?.identifier ?? "unknown"
let confidence = observation.labels.first?.confidence ?? 0
let boundingBox = observation.boundingBox // normalized coordinates
print("\(label): \(confidence) at \(boundingBox)")
}
}
request.imageCropAndScaleOption = .scaleFill
let handler = VNImageRequestHandler(cvPixelBuffer: pixelBuffer)
try handler.perform([request])
有关 Vision 框架的完整用法(文本识别、条形码检测、文档扫描),请参阅
vision-framework技能。
性能分析
MLComputePlan(iOS 17.4+)
在运行预测之前,检查每个运算将使用哪个计算设备。如需了解模型结构遍历、设备使用情况和预估成本检查,请加载 MLComputePlan 详细用法。
Instruments
在 Instruments 中使用 Core ML 模板进行性能分析:
- 模型加载时间
- 预测延迟(按运算细分)
- 计算设备分配(每个运算使用 CPU/GPU/ANE)
- 内存分配
为获得准确结果,请在调试器外运行(Xcode:Product > Profile)。
模型部署
将体积小且离线运行至关重要的模型打包进应用。对于新的大型资源或可更新资源,优先使用 Background Assets;仅在现有 ODR 项目中保留 On-Demand Resources。下载源模型后,按版本编译一次并持久化 .mlmodelc;在支持范围最低的实体设备上测试加载、首次及后续预测、生命周期转换和内存使用情况。如需了解实现详情,请加载部署模式。
内存管理
- 进入后台时卸载: 当应用进入后台时释放模型引用,以释放 GPU/ANE 内存。返回前台时重新加载。
- 共享模型实例: 绝不要基于同一个已编译模型创建多个
MLModel实例。使用 actor 提供共享访问。 - 监控内存压力: 大型模型(>100 MB)可能触发内存警告。注册监听
UIApplication.didReceiveMemoryWarningNotification,并在内存压力较大时释放缓存的模型。
有关支持生命周期感知加载和缓存淘汰的基于 actor 的模型管理器,请参阅 references/coreml-swift-integration.md。
常见错误
不要: 在主线程上加载模型。
应该: 使用 MLModel.load(contentsOf:configuration:) 异步 API,或在后台 actor 上加载。
原因: 加载大型模型可能需要数秒,导致 UI 卡顿。
不要: 忽略 MLFeatureValue 类型与模型预期类型不匹配的问题。
应该: 确保类型完全匹配——图像使用 MLFeatureValue(pixelBuffer:),而非原始数据。
原因: 类型不匹配会导致难以诊断的运行时崩溃,或悄无声息地产生错误结果。
不要: 每次预测都创建新的 MLModel 实例。
应该: 加载一次并重复使用。使用 actor 管理模型生命周期。
原因: 模型加载会占用大量内存和计算资源。
不要: 跳过模型加载和预测的错误处理。 应该: 捕获错误,并在模型失败时提供回退行为。 原因: 在较旧设备上或资源受限时,模型可能无法加载。
不要: 假设所有操作都在 Neural Engine 上运行。
应该: 使用 MLComputePlan(iOS 17.4+)验证每项操作的设备调度情况。
原因: 不受支持的操作会回退到 CPU,可能成为流水线的性能瓶颈。
不要: 在将图像传递给 Vision + Core ML 之前手动处理图像。
应该: 使用 CoreMLRequest(iOS 18+)或 VNCoreMLRequest(旧版),让 Vision 负责预处理。
原因: Vision 能正确处理方向、缩放和像素格式转换。
审查清单
- 异步加载模型(不阻塞主线程)
- 根据使用场景设置
MLModelConfiguration.computeUnits - 在多次预测间重复使用模型实例(而非每次都重新创建)
- 在可用时使用自动生成的类(类型化输入/输出)
- 针对模型加载和预测失败进行错误处理
- 如果在运行时编译模型,则持久缓存已编译的模型
- 图像输入使用 Vision 流水线(iOS 18+ 使用
CoreMLRequest,或使用VNCoreMLRequest)以确保正确预处理 - 检查
MLComputePlan,以验证计算设备调度情况(iOS 17.4+) - 处理多个输入时使用批量预测
- 模型大小适合部署策略(bundle、Background Assets、ODR)
- 在目标设备上测试内存使用情况(尤其是 RAM 较少的旧设备)
- 在调试器外运行预测,以准确测量性能
参考资料
- 模式和代码:references/coreml-swift-integration.md
- 模型转换和优化(Python 端):参见
apple-on-device-ai技能 - Apple 文档:Core ML | MLModel | MLTensor | MLComputePlan | Background Assets