 Shaun ZhouandClaude Opus 5
|
2a92275317
|
feat(detect): 固定 160x160 输入,只用裁剪与镜像填充,禁止缩放
产线要求送进模型的图固定为 N×N 且不许 resize——缺陷的绝对尺度是判别依据,
拉伸会把"5 像素的黑点"变成别的东西。
- engine/tiling.py:切片几何。边长 < N 镜像填充(reflect,真镜像,原图居中);
边长 >= N 按步长裁剪、末片贴边保证全覆盖。框跟着平移裁剪,露出面积低于
min_visibility 的丢弃;to_source 反向映射供推理时拼回原图。
- scripts/tile_dataset.py:整套数据集转换。有框图切出的空片会爆量
(524x959 能切 24 片),用 --max-empty-ratio 限量;原本无框的真负样本不受限。
- 训练配置 imgsz 改 160,并显式关掉 scale 与 translate——ultralytics 的默认值是
0.5 / 0.1 而不是 0,不写出来等于一直在做仿射缩放,违反约束。
尺寸正好等于 imgsz 时 letterbox 退化为空操作(r=1、dw=dh=0),核对过源码。
合成数据上验证:所有片正好 160x160、框区域与原图逐像素一致、填充是真镜像。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2026-09-23 12:27:57 +08:00 |
|
 Shaun ZhouandClaude Opus 5
|
154677032f
|
Revert "约束预测框互不重叠"(eba533a、9439cbb)
去掉强制非重叠:detect.py 不再给 DetectionValidator.postprocess 打补丁,
配置里移除 train.max_overlap 与 agnostic_nms,可视化脚本恢复为直接使用模型原始输出,
engine/detection 里的 suppress_overlaps / filter_overlapping_outputs 一并移除。
约束会把 mAP50 从 0.555 压到 0.483(precision 0.536->0.612),代价是按置信度抑制时
高分错框会压掉本可命中的低分框。需要时用 git revert 这次提交即可取回。
按类别分目录的可视化产出结构(36fff98)保留。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2026-09-18 15:34:13 +08:00 |
|
 Shaun ZhouandClaude Opus 5
|
9439cbb56a
|
feat(detect): 训练期的验证也约束预测框互不重叠
ultralytics 没有可用的开关:yolo26 是端到端模型,non_max_suppression 对它早退
(utils/nms.py 里 end2end 分支),只按置信度与 max_det 截断,传入的 iou 和 agnostic
都不参与 IoU 抑制;agnostic_nms 只作用于检测头 top-k(每个 anchor 取一个类别),
压不掉不同 anchor 产生的重叠框。
所以给 DetectionValidator.postprocess 包一层 filter_overlapping_outputs。训练期验证、
早停、best.pt 的选择都随之遵守这条约束,指标与最终推理一致。配置项 train.max_overlap
(默认 0,负数关闭),由 detect.py 摘出后自行实现,不传给 ultralytics。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2026-09-18 11:30:48 +08:00 |
|
 Shaun ZhouandClaude Opus 5
|
ad50c38f41
|
chore(detect): 配置指向人工复核后的数据集 data/film_yolo
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2026-09-17 16:45:14 +08:00 |
|
 Shaun ZhouandClaude Opus 5
|
891f930de2
|
refactor: prepare_label_studio.py 的内容改动(补上 a3e08a9 漏掉的部分)
a3e08a9 只提交了 git mv 的改名,内容修改因 git add 的路径报错没有进入暂存区。
本提交补上:
- 缺省输出 runs/<source>_label_studio/,不再写到 data/;该目录同时是 Label Studio
的 DOCUMENT_ROOT,打印的导入步骤里提醒复核期间不要删除或 --overwrite。
- 总是生成 tasks.json 与 labeling config,去掉 --label-studio 开关。
- 不再写 data.yaml:复核材料不是训练集,没有 data.yaml 就不会被误拿去训练,
原先"train 与 val 相同"的告警也随之移除(detect.py 里的同类告警保留)。
- detect.py、configs/detect/film.yaml、README 里对旧脚本的引用改为新流程。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2026-09-15 17:26:22 +08:00 |
|
xzhou
|
960f0d753a
|
fix(configs): update training epochs in film.yaml and film.yaml for classifier and YOLO models
|
2026-09-15 06:49:16 +00:00 |
|
 Shaun ZhouandClaude Opus 5
