door_state_v20260512 — 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_v20260512 best.pt | door_v20260512 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.9856 | 0.9847 |
| test macro F1 | 0.5815* | 0.9582 | 0.9531 |
| 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.9989 | 0.9872 | 0.9817 | 0.9927 | 0.171 | 1640 | 0.9986 | 0.9834 | 0.9910 | 0.9758 | 0.131 |
| has_close | 0.9724 | 0.9292 | 0.9278 | 0.9305 | 0.901 | 1640 | 0.9708 | 0.9228 | 0.9095 | 0.9364 | 0.938 |
Training history
| ep | train_loss | val_mAP | val_macroF1 | val_open_AP | val_close_AP |
| 1 | 0.4927 | 0.8965 | 0.8792 | 0.795 | 0.998 |
| 2 | 0.0994 | 0.9959 | 0.9777 | 0.992 | 1.000 |
| 3 | 0.0219 | 0.9990 | 0.9873 | 0.999 | 0.999 |
| 4 | 0.0096 | 0.9996 | 0.9919 | 0.999 | 1.000 |
| 5 | 0.0113 | 0.9991 | 0.9891 | 0.999 | 0.999 |
| 6 | 0.0054 | 0.9995 | 0.9924 | 0.999 | 1.000 |
| 7 | 0.0048 | 0.9968 | 0.9770 | 0.994 | 0.999 |
| 8 | 0.0042 | 0.9997 | 0.9947 | 1.000 | 1.000 |
| 9 | 0.0073 | 0.9993 | 0.9882 | 0.999 | 0.999 |
| 10 | 0.0046 | 0.9995 | 0.9931 | 0.999 | 1.000 |
| 11 | 0.0027 | 0.9995 | 0.9943 | 0.999 | 1.000 |
| 12 | 0.0031 | 0.9992 | 0.9896 | 0.999 | 0.999 |
| 13 | 0.0012 | 0.9996 | 0.9936 | 0.999 | 1.000 |
| 14 | 0.0017 | 0.9996 | 0.9941 | 0.999 | 1.000 |
| 15 | 0.0014 | 0.9996 | 0.9941 | 0.999 | 1.000 |
| 16 | 0.0012 | 0.9996 | 0.9939 | 0.999 | 1.000 |
| 17 | 0.0005 | 0.9996 | 0.9941 | 0.999 | 1.000 |
| 18 | 0.0010 | 0.9997 | 0.9939 | 1.000 | 1.000 |
| 19 | 0.0005 | 0.9996 | 0.9939 | 0.999 | 1.000 |
| 20 | 0.0007 | 0.9996 | 0.9936 | 1.000 | 1.000 |
Sample inference (test, 4 per state,SWA-4 + val-thr)
truth=open pred=closed open=0% close=100% thr_open=0.31 thr_close=0.00

truth=open pred=mixed open=100% close=4% thr_open=0.31 thr_close=0.00

truth=open pred=closed open=6% close=96% thr_open=0.31 thr_close=0.00

truth=open pred=mixed open=91% close=66% thr_open=0.31 thr_close=0.00

truth=closed pred=closed open=0% close=100% thr_open=0.31 thr_close=0.00

truth=closed pred=closed open=1% close=100% thr_open=0.31 thr_close=0.00

truth=closed pred=closed open=1% close=100% thr_open=0.31 thr_close=0.00

truth=closed pred=closed open=0% close=100% thr_open=0.31 thr_close=0.00

truth=mixed pred=mixed open=100% close=100% thr_open=0.31 thr_close=0.00

truth=mixed pred=mixed open=100% close=100% thr_open=0.31 thr_close=0.00

truth=mixed pred=mixed open=100% close=100% thr_open=0.31 thr_close=0.00

truth=mixed pred=mixed open=54% close=100% thr_open=0.31 thr_close=0.00

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

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

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

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

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

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

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

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

Config
{
"version": "v20260512",
"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.9997028823059231,
"best_epoch": 8,
"epochs_run": 20,
"total_train_time_s": 410.6830735206604,
"test_metrics_best": {
"mAP": 0.9856405542241217,
"macro_f1": 0.9581653893462012,
"per_attr": {
"has_open": {
"ap": 0.998907064547578,
"f1": 0.9871794871794872,
"p": 0.9816733067729083,
"r": 0.9927477840451249,
"thr": 0.170654296875,
"n": 1241,
"valid": 1640,
"tp": 1232,
"fp": 23,
"fn": 9
},
"has_close": {
"ap": 0.9723740439006653,
"f1": 0.9291512915129151,
"p": 0.9277818717759764,
"r": 0.9305247597930525,
"thr": 0.90087890625,
"n": 1353,
"valid": 1640,
"tp": 1259,
"fp": 98,
"fn": 94
}
}
},
"test_metrics_swa": {
"mAP": 0.9847311700948495,
"macro_f1": 0.9530752145593088,
"per_attr": {
"has_open": {
"ap": 0.9986153377948864,
"f1": 0.9833536337799431,
"p": 0.9909983633387889,
"r": 0.975825946817083,
"thr": 0.1312255859375,
"n": 1241,
"valid": 1640,
"tp": 1211,
"fp": 11,
"fn": 30
},
"has_close": {
"ap": 0.9708470023948125,
"f1": 0.9227967953386744,
"p": 0.9095477386934674,
"r": 0.9364375461936437,
"thr": 0.9384765625,
"n": 1353,
"valid": 1640,
"tp": 1267,
"fp": 126,
"fn": 86
}
}
},
"val_metrics_swa": {
"mAP": 0.9996298223047773,
"macro_f1": 0.9938514344668863,
"per_attr": {
"has_open": {
"ap": 0.9995107452750263,
"f1": 0.9952978056426333,
"p": 0.9984276729559748,
"r": 0.9921875,
"thr": 0.314208984375,
"n": 640,
"valid": 1091,
"tp": 635,
"fp": 1,
"fn": 5
},
"has_close": {
"ap": 0.9997488993345282,
"f1": 0.9924050632911392,
"p": 0.9949238578680203,
"r": 0.98989898989899,
"thr": 0.003780364990234375,
"n": 990,
"valid": 1091,
"tp": 980,
"fp": 5,
"fn": 10
}
}
},
"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
}
}