【免费下载链接】propel
Differential Programming in JavaScript.
Propel是一款在 JavaScript 中做差分编程(可微编程)的开源库,它的 Experiment 模块能自动为模型训练保存检查点(checkpoint),并在程序中断后从断点继续训练,让你不用再担心训练白跑。本文将带你快速掌握 Propel 实验管理的核心机制。
为什么需要实验管理?
训练神经网络时,最怕两件事:
- ❌ 程序意外中断(断电、报错、Ctrl+C),几小时的训练成果瞬间清零
- ❌ 磁盘被旧参数文件塞满,不知道哪个版本才是最新的
Propel 的Experiment就是为解决这两个问题而设计的:它把"参数存盘、参数恢复、接口对接优化器"这三件事统一封装(见 src/experiment.ts),你只需要一行代码就能获得:
自动检查点 + 断点续训 + 训练进度日志,全程零额外代码。
创建实验:一行代码搞定
通过 API 入口 src/api.ts 导入experiment,调用时只需传入一个实验名:
const exp = await pr.experiment("exp001");experiment函数(src/experiment.ts)会做一件聪明的事:根据运行环境自动选择实现。
| 运行环境 | 使用的实现 | 检查点行为 |
|---|---|---|
| Node.js | DiskExperiment | 保存到磁盘,支持恢复 |
| 浏览器 | BrowserExperiment | 不保存检查点,从 step 0 开始 |
实验名也不能随意取——"cache"是保留名,直接使用会抛出Invalid experiment name.错误。
四个关键配置项
experiment支持传入ExperimentOpts选项(src/experiment.ts),默认值如下:
| 参数 | 默认值 | 作用 |
|---|---|---|
saveSecs | 60 | 两次保存检查点之间的最小间隔(秒) |
checkpointsToKeep | 3 | 最多保留的检查点个数 |
saveOnExit | true | 进程正常退出时,最后再保存一次 |
printStepSecs | 1 | 进度日志的最小打印间隔(秒) |
💡 默认配置意味着:每分钟自动存一次检查点,只保留最近 3 份,旧文件自动删除——对新手来说完全无需操心。
自动检查点:训练过程中如何工作?
每次调用exp.sgd({ lr: 0.01 }, lossFn)执行一步梯度下降时,Experiment.minimize()(src/experiment.ts)会顺带做三件事:
- step 计数 +1,并把当前参数交给优化器做反向传播更新
- 打印进度:按
printStepSecs限流输出step / loss / steps/sec - maybeSave 检查:距离上次保存超过
saveSecs秒就触发save()
保存时(src/disk_experiment.ts),每个参数张量会被序列化成一个.npy文件写入对应检查点目录,并打印类似Checkpoint saved 1.23 mb的日志。保存完成后立即执行清理:按 step 从新到旧排序,超出checkpointsToKeep数量的旧检查点会被自动删除(src/experiment.ts)。
✅ 换句话说:磁盘上永远只有最新的几份检查点,永远不会无限膨胀。
断点续训:中断后自动恢复
真正的"魔法"在createOrRestore()(src/disk_experiment.ts)中。当你再次用同一个实验名创建实验时,它会:
- 扫描实验目录下所有纯数字命名的文件夹(如
00000123) - 找出 step 最大的检查点
- 调用
restore()把所有.npy文件加载回参数对象(src/disk_experiment.ts) - 把 step 计数器恢复到中断前的值
于是你重新运行训练脚本,就会看到类似这样的输出:
checkpoints [ 123 ] Restore checkpoint 123 hello/world float32 [3]从第 123 步无缝继续,不需要写任何"加载模型"的代码。整个过程有完整的测试保障,可以参考 src/disk_experiment_test.ts。
检查点存放在哪里?
默认位于~/.propel/<实验名>/下,也可以设置环境变量PROPEL_ROOT指向自定义目录(src/util_node.ts)。每个检查点是一个以 8 位数字补零命名的目录,内部按参数名存放.npy文件,目录结构如下:
~/.propel/ └── exp001/ ├── 00000120/ │ ├── L1/weights.npy │ └── L2/weights.npy └── 00000123/ ├── L1/weights.npy └── L2/weights.npy实战示例:训练 MNIST
仓库自带一个非常直观的 MNIST 训练示例 src/example.ts,完整展示了实验管理的使用姿势:
const ds = pr.dataset("mnist/train").batch(128).repeat(100); const exp = await pr.experiment("exp001"); for (const batchPromise of ds) { const { images, labels } = await batchPromise; exp.sgd({ lr: 0.01 }, (params) => images.rescale([0, 255], [-1, 1]) .linear("L1", params, 200).relu() .linear("L2", params, 100).relu() .linear("L3", params, 10) .softmaxLoss(labels)); if (maxSteps && exp.step >= maxSteps) break; }几个值得注意的细节:
- 参数通过
params.define(...)在计算图中惰性定义,首次遇到才初始化(src/params.ts) - 损失函数必须写成闭包、在回调内部计算 loss,这样才能保证反向传播的追踪不会泄漏内存(src/experiment.ts)
- 想换优化器可以用更通用的
exp.minimize(optimizer, opts, lossFn),优化器实现见 src/optimizers.ts
运行方式(需先全局安装ts-node):
ts-node example.ts中途Ctrl+C后再次执行同一命令,就会自动从最近的检查点继续训练 🎉
常见问题速查
| 问题 | 说明 |
|---|---|
| 浏览器里为什么没有检查点? | BrowserExperiment的save()是空实现,磁盘检查点仅在 Node 环境可用(src/experiment.ts) |
| 退出时还会保存吗? | 会。saveOnExit默认为true,进程以退出码 0 结束且step > 0时会再存一次(src/disk_experiment.ts) |
| 如何临时换存储位置? | 设置PROPEL_ROOT环境变量即可 |
| 训练日志太频繁怎么办? | 调大printStepSecs;日志限流逻辑见 src/experiment.ts |
小结
Propel 的 Experiment 模块用极小的 API 面提供了生产级的实验管理能力:
- 📦自动检查点:
saveSecs定时存盘,checkpointsToKeep自动清理旧文件 - ⏩断点续训:同名实验自动
restore最新检查点,无缝续跑 - 📊进度可视:限流打印 step、loss 和 steps/sec
- 🛡️退出兜底:正常退出前最后一刻再保存一次
对于刚接触 JavaScript 机器学习的开发者来说,记住一句话就够了:创建实验时给它起个好名字,剩下的交给 Propel。
【免费下载链接】propel
Differential Programming in JavaScript.
相关推荐
训练中断不用慌:OpenRLHF断点续训全攻略
训练中断不用慌:OpenRLHF断点续训全攻略 在大模型训练过程中,意外断电、显存溢出或网络中断等问题时常导致训练被迫中止。重新开始不仅浪费算力,更可能错过最佳
人工智能大模型强化学习RLHF分布式训练微调Composer Checkpointing 实战指南:自动保存、断点续训与云端对象存储全攻略
Composer Checkpointing 实战指南:自动保存、断点续训与云端对象存储全攻略 导读 本指南围绕 Composer 训练框架的检查点(Check
深度学习分布式训练模型优化训练中断自救指南:ControlNet检查点机制与状态恢复全攻略
训练中断自救指南:ControlNet检查点机制与状态恢复全攻略 ControlNet作为强大的扩散模型控制工具,其训练过程往往耗时且资源密集。本文将详细介绍C
人工智能大模型深度学习计算机视觉媒体生成微调
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考