Commit Graph
20 Commits
Author SHA1 Message Date
xzhou 4e6c8aa2ea fix: update work directory in film.yaml and add pearlescent.yaml configuration 2026-09-04 06:54:06 +00:00
xzhou a92d1125d4 fix: uv 换源至清华源 2026-09-04 06:26:16 +00:00
Shaun Zhou 4550fdfa8e feat(cluster): add ImageNet pre-trained model section and adjust batch sizes 2026-09-03 15:47:37 +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 7d5b6ec423 docs(readme): 补全 SimCLR 训练与复用权重聚类的完整流程
- 拆成三步:训练+聚类一条命令(含产出目录树、45 分钟预期、nohup 后台跑法)、
  用 simclr.checkpoint 复用权重重新聚类(约 1 分钟,含 k=2 与 --sweep-k)、
  以及把 --set 固化进 yaml 的写法
- 提醒复用权重时要换 --work-dir,否则会覆盖上次的聚类产出
- 修复三条 uv run 命令的续行反斜杠(此前被折叠成单行)
- 目录表 utils/ 的描述由"GPU 守卫"改为"设备解析(cuda/mps/cpu)"
- profiler 小节补充三后端差异并链到"计算后端"

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-03 09:10:36 +08:00
Shaun ZhouandClaude Opus 5 938d62ea53 docs: SimCLR 域内自监督的实测对比与多后端说明
- 新增 §10.5:SimCLR vs ImageNet 预训练在 14,579 张上的同设置对比。
  只训 1 个 epoch 的域内特征在 k=4 上即追平(轮廓 0.334 vs 0.325),
  在 k=2 上大幅胜出(轮廓 0.469、稳定性 0.991)——目视确认该二分正是
  "有明显缺陷 / 弱纹理近空白",可直接作为流水线的第一级过滤
- 复杂度表补 MPS 实测:特征提取 84s(CPU) -> 51s(MPS),SimCLR 约 65s/epoch
- README 增加"计算后端"小节(三后端的 AMP 默认值、显存统计与限制)
- 流程图与对照表同步去掉已移除的 GPU 守卫

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-02 21:43:35 +08:00
Shaun ZhouandClaude Opus 5 b6f83fcad0 fix(simclr): 周期性落盘,中途中断不再丢失训练成果
此前 fit() 只在全部 epoch 跑完后才保存骨架,一次跑到 epoch 12 被停掉后
13 分钟的训练全部作废。

- 每 save_interval(默认 5)个 epoch 保存一次骨架
- 捕获 KeyboardInterrupt,中断时先落盘再返回
- 聚类脚本改用 resolve_device,自监督分支不再有 GPU 守卫

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-02 21:43:35 +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 4fc0fa5353 docs: 无监督聚类的数学说明、mermaid 图与 README
- docs/unsupervised-clustering.md: 逐图标准化对仿射光照群的不变性证明、
  多 stage 特征的取舍、PCA 白化失效的谱分析、KMeans 收敛性与 kmeans++ 近似比、
  轮廓系数与 NMI 稳定性的定义、NT-Xent 与 InfoNCE 下界,附全部消融数据与代码对照表
- figures/: 四张 mermaid 图(流水线、KMeans 控制流、SimCLR、主成分谱),
  含 .mmd 源、.md 预览与渲染好的 .png
- README: 数据准备、训练评估、多类/单类、SwanLab、Profiler、聚类与自监督的运行说明

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-02 17:55:48 +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
Shaun ZhouandClaude Opus 5 f433e5cf59 feat: 未分类样本的无监督聚类(多 stage 特征 + KMeans,可选 SimCLR)
把 data/film 下所有图片拉平做聚类,不使用任何目录名,簇数由 num_clusters 决定。

预处理针对该批数据的实际情况(14.5k 张已裁好的缺陷小图,中位 152x113,
宽高比 0.24~39.9):尺寸与亮度都是 ROI 裁剪和光照的产物、不是缺陷属性,
因此拉伸到 128x128(不用 letterbox,其填充比例等价于编码了宽高比)并逐图 z-score。

- cluster: torch 实现的 kmeans++/Lloyd(含空簇处理与 n_init)、PCA、轮廓系数、
  NMI 稳定性、多 stage 特征提取;不引 scikit-learn
- 白化默认关闭:CNN 特征谱极陡(λ1/λ32≈165x),白化会把噪声方向抬到与信号同权,
  实测最大簇一度吃掉 96% 的样本
- simclr: NT-Xent 自监督预训练,用项目自己的卷积骨架,权重可直接初始化 DefectNet;
  属于训练,走 require_cuda() 守卫
- 产出 assignments.csv、summary.json、按簇的软链目录与代表样本拼图,供人工核对

