Upload docs/config_parity.md
Browse files- docs/config_parity.md +106 -0
docs/config_parity.md
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Config Parity:官方 mmrotate config ↔ Jittor config 逐项对照
|
| 2 |
+
|
| 3 |
+
> 真相来源:`/root/ref/Point2RBox-v3/configs/point2rbox_v2/*.py`(解析展平后的 golden
|
| 4 |
+
> 在 `tests/parity/golden/config_*.json`,由 `tools/dump_config.py` 生成)。
|
| 5 |
+
> 可执行版对照:`tests/parity/test_L0_config.py::TestJittorConfigParity`(10 tests)。
|
| 6 |
+
> 本文只记录**映射规则**与**疑似异常清单**,数值一律以 golden 为准。
|
| 7 |
+
|
| 8 |
+
## 类名 / 写法映射表(铁律一允许变的三类)
|
| 9 |
+
|
| 10 |
+
| 官方(mmrotate/mmdet/mmengine) | Jittor(JDet) | 说明 |
|
| 11 |
+
|---|---|---|
|
| 12 |
+
| `mmdet.ResNet, out_indices=(1,2,3)` | `Resnet50, return_stages=['layer2','layer3','layer4']` | 数值语义相同 |
|
| 13 |
+
| `init_cfg=Pretrained(torchvision://resnet50)` | `pretrained=True` | 同一份 torchvision 权重 |
|
| 14 |
+
| `mmdet.FPN` | `FPN` | 参数逐值相同 |
|
| 15 |
+
| `mmdet.FocalLoss` | `FocalLoss` | |
|
| 16 |
+
| `GWDLoss`(v3 注册名)/`GDLoss(gwd)` | `GDLoss(loss_type='gwd')` | |
|
| 17 |
+
| `optim_wrapper.optimizer=AdamW(...)` + `clip_grad` | `optimizer=AdamW(..., grad_clip=...)` | clip 数值不变 |
|
| 18 |
+
| `param_scheduler=[LinearLR, MultiStepLR]` | `scheduler=LinearWarmupMultiStepLR` | LR 序列逐点相等(L1 测试 1440 点 rtol 1e-9) |
|
| 19 |
+
| `custom_hooks=[mmdet.SetEpochInfoHook]` | Runner 内建 `model.set_epoch(epoch)` | C3 |
|
| 20 |
+
| `train_cfg=EpochBasedTrainLoop(max_epochs=12, val_interval=12)` | `max_epoch=12, eval_interval=12` | |
|
| 21 |
+
| `default_hooks.logger interval=50 / checkpoint interval=1` | `log_interval=50 / checkpoint_interval=1` | |
|
| 22 |
+
| pipeline `LoadImageFromFile→LoadAnnotations(qbox)→ConvertBoxType→ConvertWeakSupervision` | `P2RV2DOTADataset`(内建,直读 split txt) | qbox→rbox 用 cv2.minAreaRect 原样;point_dummy=1 官方默认 |
|
| 23 |
+
| pipeline `Resize((1024,1024), keep_ratio=True)` | `MMRotateResize(min_size=1024, max_size=1024)` | 不复用底座 RotatedResize(会重规范角度) |
|
| 24 |
+
| pipeline `RandomFlip(0.75, [h,v,diag])` | `MMRotateRandomFlip(同参数)` | 不复用底座 RotatedRandomFlip(-1 偏移+角度公式不同) |
|
| 25 |
+
| `data_preprocessor(mean/std/bgr_to_rgb/pad_size_divisor)` | transforms 的 `Normalize`+`Pad(32)`;mean/std 同时传 model 供 TED 反归一化 | |
|
| 26 |
+
|
| 27 |
+
## 疑似异常但已确认照抄(铁律二,勿"修正")
|
| 28 |
+
|
| 29 |
+
| # | 项 | 已照抄的值 | 状态 |
|
| 30 |
+
|---|---|---|---|
|
| 31 |
+
| 1 | `_delete_=True` 后 clip_grad 仍生效 | `grad_clip(max_norm=35, norm_type=2)` | ✅ C1 + L0 锚定测试 |
|
| 32 |
+
| 2 | param_scheduler 未被覆盖 | LinearLR(1/3, iter 0→500) × MultiStepLR([8,11], 0.1) | ✅ C2,LR 逐点相等 |
|
| 33 |
+
| 3 | SetEpochInfoHook 是功能性依赖 | runner 每 epoch 注入 | ✅ C3 |
|
| 34 |
+
| 4 | val 指向 trainval/ | 照抄 | ✅ config + L0 测试断言 |
|
| 35 |
+
| 5 | stage-2 wd=0.005(≠端到端 0.05) | 照抄 | ✅ golden 锚定(stage-2 config M7 时写) |
|
| 36 |
+
| 6 | head strides=[8] 单层 | 照抄 | ✅ |
|
| 37 |
+
| 7 | backbone out_indices v2=(1,2,3) / stage-2=(0,1,2,3) | 各是各的 | ✅ |
|
| 38 |
+
| 8 | square_cls/edge_loss_cls/post_process/voronoi_thres 逐类魔数 | 一个数不动 | ✅ L0 锚定 |
|
| 39 |
+
| 9 | ss_prob=[0.68,0.07,0.25] | 照抄 | ✅ |
|
| 40 |
+
| 10 | RandomFlip prob=0.75 | 照抄 | ✅ |
|
| 41 |
+
| 11 | boxtype2tensor=False / relu_before_extra_convs=True / add_extra_convs='on_output' / filter_empty_gt=True | 全部显式 | ✅ |
|
| 42 |
+
| 12 | `label_assign_pseudo_label_switch_eopch` 拼写 | v3 用,v2 未涉及;若移植中遇到保持原拼写 | 备案 |
|
| 43 |
+
|
| 44 |
+
## 已知实现层差异(非 config 数值,均有记录与理由)
|
| 45 |
+
|
| 46 |
+
| 项 | 差异 | 影响 |
|
| 47 |
+
|---|---|---|
|
| 48 |
+
| torchvision `resized_crop` 的 antialias | jt.nn.interpolate 无 antialias | 仅 sca 增广路径图像内容,训练随机性范围内 |
|
| 49 |
+
| mmcv RoIAlignRotated aligned=True 不做 1x1 钳制 | JDet kernel 始终钳制 | 仅亚像素 roi |
|
| 50 |
+
| jdet nms keep 顺序 | head 内先按分数排序再 NMS,语义对齐 mmcv | 已适配 |
|
| 51 |
+
| reduce_mean(分布式均值) | 单卡训练恒等 | 官方总 batch=2 单卡,无差异 |
|
| 52 |
+
| eigh 简并子梯度基底 | w==h 时与 torch 的 a/c 分配不同(trace 一致) | 数学等价的子梯度选择 |
|
| 53 |
+
|
| 54 |
+
---
|
| 55 |
+
|
| 56 |
+
# v3 专项附录(Agent B:SAM 配置与 utils 怪癖)
|
| 57 |
+
|
| 58 |
+
# Config Parity — 官方 config ↔ Jittor config 对照
|
| 59 |
+
|
| 60 |
+
> 状态:开档(2026-07-26)。M5' 写 v3 config 时逐项补全对照表与类名映射表。
|
| 61 |
+
> L0 测试:A 的 `tools/dump_config.py` golden + `tests/parity/`,v3 侧比对在 M5' 接入。
|
| 62 |
+
|
| 63 |
+
## 疑似异常但已确认照抄(只记录,禁止"修正")
|
| 64 |
+
|
| 65 |
+
### 来自计划铁律二(写 config 时逐条勾选,见 PLAN §6)
|
| 66 |
+
|
| 67 |
+
12 条清单在 M5' 写 config 时逐条核对后搬进本表。先行确认的:
|
| 68 |
+
|
| 69 |
+
| # | 项 | 实测情况 | 处置 |
|
| 70 |
+
|---|---|---|---|
|
| 71 |
+
| 铁律二 #7 | class 1/0/14 weights 含 color_consistency 但 required_metrics 未列 | **实测只有 class 1 不对称**(0/14 两边都列了);计划描述有偏差,行为照抄不受影响 | `_base_sam-dotav1-0.py` 已逐字节 cp(md5=772f1e23…) |
|
| 72 |
+
| 铁律二 #8 | class 3/8/10 的 circularity 权重 = -3 + penalty_circularity=100 | 已数值验证:圆形 mask 在这三类被压掉、斜矩形胜出(tests/test_filter_masks.py) | 照抄 ✓ |
|
| 73 |
+
|
| 74 |
+
### 代码层怪癖(losses/utils.py 移植时发现,均已 1e-6 parity 验证照抄)
|
| 75 |
+
|
| 76 |
+
1. **`filter_masks` 内置 fallback config 与 `_base_sam-dotav1-0.py` 数值不同**:
|
| 77 |
+
fallback 的 default color_consistency 权重 6(配置文件是 2);fallback 的 class 11 多
|
| 78 |
+
`rectangularity: -2`、class 0/14 多 `rectangularity: -1`;aspect_ratio_range 普遍不同
|
| 79 |
+
(class 7:fallback (1.3,3) vs 配置 (1,5))。训练时 config 恒传入,fallback 仅
|
| 80 |
+
config=None 时生效。**两套都照抄,不合并、不统一。**
|
| 81 |
+
2. `circularity` 的 `radius=int(radius)` 截断 + `countNonZero` 栅格化圆面积(非解析
|
| 82 |
+
πr²)——量化行为,照抄。
|
| 83 |
+
3. fallback 里 class 2 的 required_metrics 列了 aspect_ratio_reasonableness 但没配
|
| 84 |
+
aspect_ratio_range → 该 metric 实际永不计算(weights 也没它,无实际影响)。照抄。
|
| 85 |
+
4. `center_alignment` 在 prompt 点落在 mask 外时返回硬惩罚 -100.0(×权重 10 = -1000),
|
| 86 |
+
刻意设计,照抄。
|
| 87 |
+
|
| 88 |
+
## 偏离项记录(config 语法层,非数值)
|
| 89 |
+
|
| 90 |
+
- (待 M5' 填写:registry 类名映射、JDet config 语法差异等允许项)
|
| 91 |
+
|
| 92 |
+
## 追加豁免(2026-07-26 14:35)
|
| 93 |
+
|
| 94 |
+
| 项 | 官方值 | Jittor 侧 | 理由 |
|
| 95 |
+
|---|---|---|---|
|
| 96 |
+
| `train/val/test_dataloader.num_workers` | 2 | 0 | jittor 1.3.8.5 多进程 dataset 环形缓冲死锁(A commit 3d87c60 实测)。纯 infra 参数,不影响样本组成/顺序/任何训练数学。jittor 修复后可恢复 |
|
| 97 |
+
|
| 98 |
+
## 上游可复现性发现(2026-07-26,loss_by_feat parity 期间)
|
| 99 |
+
|
| 100 |
+
**上游 v3 训练的 MobileSAM 实际使用了未播种的随机 attention bias。**
|
| 101 |
+
`mobile_sam` 包 `build_sam` 先 `eval()` 后 `load_state_dict`:TinyViT Attention 在 eval()
|
| 102 |
+
时缓存非持久的 `ab`(attention bias 索引结果),随后 load_state_dict 不刷新它——
|
| 103 |
+
上游每次训练运行的 SAM attention bias 都是随机初始化残留,逐次不同、不可复现。
|
| 104 |
+
本仓库 Jittor 移植是「加载后自然刷新」的正确语义(golden 采用修正语义后 SAM E2E 逐位一致)。
|
| 105 |
+
**含义**:我们的 SAM 是正确权重版;与上游 61.38 的 mAP 对比中该差异方向未知(推测中性或
|
| 106 |
+
偏正面),若最终精度有出入这是候选解释之一。详见 tools/dump_v3_head_loss_reference.py 注释。
|