 Shaun ZhouandClaude Opus 5
|
0f5bb4a5c0
|
feat(cluster): 加 --train-only,自监督训练与聚类可分两步跑
engine/simclr.py 与 engine/cluster.py 本来就互不引用,唯一接口是
simclr_backbone.pth;耦合只在 CLI——method=simclr 会训练完直接聚类。
此前"只聚类"可以用 simclr.checkpoint 做到,"只训练"没有办法。
- --train-only:训练存完权重即退出,不抽特征也不聚类,并打印下一步的聚类命令
- 与 method=pretrained / simclr.checkpoint / --sweep-k 组合时立刻报错说明原因,
而不是跑完才发现没有产出
- 典型用法:GPU 机器上 --train-only 跑几十小时,之后拿权重反复调 k,每次约 1 分钟
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2026-09-07 11:38:59 +08:00 |
|
 Shaun ZhouandClaude Opus 5
|
004d7a1ce7
|
fix(simclr): 换优化器种类时不再加载不兼容的动量缓冲
adamw 换成 sgd 时 load_state_dict 不会报错,SGD 会收下 AdamW 的 exp_avg/exp_avg_sq
却永远用不上——动量实际从零开始,但状态里白占内存,之后存盘还会一路带下去。
改为检测到优化器种类变化就跳过加载并给出日志,模型权重与训练进度不受影响。
README 补一张表,说明续训时哪些配置按 yaml、哪些来自存档、哪些不能改。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2026-09-05 11:10:04 +08:00 |
|
 Shaun ZhouandClaude Opus 5
|
b7505a743d
|
fix(simclr): 续训以配置为准,不再被存档里的超参静默覆盖
optimizer.load_state_dict 会整体覆盖 param_groups,把 lr / weight_decay 连同动量缓冲
一起还原成存档时的值。改了 yaml 再续训,改动会被静默吃掉:配置写 lr=5e-4,
实际仍按存档的 1e-3 训,scheduler.base_lrs 也是旧值。
改为「配置文件是唯一真相源,存档只提供进度」:
- 加载优化器状态前先抄下配置构造出的每组超参,加载后按组写回,只留下动量缓冲;
按组写回也保住了 build_optimizer 的分组结构(BN 与 bias 那组 weight_decay=0)
- 调度器统一按当前配置重建再快进到已训 epoch,不再恢复存档状态(它带着旧的
T_max 与 base_lrs)。cosine/step/multistep 都是 epoch 的确定性函数,
快进与恢复状态等价,因此不存在第二种行为
- 存档里额外记下当时的 optimizer/scheduler 配置,续训时逐项列出差异,
明确说明按当前配置执行
- 补回归测试:改 lr/weight_decay/总轮数后续训,三者都按 yaml 生效,
分组结构与动量缓冲不受影响
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2026-09-04 21:46:40 +08:00 |
|
 Shaun ZhouandClaude Opus 5
|
865cdd7210
|
fix(simclr): 续训时改变总轮数不再让学习率卡在 0
resume 会恢复调度器状态,其中包含存档时的 T_max。原计划 10 轮的 cosine 跑完后
学习率已降到 0,此时把 epochs 改成 30 接着练,学习率仍是 0——训练照常进行、
日志照常打印,但一步都学不动。是静默失败,比报错更难发现。
- 总轮数与存档一致时行为不变,直接恢复调度器状态
- 不一致时按新的总轮数重建调度器,并快进到当前 epoch;重建前先把 lr 复位回
initial_lr,因为 cosine 的链式实现基于当前 lr 递推,从 0 出发只会一路留在 0
- 实测续训到 30 轮时 lr 恢复为 7.50e-04,与 cosine 在 10/30 处的理论值一致
- 补三个回归测试:改变总轮数后的学习率、总轮数不变时直接恢复状态、
save_interval 落的中间盘可直接续训
- 修正一个旧测试:它断言续训后 lr 仍等于旧计划末尾的 0,编码的是错误行为
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2026-09-04 17:25:45 +08:00 |
|
 Shaun ZhouandClaude Opus 5