|
d6c6aca325
|
feat(detect): 默认模型换成 yolo26n
CLAUDE.md 已把"只用 convolution 模型"收窄到聚类与数据集生成阶段,检测这一步
不再受限,于是换成最新的 YOLO26:端到端(NMS-free),推理侧少一道后处理。
取最小的 n 档——数据 1.1 万张且标签是弱监督的,模型大了容易把标注噪声学进去。
同时去掉 test_config.py 里"不许用 yolo11/yolo12"的断言,它的依据已随
CLAUDE.md 的改动失效。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2026-09-11 14:34:16 +08:00 |
|
Shaun Zhou
|
0e830fe253
|
fix(config): update data YAML path from boxes_gradcam to boxes_shap
|
2026-09-11 14:29:27 +08:00 |
|
 Shaun ZhouandClaude Opus 5
|
8dc2fe6a2e
|
feat(detect): 把弱监督框数据集链接到 data/ 并接上 YOLO 训练
第五步产出的框标签按类别分目录,便于人工核对;检测训练要的是 train/val
划分——类别写在标签第一列,不靠目录名。补上两个入口:
- scripts/prepare_yolo_dataset.py:拍平类别目录、按类别分层切分、硬链接到
data/。分层是必需的,black 只有 53 张,随机切容易让小类在验证集里挂零。
无框的图默认保留(检测训练里是压低误检的负样本);拍平后的同名冲突直接
报错而不是静默覆盖。
- detect.py + configs/detect/film.yaml:包一层 ultralytics,沿用本仓库的
配置继承、设备解析与 SwanLab 可视化。
选 YOLOv8 而不是 v11/v12:CLAUDE.md 限定只用 convolution 模型,YOLO11 骨架
里有 C2PSA、YOLO12 以注意力为主,只有 v8 的 C2f + SPPF 是纯卷积。
mosaic/mixup 关掉——每张图只有一个弱监督框,拼接后小目标被缩得更小,对
blackdot/whitedot 这类只占千分之几面积的类别是净伤害。
ultralytics 的 project 必须传绝对路径,相对路径会被它再拼到全局 settings
的 runs_dir 上,产出会跑到 runs/detect/runs/detect/<name> 去。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2026-09-11 12:05:50 +08:00 |
|
 Shaun ZhouandClaude Opus 5
|
86c86b105c
|
refactor: 按实际的五步工作流裁掉无关代码
实际工作流是:simclr 训练 -> 聚类 -> 人工归类 -> 分类训练 -> GradCAM/SHAP 生成
热力图与 box。据此移除不参与其中的检测/定位链路,共 31 个文件、约 2600 行:
- 模型:defect_net、postprocess、necks/、heads/center_head
- 数据:film_defect(YOLO 读取端)、target_encoder
- 引擎:trainer、evaluator、losses
- 入口:train.py、eval.py
- 脚本:convert_annotations、split_dataset、export_onnx、profile_inference
- 配置:configs/{train,eval,model,dataset}
- utils/labels(多类/单类标签模式,仅检测分类头使用)
共享模块按实际用量瘦身:engine/metrics 只留 AverageMeter(检测指标随之移除);
datasets/yolo 只留写出侧(IMAGE_SUFFIXES 与 write_data_yaml)——第 5 步产出的
YOLO 标签是给外部检测训练用的交换格式,读取端不再需要。
裁剪过程中修掉一个真 bug:generate_boxes 的 --stage 默认 6(layer3)对 tiny_conv
这类非 nn.Sequential 骨架直接抛异常。现在自动退回骨架最终输出并警告,
另加 --stage -1 显式选择最终输出。
五步工作流已端到端实跑验证(simclr 1 轮 -> 聚类 -> 导出 -> 分类 1 轮 ->
gradcam 与 shap 两种方法各生成一遍)。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2026-09-11 10:27:20 +08:00 |
|
 Shaun ZhouandClaude Opus 5
