door_state_v20260515 — hatch_swa stack (2 binary heads + SWA-4)
cvat2 #11 image-level tag。Schema 從 4-class softmax 改成 2 binary heads (has_open / has_close)。
unknown 在 manifest build 階段過濾。ppe-demo HatchHandler hot-swap 即可上線。
State → (has_open, has_close):
- mixed → (1, 1)
- open → (1, 0)
- closed → (0, 1)
- unknown → filtered (no rows in cvat 樣本 → no-op)
三版對照
| door_v20260511 (4-class softmax) | door_v20260515 best.pt | door_v20260515 SWA-4 |
| schema | 4-class softmax (unknown/open/closed/mixed) | 2 binary heads | 2 binary heads |
| backbone | MobileNetV3-L 224 | MobileNetV3-L 384 | MobileNetV3-L 384 |
| test accuracy | 0.8366 | — | — |
| test mAP (active heads) | — | 0.9939 | 0.9806 |
| test macro F1 | 0.5815* | 0.9607 | 0.9645 |
| ckpt schema | 4-class softmax (handler 不相容) | HatchHandler 相容 | HatchHandler 相容 |
| ckpt thresholds | none | per-attr val-best F1 | per-attr val-best F1 |
* v20260511 macro_f1 0.5815 包含 unknown=0 support 拖累;active 3 class mean F1 0.775。
Per-attr metrics (test set)
| attr | best.pt | SWA-4 |
| AP | F1 | P | R | thr | valid |
AP | F1 | P | R | thr |
| has_open | 0.9967 | 0.9742 | 0.9750 | 0.9734 | 0.733 | 1642 | 0.9984 | 0.9924 | 0.9904 | 0.9944 | 0.313 |
| has_close | 0.9911 | 0.9472 | 0.9612 | 0.9335 | 0.914 | 1642 | 0.9628 | 0.9366 | 0.9090 | 0.9660 | 0.005 |
Training history
| ep | train_loss | val_mAP | val_macroF1 | val_open_AP | val_close_AP |
| 1 | 0.5041 | 0.9555 | 0.9150 | 0.914 | 0.996 |
| 2 | 0.0813 | 0.9938 | 0.9649 | 0.988 | 1.000 |
| 3 | 0.0233 | 0.9875 | 0.9570 | 0.975 | 1.000 |
| 4 | 0.0164 | 0.9834 | 0.9547 | 0.969 | 0.998 |
| 5 | 0.0117 | 0.9920 | 0.9788 | 0.984 | 1.000 |
| 6 | 0.0055 | 0.9622 | 0.9606 | 0.927 | 0.998 |
| 7 | 0.0081 | 0.9840 | 0.9647 | 0.969 | 0.999 |
| 8 | 0.0071 | 0.9644 | 0.9614 | 0.929 | 0.999 |
| 9 | 0.0028 | 0.9926 | 0.9770 | 0.986 | 1.000 |
| 10 | 0.0056 | 0.9800 | 0.9648 | 0.962 | 0.998 |
| 11 | 0.0039 | 0.9737 | 0.9681 | 0.948 | 1.000 |
| 12 | 0.0018 | 0.9909 | 0.9742 | 0.982 | 0.999 |
| 13 | 0.0013 | 0.9927 | 0.9779 | 0.986 | 0.999 |
| 14 | 0.0021 | 0.9937 | 0.9759 | 0.988 | 1.000 |
| 15 | 0.0011 | 0.9752 | 0.9690 | 0.951 | 1.000 |
| 16 | 0.0011 | 0.9813 | 0.9687 | 0.963 | 0.999 |
| 17 | 0.0009 | 0.9863 | 0.9700 | 0.973 | 0.999 |
| 18 | 0.0007 | 0.9853 | 0.9702 | 0.971 | 0.999 |
| 19 | 0.0018 | 0.9831 | 0.9712 | 0.967 | 0.999 |
| 20 | 0.0006 | 0.9755 | 0.9684 | 0.952 | 0.999 |
Sample inference (test, 4 per state,SWA-4 + val-thr)
truth=open pred=unknown/? open=100% close=0% thr_open=1.00 thr_close=0.18

truth=open pred=unknown/? open=100% close=0% thr_open=1.00 thr_close=0.18

truth=open pred=unknown/? open=100% close=0% thr_open=1.00 thr_close=0.18

truth=open pred=unknown/? open=100% close=0% thr_open=1.00 thr_close=0.18