全量 14,579 张:轮廓系数 0.326、换种子稳定性 0.964,CPU 约 100 秒。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-02 17:55:47 +08:00
Shaun ZhouandClaude Opus 5 4b1147ed8f feat(scripts): 数据转换、ONNX 导出与推理性能分析
- convert_annotations: labelme / VOC -> YOLO txt,顺带生成 data.yaml
- split_dataset: 切分成 images/{train,val} 与 labels/{train,val},默认建软链不复制数据
- export_onnx: 导出部署用 ONNX,CPU 可跑,缺依赖时提示 `uv sync --group export`
- profile_inference: torch.profiler 测单帧延迟/FPS、CUDA 显存峰值与算子级明细
- check_env: Python / PyTorch / Nvidia GPU 自检

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-02 17:55:20 +08:00
Shaun ZhouandClaude Opus 5 b0d0dfffbb feat: 训练与评估入口及 yaml 配置
- train.py: 先过 require_cuda() 守卫再建模型/数据,支持 --resume 与 --set 覆盖
- eval.py: 允许 CPU,输出定位与分类指标并可写 json
- configs: model/dataset/train/eval 四类,通过 `_base_` 组合;
  classes 既可直接写列表,也可指向 YOLO data.yaml 由框架读 names

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-02 17:55:20 +08:00
Shaun ZhouandClaude Opus 5 ef64e5bf77 feat(engine): 训练评估循环、CenterNet 损失与指标
- trainer: AMP、梯度裁剪、cosine/step 调度、last/best 检查点,按 monitor 指标挑选 best
- losses: penalty-reduced focal loss(heatmap)+ 掩码 L1(wh/offset)+ 分类损失
  (多类 BCE / 单类 CE,随 label_mode 切换)
- metrics: 定位 IoU 匹配下的 P/R/F1 与 mean IoU;分类多标签 micro-F1 与单标签 accuracy,
  两种模式都输出 cls_f1,故 train.monitor 无需跟着改
- optim: BatchNorm 与 bias 不做 weight decay
- visualizer: SwanLab 记录损失/学习率/验证指标/显存峰值,未安装或离线时降级为警告

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-02 17:55:20 +08:00
Shaun ZhouandClaude Opus 5 af22dc639c feat(datasets): YOLO 风格标注数据集与几何/像素增强
- yolo: images/ 与同层 labels/ 的路径约定、`class_id cx cy w h` 归一化行解析
  (兼容分割多边形取外接矩形)、data.yaml 读写;缺失或空 txt 即无缺陷样本
- film_defect: 抛出图像、框、图像级标签;label_mode 决定多热向量还是互斥下标
- transforms: 图框同步的 Resize / Letterbox / CenterCrop / RandomResizedCrop /
  翻转 / ColorJitter / GaussianBlur / PerImageStandardize
- target_encoder: 高斯半径与 heatmap / wh / offset / mask 监督信号编码

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-02 17:55:20 +08:00
Shaun ZhouandClaude Opus 5 3a36aad6c3 feat(models): 纯卷积缺陷分类定位模型
面向实时设备部署,全程只用 convolution,不含 attention / transformer。

- backbones: 自研 tiny_conv(深度可分离,默认)与 torchvision 封装(resnet/mobilenet/shufflenet)
- necks: nearest 上采样 + 3x3 卷积,把特征恢复到 stride 4,兼顾小缺陷定位与速度
- heads: anchor-free 中心点定位头(heatmap + wh + offset)与图像级分类头;
  分类头输出维度随 label_mode 切换(多类多热 / 单类互斥含背景位)
- postprocess: 3x3 max-pool 峰值抑制替代 NMS 循环,无循环、可导出 TensorRT / OpenVINO

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-02 17:54:55 +08:00
Shaun ZhouandClaude Opus 5 f4eff8beee feat(utils): 配置继承、注册表、日志与 Nvidia GPU 守卫
- config: yaml `_base_` 继承 + 深度合并 + 命令行 `--set a.b.c=value` 覆盖,检测循环引用
- registry: 组件按名注册与构建,模型/数据集共用
- device: require_cuda() 守卫,按 CLAUDE.md 约定禁止在无 Nvidia GPU 的设备上训练;
  评估与导出走 resolve_device() 允许 CPU
- labels: multilabel / multiclass 两种图像级标签形式的共用定义
- logging / seed: 控制台+文件日志、随机种子与 cudnn 确定性

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-02 17:54:55 +08:00
Shaun ZhouandClaude Opus 5 0645fc19f7 chore: 初始化 uv 项目配置与忽略规则
- pyproject.toml 采用 uv 应用模式(package = false),直接从仓库根运行入口脚本
- 依赖:torch / torchvision / numpy / pillow / pyyaml / swanlab
- dev 组含 pytest 与 ruff,export 组按需安装 onnx / onnxscript
- 忽略数据集本体、runs/ 训练产物、权重与 .DS_Store

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-02 17:54:55 +08:00
xzhou c0e7c23aef Initial commit 2026-09-01 16:48:33 +08:00