docs: 修正 clusters/ 是软链的说法

默认 link_mode 是 hard(scripts/cluster_unlabeled.py 与 configs/cluster/film.yaml
都是),README 里却有三处说成软链,与同一节上文"放的是硬链接"自相矛盾。

- 产出清单与导出小节改为硬链接。
- "导出的是真实文件(不是软链)"在硬链接下不成立——条目本身就是原图数据,
  复制的意义是脱离 runs/ 路径、去掉排序前缀、避免删改牵连原图。
- 跨机器那条注记原本只讲失效软链,补成 SourceResolver 实际处理的三种条目
  (硬链接走 inode 反查 assignments.csv / 有效软链 / 失效软链重定位)。
- scripts/export_clusters.py 的 docstring 是同一处错误,一并修正。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Shaun Zhou
2026-10-09 16:04:01 +08:00
co-authored by Claude Opus 5
parent 29ff7a2c9b
commit 6a8941c18a
2 changed files with 22 additions and 19 deletions
+13 -10
View File
@@ -114,7 +114,7 @@ uv run python scripts/cluster_unlabeled.py --config configs/cluster/film.yaml --
簇数由配置的 `num_clusters` 决定,也可以 `--num-clusters 6` 临时覆盖(实测 4 类的换种子稳定性最高,见文档 §10.4)。产出在 `work_dir`:
`assignments.csv`(每张图的簇号与到质心的距离)、`summary.json`、
`clusters/cluster_XX/`(按簇建的软链目录,直接用看图软件翻)、
`clusters/cluster_XX/`(按簇建的硬链接目录,直接用看图软件翻)、
`cluster_XX_preview.png`(每簇最靠近质心的代表样本拼图)、
`cluster_scatter.png`(**簇分布图**,见下)。
@@ -173,9 +173,9 @@ scatter:
### 按聚类结果导出数据集
聚类产出的 `clusters/` 里是**软链**,方便人工翻看和调整——可以把图在子目录间挪动、
删掉分错的、把 `cluster_03` 改名成 `grease`。整理完之后,以这个目录为准把**真实文件**
复制出来,得到一个可以直接使用的数据集:
聚类产出的 `clusters/` 默认是**硬链接**(见上文 `link_mode`),方便人工翻看和调整——
可以把图在子目录间挪动、删掉分错的、把 `cluster_03` 改名成 `grease`。整理完之后,
以这个目录为准把图**复制**出来,得到一个与 `runs/` 彻底解耦的数据集:
```bash
uv run python scripts/export_clusters.py --work-dir runs/simclr_r101 --prefix-parent
@@ -190,14 +190,17 @@ data/simclr_r101/ # 默认取 work_dir 的名字,--out 可完全指
└── manifest.json # 每张图的原始路径与所属类别,便于追溯
```
导出的是**真实文件**(不是软链),文件名用原图的名字、去掉 `clusters/` 里的 `0125_`
排序前缀。加 `--prefix-parent` 会再拼上原父目录名(`反面纵黑点/abc.png` ->
导出的是**独立的副本**:硬链接条目虽然本身就是原图数据,但路径在 `runs/` 下、
文件名还带排序前缀,而且删改会牵连原图。文件名用原图的名字、去掉 `clusters/` 里的
`0125_` 排序前缀。加 `--prefix-parent` 会再拼上原父目录名(`反面纵黑点/abc.png` ->
`反面纵黑点_abc.png`),既保住来源信息,也化解不同目录同名文件撞车。
> **从服务器拷回来的 `clusters/` 软链全都是坏的**(指向 `/home/deep/...`),不影响使用:
> 脚本读出链接目标,按其中的 `data/` 段重新落到本机 `--source-root`(默认当前目录)上;
> 万一还找不到,再用文件名在源目录里兜底索引一次。解析不到的条目会列出来并中止,
> 确认要忽略就加 `--skip-missing`。
> **三种条目都能解析。** 硬链接(默认)条目本身就是原图,脚本按 inode 反查
> `assignments.csv` 认出它对应哪张原图,好让文件名与 `--prefix-parent` 拿到真正的来源;
> 有效软链直接 resolve;**从服务器拷回来的软链**(`link_mode: sym` 时,指向
> `/home/deep/...`)在本机全部失效,脚本读出链接目标、按其中的 `data/` 段重新落到本机
> `--source-root`(默认当前目录)上,万一还找不到再用文件名在源目录里兜底索引一次。
> 解析不到的条目会列出来并中止,确认要忽略就加 `--skip-missing`。
几个保护:同类别内重名(保持原名会互相覆盖)直接报错并提示可用 `--prefix-parent`;
目标目录非空时必须显式 `--overwrite`。
+9 -9
View File
@@ -3,9 +3,9 @@
uv run python scripts/export_clusters.py --work-dir runs/orgnized_from_r101_k40
聚类脚本产出的 `clusters/` 里是**软链**,方便人工翻看、调整——可以把图在子目录之间
挪动、删掉分错的、把 `cluster_03` 改名成 `grease`。这个脚本以整理后的目录为准,
把每张图的**真实文件**复制出来:
聚类脚本产出的 `clusters/` 默认是**硬链接**(`link_mode: hard`),方便人工翻看、调整——
可以把图在子目录之间挪动、删掉分错的、把 `cluster_03` 改名成 `grease`。这个脚本以整理后的
目录为准,把每张图**复制**成独立的副本:
```
data/orgnized_from_r101_k40/
@@ -15,14 +15,14 @@ data/orgnized_from_r101_k40/
└── manifest.json # 每张图的原始路径与所属类别,便于追溯
```
**软链失效也没关系。** 从服务器拷回来的 clusters/ 目录,软链指向的是服务器路径
(`/home/deep/ModelTrainEval/data/raw/...`),在本机全部失效。脚本会读出链接目标,
按其中的 `data/` 段重新落到本机 `--source-root` 上;万一还找不到,再用文件名在
源目录里兜底索引一次。
clusters/ 里若是**硬链接**(`link_mode: hard`,默认),条目本身就是原图;脚本按 inode
**硬链接条目本身就是原图**,只是路径在 runs/ 下、文件名带着排序前缀。脚本按 inode
反查 assignments.csv 认出它对应哪张原图,好让文件名和 `--prefix-parent` 拿到真正的来源。
**软链失效也没关系**(`link_mode: sym` 时)。从服务器拷回来的 clusters/ 目录,软链指向的
是服务器路径(`/home/deep/ModelTrainEval/data/raw/...`),在本机全部失效。脚本会读出链接
目标,按其中的 `data/` 段重新落到本机 `--source-root` 上;万一还找不到,再用文件名在
源目录里兜底索引一次。
导出的文件名用**原图的名字**,不带 clusters/ 里的 `0125_` 排序前缀。
加 `--prefix-parent` 则再拼上原父目录名(`反面纵黑点/abc.png` -> `反面纵黑点_abc.png`),
便于导出后仍能看出图片来自哪个原始目录。