|
33fdf396ee
|
feat: 新增缺陷分类训练与评估链路
在聚类 + 人工归类得到的数据集(data/<集>/<类别名>/*.png)上训练分类模型。
- datasets/classification.py:按目录组织的分类数据集,**逐类分层**切分 train/val
(others 只有 65 张,整体随机切很容易让它在验证集里挂零),固定种子可复现
- models/classifier.py:卷积骨架 + 分类头,与 DefectNet 共用 backbone 注册表,
因此自监督产出的 simclr_backbone.pth 可用 init_from 直接初始化;
frozen_backbone 可做线性探针
- engine/classification.py:训练循环 + 指标。主指标用 macro-F1 而非准确率——
数据从 normal 2679 张到 others 65 张差 41 倍,全预测成 normal 也有 24% 准确率;
损失按类别频率加权,避免小类被淹没;输出逐类 P/R/F1 与混淆矩阵
- classify.py:训练/评估入口,--eval-only 可单独评估并导出 eval_report.json
- configs/classify/film.yaml:预处理沿用聚类阶段的结论(拉伸 + 逐图标准化)。
抹掉亮度在这里尤其重要:有几类几乎只来自单一原始数据集,不抹掉的话模型可能
靠"认出这是哪个数据集"作弊
- 续训语义与检测/自监督一致:检查点只提供进度,超参以配置为准
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2026-09-10 14:58:41 +08:00 |
|
 Shaun ZhouandClaude Opus 5
|
33d28dcc7c
|
feat(cluster): clusters/ 默认改用硬链接,便于直接在 runs/ 下继续分子类
软链接记的是绝对路径,从服务器拷到本机后全部失效,也不便于直接在 runs/ 下整理。
硬链接不占额外磁盘却表现得和真实文件一样:看图软件能开、可以随意挪动、建子目录
继续分子类,整个目录拷到别的机器也不会断链。
- 新增 link_mode: hard(默认)/ sym / copy;跨文件系统时 hard 自动退回软链并警告
- 落盘后打印各方式的条目数,便于确认实际用的是哪种
- export_clusters.py 适配硬链接:条目本身就是原图,但路径在 runs/ 下、名字还带
0125_ 排序前缀。按 inode 反查 assignments.csv 还原原图路径,这样导出的文件名与
--prefix-parent 才能拿到真正的来源目录;查不到则剥掉前缀后用文件名索引兜底
实测:14,579 张跑聚类后 clusters/ 全为硬链接(nlink=2、可直接打开);
把簇改名、建子目录挪图后再导出,排序前缀已剥除、来源目录正确还原为「反面纵黑点」,
120 张内容与原图逐字节一致。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2026-09-10 12:04:08 +08:00 |
|
 Shaun ZhouandClaude Opus 5
|
6e543660ce
|
feat(configs): 新增 resnet101 的自监督聚类配置
resnet101 此前不在 TorchvisionBackbone 的支持列表里,先补进 _SUPPORTED
(out_channels 2048),随后被既有的参数化测试自动覆盖:能前向、声明维度与实际一致。
configs/cluster/film_simclr_resnet101.yaml 仿照 resnet18/50 两份,只改骨架与
batch_size,其余超参一致以便横向对比:
- 42.5M 参数(resnet18 11.2M / resnet50 23.5M),layer2+3 仍是 1536 维,
与 resnet50 相同,差别在深度(layer3 有 23 个 block 而非 6 个)
- batch_size 取 128:MPS 上 resnet50 在 1024 已 OOM,resnet101 约重 1.8 倍故再降一档;
注释里说明该数字来自 MPS,16 GB 独显上可往上调
- pretrained 首次使用会下载约 171 MB 权重
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2026-09-07 20:51:16 +08:00 |
|
xzhou
|
c9e7e4104c
|
fix(configs): update dataset root path in film.yaml
|
2026-09-07 12:36:51 +00:00 |
|
 Shaun ZhouandClaude Opus 5
|
92c88b785c
|
fix(config): --set 拦下不存在的键,并支持续训时重开学习率曲线
用户反馈"聚类配置里改不了 lr/weight_decay",实测是两件事:
1. --set 的键打错字母会凭空造出一个谁也不读的键,训练照跑但改动无效。
实例:simclr.optmizer.weight_decay=0.0(optimizer 少个 i)被静默接受。
现在 apply_overrides 默认只允许覆盖已存在的键,报错时给出同级可用键
与最接近的拼写("是不是想写 'optimizer'?")。需要新增键时可 strict=False。
2. lr 其实生效了,但从 2229/2500 续训时 cosine 只剩满值的 3%,
新设的 1e-3 落到 2.87e-5。新增 restart_schedule 开关:按剩余轮数重开曲线,
新 lr 从满值开始;SimCLR 与检测训练都支持。续训日志补上调度进度,
并在 lr 不足 initial_lr 的 10% 时警告并给出两种解法。
顺带:严格校验立刻暴露出 configs/cluster/film.yaml 里根本没有 scatter 段
(代码 cfg.get("scatter", {}) 兜底走默认值,所以功能正常但配置项形同虚设),已补上。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2026-09-07 19:30:17 +08:00 |
|
xzhou
|
01cfff9b02
|
fix(configs): update optimizer settings and add projection parameters in film_simclr_resnet50.yaml
|
2026-09-07 06:25:54 +00:00 |
|
 Shaun ZhouandClaude Opus 5
|
5d395b7c25
|
chore: 数据迁到 data/raw/ 后同步所有路径引用
原始数据从 data/<数据集> 移到了 data/raw/<数据集>。
- 聚类配置的 dataset.root:film / pearlescent 均改为 data/raw/ 下
- 检测配置的 img_dir 与 label_dir 注释同步
- README、data/README、算法文档、流程图(含重新渲染的 PNG)与各脚本
docstring 里的路径示例一并更新
- data/README 补充目录约定:原始数据只读放 data/raw/,
export_clusters.py 的派生数据集放在 data/ 下与 raw/ 平级
- 顺手把 unlabeled 数据集加进 datasets/__init__.py:此前它没在包初始化时注册,
build_dataset({"name": "unlabeled"}) 只有在别处先 import 过该模块时才可用
迁移后重跑全量聚类,结果与迁移前逐项一致(轮廓 0.3255、稳定性 0.9641、
簇大小 [4507, 3795, 4849, 1428])。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2026-09-07 11:19:42 +08:00 |
|
 Shaun ZhouandClaude Opus 5
|
5f31ed0a92
|
feat(configs): 新增 resnet50 的自监督聚类配置
仿照 film_simclr_resnet18.yaml,只改骨架与 batch_size,其余超参保持一致以便对比。
batch_size 取 256 而非照抄 resnet18 的 1024:实测 resnet50 在 Apple MPS 上
batch 1024 直接 OOM(需 18.7 GiB),batch 128 时 604 MB。每 epoch 耗时与 batch
基本无关(约 155 秒,算力受限),所以调小 batch 不花额外时间,只是负样本变少。
配置注释里记下了实测数据与降级路径(显存不够继续调到 128 / 64),
并说明 resnet50 的 layer2+3 是 1536 维(resnet18 为 384 维)。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2026-09-07 11:07:55 +08:00 |
|
xzhou
|
7f13ec5d18
|
fix(configs): update training epochs and optimizer settings in film_simclr_resnet18.yaml
|
2026-09-06 05:05:47 +00:00 |
|
xzhou
|
703ba7076b
|
fix(configs): update num_clusters and training parameters in film_simclr_resnet18.yaml
|
2026-09-04 13:41:41 +00:00 |
|
xzhou
|
6b11128357
|
fix(configs): update film_simclr_resnet18.yaml with new clustering parameters and optimizer settings
|
2026-09-04 09:19:15 +00:00 |
|
 Shaun ZhouandClaude Opus 5
|
6f00074199
|
feat(cluster): 新增 resnet18 自监督聚类配置,并修复 --set 的 YAML 标量解析
- 新增 configs/cluster/film_simclr_resnet18.yaml:用 resnet18 做域内自监督后聚类。
backbone 块带 _replace_,避免 base 里 tiny_conv 的 widths/depths 残留
- parse_override 此前只用 ast.literal_eval,不认 YAML 风格的 null/true/false:
`--set xxx.enabled=false` 会得到字符串 "false",而非空字符串是真值,开关反被打开。
改为先试 Python 字面量(保住 1e-3 这类),再退回 YAML 标量解析
- feature_stages 默认由 null 改为 [5, 6]:实测 1 epoch 自监督后 layer2+3 的轮廓
0.243/稳定性 0.997,明显优于 layer4 的 0.156/0.528。原注释里"自监督后 layer4
已是域内特征"的推断被数据推翻
- README 补充三种方案的实测对比与成本
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2026-09-04 15:51:28 +08:00 |
|
 Shaun ZhouandClaude Opus 5
|
47fb0f1125
|
fix(configs): 修复 resnet18 训练配置无法构建,并补上对应的评估配置
- configs/train/resnet18.yaml 此前直接报错:它同时继承 tiny_conv 与 resnet18 的模型
配置,深度合并后 backbone 混了两边字段。在 configs/model/resnet18.yaml 的 backbone
上加 _replace_: true 整块替换
- _replace_ 标记此前不生效:_load_raw 对每个 base 都会先 deep_merge({}, data),
标记在参与替换判断之前就被剥掉了。改为合并期间保留、load_config 末尾统一剥除
- 新增 configs/eval/resnet18.yaml:评估必须与训练用同一套模型配置,否则构建出的
骨架与权重对不上,而此前只有 baseline 一个评估配置
- 新增参数化测试:仓库里每个配置都要能真的构建出组件(片段自动跳过),
且训练/评估配置对的 model 段必须一致
- README 补充骨架与配置对的对应表
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2026-09-04 15:42:14 +08:00 |
|
xzhou
|
4e6c8aa2ea
|
fix: update work directory in film.yaml and add pearlescent.yaml configuration
|
2026-09-04 06:54:06 +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
|
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
|
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
|
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 |
|