|
e4bd794025
|
feat(cluster): 输出簇分布图,直观展示簇间距离
在 preview 拼图的同级目录生成 cluster_scatter.png:
- 左:聚类空间的 PCA 二维投影,散点按簇着色 + 质心标记,标题标注两个主成分的方差占比
- 右:质心两两距离矩阵(在聚类空间里算,不是投影后),带数值标注
投影用 PCA 而不是 t-SNE/UMAP——后两者为了把簇拉开会扭曲簇间距离,
而这张图的目的就是看距离。
- ClusterResult 新增 points 字段,保留 KMeans 实际使用的空间供可视化复用,
质心与散点用同一组主成分变换,避免质心飘到簇外
- summary.json 新增 centroid_distances
- 新增 scatter 配置块(enabled / max_points / point_size / alpha / figsize / dpi)
- 中文字体按 PingFang / Noto Sans CJK 等顺序探测,找不到自动退回英文标签,
不会画成豆腐块
- 新增依赖 matplotlib
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2026-09-04 15:09:35 +08:00 |
|
 Shaun ZhouandClaude Opus 5
|
345dee50da
|
feat(simclr): 支持断点续训,恢复优化器与调度器状态
此前 simclr.checkpoint 的语义是"有权重就跳过训练",没有真正的续训:
中途停掉再启动只能从头再来,或者放弃已训的轮次。
- 新增 simclr_last.pth:骨架 + 投影头 + 优化器 + 调度器 + scaler + epoch + step,
与给下游用的 simclr_backbone.pth 并存,两者在同一时机落盘
- 新增 simclr.resume:载入完整状态从下一个 epoch 接着练。只恢复权重不恢复动量与
cosine 进度的话,续训时损失会先反弹一段
- resume 与 checkpoint 互斥(同时给直接报错);拿只含骨架的 simclr_backbone.pth
去 resume 会给出可操作的报错,提示改用 checkpoint
- 续训轮数已达计划值时不再训练,只打警告
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2026-09-03 09:34:55 +08:00 |
|
 Shaun ZhouandClaude Opus 5
|
be6173c746
|
feat(simclr): 接入 SwanLab 可视化,并补上本地看板缺失的依赖
- SimCLRTrainer 记录 simclr/loss、loss_avg、lr(按 step)与 epoch_loss、
epoch_seconds、gpu_mem_peak_mb(按 epoch),超参为完整 yaml 配置;
正常结束与 KeyboardInterrupt 两条路径都会 finish()
- 配置新增 simclr.swanlab(字段同 train.swanlab),默认 mode: local,
不需要登录,日志写到 <work_dir>/swanlog
- 依赖改为 swanlab[dashboard]:此前 `swanlab watch` 在干净环境里会报
"Please install the swanboard package",README 里检测训练那节的看板命令
同样受影响,现已随 uv sync 装好
- README 补齐本地看板/云端/离线补传三种用法与端口、局域网参数
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2026-09-03 09:24:39 +08:00 |
|
 Shaun ZhouandClaude Opus 5
|
141cb907f2
|
feat: 支持 cuda / mps / cpu 三后端,Mac 上可用 MPS 训练
移除"训练必须有 Nvidia GPU"的硬性守卫,改为按后端能力分派。
- utils/device: resolve_device("auto") 按 cuda > mps > cpu 挑最快的可用后端;
显式指定不可用的后端时直接报错,不会悄悄退回 CPU——训练慢几十倍却不吭声是最坏的情况
- AMP 随后端取默认值:CUDA 开、MPS 关。MPS 上 autocast 数值正常但实测更慢
(tiny_conv @128²:fp32 76 ms/步、fp16 90 ms、bf16 108 ms),需要时 amp: true 可强开
- PeakMemory 统一显存峰值统计:CUDA 读内置计数器,MPS 无峰值 API 改用逐 step 采样
(是下界,日志与产出里已标注)
- profile_inference 支持 MPS,并提示 torch.profiler 没有 MPS 的 ProfilerActivity,
算子明细只反映 CPU 侧下发耗时
- train.py / eval.py 新增 --device,配置默认改为 auto
- check_env 改为列出全部可用后端与 auto 的选择结果
实测:tiny_conv 训练在 MPS 上比 CPU 快约 32 倍。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2026-09-02 21:43:35 +08:00 |
|
 Shaun ZhouandClaude Opus 5
|
d6adea5b05
|
test: 单元测试与端到端冒烟
88 个测试覆盖配置继承、注册表、GPU 守卫、YOLO 格式解析、数据集、模型形状、
标签模式、聚类原语与 SimCLR 损失,以及 train.py / eval.py / 聚类脚本的入口接线。
含两条回归测试:
- PCA 白化放大噪声方向导致簇塌陷(默认 whiten=False 的依据)
- classes 写成 data.yaml 路径时 num_classes 必须是类别数而非路径字符串长度
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2026-09-02 17:55:47 +08:00 |
|