truth=closed pred=closed open=0% close=100% thr_open=1.00 thr_close=0.18

truth=closed pred=closed open=0% close=100% thr_open=1.00 thr_close=0.18

truth=closed pred=closed open=0% close=100% thr_open=1.00 thr_close=0.18

truth=closed pred=closed open=0% close=100% thr_open=1.00 thr_close=0.18

truth=mixed pred=closed open=100% close=100% thr_open=1.00 thr_close=0.18

truth=mixed pred=closed open=100% close=100% thr_open=1.00 thr_close=0.18

truth=mixed pred=closed open=100% close=100% thr_open=1.00 thr_close=0.18

truth=mixed pred=closed open=71% close=100% thr_open=1.00 thr_close=0.18

FP audit — top-8 最自信錯判(sampled 300)
truth=mixed → pred=closed open=100% close=100%

truth=mixed → pred=closed open=100% close=100%

truth=mixed → pred=closed open=100% close=100%

truth=mixed → pred=closed open=100% close=100%

truth=mixed → pred=closed open=100% close=100%

truth=mixed → pred=closed open=100% close=100%

truth=mixed → pred=closed open=100% close=100%

truth=mixed → pred=closed open=100% close=100%

Config
{
"version": "v20260515",
"backbone_name": "mobilenetv3_large_100.ra_in1k",
"arch": "MobileNetV3-L 2 binary heads (has_open/has_close), partial-label BCE, hatch_swa stack, SWA-4",
"params_M": 4.204594,
"feat_dim": 1280,
"attrs": [
"has_open",
"has_close"
],
"img_size": 384,
"best_val_mAP": 0.993847131190981,
"best_epoch": 2,
"epochs_run": 20,
"total_train_time_s": 495.99095845222473,
"test_metrics_best": {
"mAP": 0.993896870987621,
"macro_f1": 0.9606927842247622,
"per_attr": {
"has_open": {
"ap": 0.9967186921084682,
"f1": 0.9742143432715552,
"p": 0.975,
"r": 0.9734299516908212,
"thr": 0.73291015625,
"n": 1242,
"valid": 1642,
"tp": 1209,
"fp": 31,
"fn": 33
},
"has_close": {
"ap": 0.991075049866774,
"f1": 0.9471712251779693,
"p": 0.9612167300380228,
"r": 0.9335302806499262,
"thr": 0.9140625,
"n": 1354,
"valid": 1642,
"tp": 1264,
"fp": 51,
"fn": 90
}
}
},
"test_metrics_swa": {
"mAP": 0.9806083384001334,
"macro_f1": 0.9644968473528424,
"per_attr": {
"has_open": {
"ap": 0.9984425119276941,
"f1": 0.9923664122137404,
"p": 0.9903769045709703,
"r": 0.9943639291465378,
"thr": 0.31298828125,
"n": 1242,
"valid": 1642,
"tp": 1235,
"fp": 12,
"fn": 7
},
"has_close": {
"ap": 0.9627741648725727,
"f1": 0.9366272824919442,
"p": 0.9089645587213343,
"r": 0.96602658788774,
"thr": 0.005489349365234375,
"n": 1354,
"valid": 1642,
"tp": 1308,
"fp": 131,
"fn": 46
}
}
},
"val_metrics_swa": {
"mAP": 0.9829408931150647,
"macro_f1": 0.9705861404390816,
"per_attr": {
"has_open": {
"ap": 0.9665191589075289,
"f1": 0.9520697167755992,
"p": 0.9700332963374029,
"r": 0.9347593582887701,
"thr": 1.0,
"n": 935,
"valid": 1972,
"tp": 874,
"fp": 27,
"fn": 61
},
"has_close": {
"ap": 0.9993626273226005,
"f1": 0.9891025641025641,
"p": 0.9993523316062176,
"r": 0.9790609137055838,
"thr": 0.1759033203125,
"n": 1576,
"valid": 1972,
"tp": 1543,
"fp": 1,
"fn": 33
}
}
},
"swa_n": 4,
"swa_source_ckpts": [
"ep17.pt",
"ep18.pt",
"ep19.pt",
"ep20.pt"
],
"hyperparams": {
"batch": 64,
"epochs": 20,
"lr": 0.0003,
"wd": 0.01,
"patience": 20,
"img_size": 384,
"aug": "cam_erase",
"sampler": "weighted",
"loss": "bce",
"focal_gamma": 2.0
}
}