探索机器学习开发体验
Explore the machine learning development experience
2022年6月6日
一句话判断
从找到开源模型到实机运行——这场 Session 是一份完整的端到端 ML 应用开发流程演示,特别适合第一次把 ML 模型集成到 iOS 应用的开发者。
这场 Session 讲了什么
Session 以一个具体的 ML 任务为线索:将黑白老照片自动上色。完整覆盖了从模型搜索到应用集成的六个阶段:
模型搜索:在学术论文和专用网站上找到合适的开源模型(Colorizer),它接受黑白图像的亮度通道,输出两个色彩通道,组合后生成彩色图像。
模型转换:使用 coremltools 将 PyTorch 模型转换为 Core ML 格式。三步完成:导入模型架构和权重、trace 模型、转换并保存。
模型验证:在 Python 中用 coremltools 运行转换后的模型,对比输出与原始 PyTorch 模型是否一致。
性能评估:使用 Xcode 14 新增的 Core ML Performance Report,拖入模型文件即可获得预测时间估算。示例模型在 iPad Pro M1 上约 90ms,适合静态图片处理。
应用集成:用 Core Image 的新 CIFilter(convertRGBtoLab 和 convertLabToRGB)处理色彩空间转换,用 CIKernel 组合通道,用 Core ML 运行推理。
实时化:通过 Core ML 的动态 batch size 和异步预测 API,将 90ms 的单帧处理优化到支持实时摄像头输入。
值得深挖的点
RGB 到 LAB 色彩空间转换是整个流程的关键前置步骤。Colorizer 模型不直接处理 RGB 图像,而是在 LAB 色彩空间中工作:L 通道代表亮度(作为输入),A 和 B 通道代表色彩(作为输出)。Core Image 新增的 convertRGBtoLab 和 convertLabToRGB 滤镜让这个转换在 GPU 上高效完成。
Xcode 14 的 Core ML Performance Report 是一个被低估的工具。它不需要你写任何测试代码——把 .mlmodel 文件拖进 Xcode,几秒内就能看到在目标设备上的预估推理时间。这让你在写一行 Swift 代码之前就能判断模型是否满足性能要求。
从静态图片到实时摄像头的优化路径展示了 ML 应用的典型演进。90ms 的推理时间对单张图片足够好,但对 30fps 的视频流不够。解决方案包括:动态调整 batch size、使用 Core ML 的异步预测 API、以及利用 Neural Engine 的专用加速。
代码片段
模型转换(Python):
import coremltools as ct
import torch
# 导入 PyTorch 模型
model = Colorizer()
model.load_state_dict(torch.load("colorizer_weights.pth"))
model.eval()
# Trace 模型
example_input = torch.rand(1, 1, 256, 256)
traced_model = torch.jit.trace(model, example_input)
# 转换为 Core ML
mlmodel = ct.convert(
traced_model,
inputs=[ct.TensorType(name="lightness", shape=(1, 1, 256, 256))]
)
mlmodel.save("Colorizer.mlmodel")
应用集成(Swift):
import CoreImage
import CoreML
func colorize(image: CIImage, context: CIContext) -> CIImage? {
// RGB 转 LAB,提取亮度通道
guard let labFilter = CIFilter(name: "CIColorMatrix",
parameters: ["inputImage": image]) else { return nil }
// ... 使用 convertRGBtoLab 滤镜
let lightness = extractLightness(from: labFilter.outputImage!)
// 运行 Core ML 预测
guard let model = try? VNCoreMLModel(for: Colorizer(configuration: MLModelConfiguration())
.model) else { return nil }
// 组合亮度 + 预测的色彩通道
let labResult = combineChannels(lightness: lightness,
channelA: prediction.channelA,
channelB: prediction.channelB)
// LAB 转 RGB
return convertLabToRGB(labResult)
}
自定义 CIKernel 组合通道:
// 自定义 Core Image Kernel,组合 L/A/B 三个通道
let kernelString = """
kernel vec4 combineLAB(sampler lightness, sampler chA, sampler chB) {
vec4 l = sample(lightness, destCoord());
vec4 a = sample(chA, destCoord());
vec4 b = sample(chB, destCoord());
return vec4(l.r, a.r, b.r, 1.0);
}
"""
最佳实践
- 先验证再集成:用 coremltools 在 Python 中验证转换正确性,再用 Performance Report 评估性能
- 色彩空间转换用 Core Image:GPU 上做 RGB/LAB 互转比 Swift 手写或 Metal kernel 更高效
- 性能不达标时考虑模型简化:减小输入分辨率或使用量化
- 摄像头场景用异步预测:避免阻塞主线程
- Neural Engine 是首选推理目标:功耗最低,性能最优
还有什么值得关注
- CIFilter 的
convertRGBtoLab和convertLabToRGB是新增的,详见 “Display EDR content with Core Image, Metal, and SwiftUI” - Core ML Performance Report 在 Xcode 14 中可用
- Session 建议搭配 “Optimize your Core ML usage” 一起看
- 模型验证阶段比较原始模型和转换模型的输出差异是必要的——转换可能引入精度损失