Highlight
Create ML 在 macOS Big Sur 引入异步训练、checkpoint 和 Combine publisher API,让开发者能在 Swift 中观察训练指标、暂停并恢复长时间训练、从中间 checkpoint 导出模型。
核心内容
训练机器学习模型经常卡在等待上。以前在 Create ML 里调用模型构造器,代码会等到训练结束才返回模型。遇到耗时数小时的 object detection(物体检测)训练时,如果达到最大 iteration(迭代次数)后 loss(损失值)还在下降,开发者只能重新设置更大的训练次数,再从头开始。(02:54)
macOS Big Sur 的 Create ML framework 把训练流程拆成可观察、可中断、可恢复的 MLJob。开发者调用新的 train 方法启动异步训练,然后通过 result、progress 和 checkpoints 三个 publisher 处理最终模型、训练指标和中间 checkpoint。cancel() 可以停止训练,同一个 sessionDirectory 会在下一次训练时恢复已有进度。(04:46)
这套 API 的价值在 Style Transfer(风格迁移)里很直观。风格迁移的好坏带有主观判断,内置评估指标不一定能替你决定何时停止。Session 把 checkpoint 中的 stylized validation image(风格化验证图片)取出来,再用 SwiftUI 放进 Playground Live View。训练仍在继续,开发者已经能看到模型每隔几轮产生的真实效果。(16:02)
详细内容
用 sessionParameters 定义训练会话
(04:58)新的训练入口接收 MLTrainingSessionParameters。它把训练会话保存在哪、多久报告一次进度、多久保存一次 checkpoint、最多训练多少轮,都放在同一个参数对象里。
// Session parameters can be provided to `train` method.
let sessionParameters = MLTrainingSessionParameters(
sessionDirectory: sessionDirectory,
reportInterval: 10,
checkpointInterval: 100,
iterations: 1000
)
let job = try MLStyleTransfer.train(trainingData: dataSource,
parameters: trainingParameters,
sessionParameters: sessionParameters)
关键点:
sessionDirectory是训练状态的落盘位置。目录存在时,Create ML 会用它恢复已有 session。reportInterval控制 progress report(进度报告)的频率。间隔越小,反馈越密集,也可能带来额外开销。checkpointInterval控制 checkpoint 保存频率。它决定你能以多细的粒度回看训练过程。iterations是本轮训练的目标迭代次数。后续调用train时可以把这个数字调大,让训练继续往前走。train返回MLJob,训练从同步等待变成异步任务。
用 Combine 取回结果和进度
(06:21)MLJob 的 result publisher 在训练结束时返回模型,失败时返回错误。Session 使用 Combine 的 sink 接收完成状态和模型值。
// Register a sink to receive the resulting model.
job.result.sink { result in
// Handle errors
}
receiveValue: { model in
// Use model
}
.store(in: &subscriptions)
关键点:
result的 completion closure 负责处理成功或失败状态。receiveValueclosure 拿到最终训练好的模型。.store(in: &subscriptions)保留订阅,否则异步训练还没结束,订阅就可能被释放。
(07:07)训练中的 progress 仍然是 Foundation 的 Progress。Create ML 提供 MLProgress helper type(辅助类型),用来读取 loss、accuracy 等模型相关指标。
// Observing progress details
job.progress.publisher(for: \.fractionCompleted)
.sink { [weak job] fractionCompleted in
guard let job = job, let progress = MLProgress(progress: job.progress) else {
return
}
print("Progress: \(fractionCompleted)")
print("Iteration: \(progress.itemCount) of \(progress.totalItemCount ?? 0)")
print("Accuracy: \(progress.metrics[.accuracy] ?? 0.0)")
}
.store(in: &subscriptions)
关键点:
publisher(for: \.fractionCompleted)监听 FoundationProgress的完成比例。[weak job]避免订阅闭包长期持有训练任务。MLProgress(progress:)在新 session 刚创建或切换 phase(阶段)时可能初始化失败,所以代码提前返回。itemCount在训练 phase 代表当前 iteration,在 feature extraction(特征提取)phase 代表已处理的文件或记录。progress.metrics[.accuracy]读取任务相关指标。不同训练任务可能提供 accuracy、loss 或验证集指标。
暂停并恢复长时间训练
(12:04)停止训练只需要调用 cancel()。恢复训练时,再次调用同一个模型类型的 train,并传入相同的 sessionDirectory。
job.cancel()
let resumedJob = try MLStyleTransfer.train(
trainingData: dataSource,
parameters: trainingParameters,
sessionParameters: sessionParameters)
resumedJob.progress
.publisher(for: \.fractionCompleted)
.sink { completed in
_ = completed
guard let progress = MLProgress(progress: resumedJob.progress) else { return }
if let styleLoss = progress.metrics[.styleLoss] { _ = styleLoss }
if let contentLoss = progress.metrics[.contentLoss] { _ = contentLoss }
}
.store(in: &subscriptions)
resumedJob.result.sink { result in
print(result)
}
receiveValue: { model in
try? model.write(to: sessionDirectory)
}
.store(in: &subscriptions)
关键点:
cancel()让开发者在达到固定 iteration 前主动停止训练。sessionParameters里的目录决定恢复位置。要开始新训练,就删除旧目录或换一个路径。- 恢复后的
resumedJob仍然提供 progress 和 result publisher。 styleLoss与contentLoss来自 Style Transfer 任务,说明 metrics 会随模型类型变化。model.write(to:)把完成后的模型写入 session 目录,方便后续检查或部署。
从 checkpoint 观察和导出模型
(14:26)异步训练会自动生成 checkpoint。checkpoints publisher 给开发者一个处理新 checkpoint 的入口,可以记录自定义指标、生成模型,或按自己的规则停止训练。
// Register for receiving checkpoints.
job.checkpoints.sink { checkpoint in
// Process checkpoint
}
.store(in: &subscriptions)
关键点:
- checkpoint 会保存到 session folder(会话目录)中。
- publisher 在新 checkpoint 产生时触发。
- feature extraction checkpoint 和 training checkpoint 都可能出现,后续处理要区分 phase。
(14:50)只有 training checkpoint 能直接生成模型。Session 在代码里先检查 phase,再把 checkpoint 转成 MLActivityClassifier。
// Generate a model from a checkpoint
guard checkpoint.phase == .training else {
// Not a training checkpoint, can't create model yet.
return
}
let model = try MLActivityClassifier(checkpoint: checkpoint)
try model.write(to: url)
关键点:
checkpoint.phase == .training是导出模型前的必要检查。MLActivityClassifier(checkpoint:)从某个训练中间态创建模型。model.write(to:)能把中间模型保存下来,用于比较或提前试用。- transcript 明确提到 training checkpoint 可用于 action classification、object detection、Style Transfer 和 activity classification。
管理历史 session 和 checkpoint 空间
(15:40)MLTrainingSession 是 checkpoint 和 metadata(元数据)的集合。开发者可以恢复一个 session,查看创建时间、当前 phase、iteration,以及历史 metrics。
let session = MLObjectDetector.restoreTrainingSession(sessionParameters: sessionParameters)
let losses = session.checkpoints.compactMap { $0.metrics[.loss] as? Double }
关键点:
restoreTrainingSession用同一组sessionParameters找回训练会话。session.checkpoints让你离线分析整段训练历史。metrics[.loss]可以用来画 loss 曲线,判断是否需要延长训练。
(15:48)checkpoint 会占用磁盘。Create ML 允许按条件删除不再需要的 checkpoint。
let session = MLObjectDetector.restoreTrainingSession(sessionParameters: sessionParameters)
// Save space by removing some checkpoints
session.removeCheckpoints { $0.iteration < 500 }
关键点:
removeCheckpoints接收一个判断闭包。$0.iteration < 500会删除较早的 checkpoint。- 保留关键节点、删除早期节点,能在可追溯性和磁盘占用之间做取舍。
在 Playground 里可视化训练效果
(16:24)Style Transfer checkpoint 会携带 stylizedImageURL。Session 把它转成 NSImage,再用 SwiftUI 拼成 Playground Live View。
job.checkpoints
.compactMap { $0.metrics[.stylizedImageURL] as? URL }
.receive(on: DispatchQueue.main)
.map { NSImage(byReferencing: $0) }
.sink { image in
let _ = image
let view = VStack {
Image(nsImage: image)
.resizable()
.aspectRatio(contentMode: .fit)
Image(nsImage: style)
.resizable()
.aspectRatio(contentMode: .fit)
Image(nsImage: validation)
.resizable()
.aspectRatio(contentMode: .fit)
}.frame(maxHeight: 1400)
PlaygroundSupport.PlaygroundPage.current.setLiveView(view)
}
.store(in: &subscriptions)
关键点:
.compactMap只保留带有stylizedImageURL的 checkpoint。.receive(on: DispatchQueue.main)把 UI 更新切回主线程。VStack同时展示当前风格化结果、style image(风格图)和 validation image(验证图)。setLiveView让训练过程直接出现在 Xcode Playground 中。
核心启发
训练进度面板
做什么:为内部模型训练工具加一个实时进度面板,显示 fraction completed、iteration、loss、accuracy 和验证集指标。
为什么值得做:Session 展示了 MLJob.progress 与 MLProgress,训练指标可以在训练中读取,不必等最终模型生成后才判断质量。
怎么开始:在调用 train 后订阅 job.progress.publisher(for: \.fractionCompleted),用 MLProgress(progress:) 读取 metrics,再把数据写到日志、图表或 SwiftUI 界面。
可恢复的长时间训练任务
做什么:给 object detection、Style Transfer 或 activity classification 训练加上暂停、恢复和延长训练能力。
为什么值得做:transcript 提到 object detection 训练可能耗时五小时。若 loss 还在下降,复用 sessionDirectory 能继续已有训练进度。
怎么开始:把 sessionDirectory 固定到某个实验目录,创建 MLTrainingSessionParameters,停止时调用 job.cancel(),恢复时用同一目录再次调用 train。
checkpoint 模型对比库
做什么:把训练过程中关键 checkpoint 导出成多个候选模型,让团队比较中间版本的实际效果。
为什么值得做:Create ML 会自动保存 training checkpoint,并允许通过 MLActivityClassifier(checkpoint:) 这类 initializer 生成模型。
怎么开始:订阅 job.checkpoints,先检查 checkpoint.phase == .training,再从 checkpoint 创建模型并写入带 iteration 编号的目录。
训练历史清理工具
做什么:写一个脚本扫描 session 目录,保留关键 iteration,删除早期或无价值 checkpoint。
为什么值得做:training checkpoint 会持续保存,长期实验会消耗磁盘。MLTrainingSession 提供恢复 session 和删除 checkpoint 的 API。
怎么开始:调用 restoreTrainingSession(sessionParameters:),读取 session.checkpoints 中的 loss 或 iteration,再用 removeCheckpoints 清理旧 checkpoint。
Playground 可视化实验台
做什么:把 Style Transfer 的 checkpoint 图片实时放进 Playground Live View,对比风格图、原验证图和当前输出。
为什么值得做:风格迁移质量带有主观判断,session 演示了通过 stylizedImageURL 直接观察中间效果。
怎么开始:从 checkpoint metrics 取出 .stylizedImageURL,转成 NSImage,在主线程用 SwiftUI 的 VStack 展示三张图。
关联 Session
- Build Image and Video Style Transfer models in Create ML — 讲解如何用 Create ML 训练风格迁移模型,本场演示正是用它展示训练进度和 checkpoint 可视化。
- Build an Action Classifier with Create ML — 展示 Create ML 动作分类训练流程,可和本场的训练会话、checkpoint 与进度监听配合使用。
- Use model deployment and security with Core ML — 介绍训练完成后的 Core ML 模型如何部署、更新和加密,连接模型训练与发布环节。
- Get models on device using Core ML Converters — 补充从 TensorFlow、PyTorch 等训练框架转换模型到 Core ML 的流程。
评论
GitHub Issues · utterances