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>
This commit is contained in:
Shaun Zhou
2026-09-02 17:55:48 +08:00
co-authored by Claude Opus 5
parent d6adea5b05
commit 4fc0fa5353
15 changed files with 1475 additions and 0 deletions
+66
View File
@@ -0,0 +1,66 @@
# data
存放数据集本体或指向数据集的软链接;除本文件外的内容都不入库(见 .gitignore)。
标注采用 **YOLO 风格**:`images/` 下每张图在同层 `labels/` 里有一个同名 `.txt`。
```
data/
└── film/
├── images/ # 原图(或指向 NAS 的软链:ln -s /mnt/nas/film/images data/film/images)
│ ├── train/0001.png
│ └── val/0002.png
├── labels/ # 与 images 目录结构一一对应
│ ├── train/0001.txt
│ └── val/0002.txt
└── data.yaml # path / train / val / nc / names
```
标注文件每行一个目标,坐标**相对图像宽高归一化**到 [0, 1],中心点格式:
```
<class_id> <cx> <cy> <w> <h>
0 0.312500 0.204688 0.087500 0.065625
1 0.640625 0.712500 0.120000 0.093750
```
- `class_id` 是 `data.yaml` / 配置里 `classes` 的下标,顺序即含义,改动必须重新训练。
- **空文件或缺失 `.txt` = 无缺陷样本(OK 片)**,会作为纯负样本参与训练。
- 也接受 YOLO 分割格式的多边形行(`class_id x1 y1 x2 y2 ...`),读取时取外接矩形。
`data.yaml` 与 ultralytics 通用:
```yaml
path: data/film
train: images/train
val: images/val
nc: 5
names: {0: scratch, 1: bubble, 2: particle, 3: crease, 4: stain}
```
配置里的 `classes` 既可以直接写类别列表,也可以写成 `data/film/data.yaml` 由框架读取 `names`。
## 还没分类的样本
`data/film` 下按人工整理留下的目录(`grease`、`wrinkle`、`反面纵黑点` ……)只是历史产物,
不是最终类别。要重新梳理类别时用无监督聚类,它会忽略这些目录名、把所有图拉平处理:
```bash
uv run python scripts/cluster_unlabeled.py --config configs/cluster/film.yaml
```
结果里的 `clusters/cluster_XX/` 是软链目录,人工确认后再决定每个簇对应什么缺陷、
以及是否要合并/拆分。
## 从其它格式转过来
```bash
# labelme / VOC -> YOLO txt(顺带生成 data.yaml)
uv run python scripts/convert_annotations.py --format labelme \
--input data/film/labelme --images data/film/images \
--output data/film/labels --data-yaml data/film/data.yaml
# 划分 train / val(默认建软链,不复制数据)
uv run python scripts/split_dataset.py --images data/film/images \
--labels data/film/labels --val-ratio 0.2 --data-yaml data/film/data.yaml
```