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):

三版對照

door_v20260511 (4-class softmax)door_v20260512 best.ptdoor_v20260512 SWA-4
schema4-class softmax (unknown/open/closed/mixed)2 binary heads2 binary heads
backboneMobileNetV3-L 224MobileNetV3-L 384MobileNetV3-L 384
test accuracy0.8366
test mAP (active heads)0.98560.9847
test macro F10.5815*0.95820.9531
ckpt schema4-class softmax (handler 不相容)HatchHandler 相容HatchHandler 相容
ckpt thresholdsnoneper-attr val-best F1per-attr val-best F1

* v20260511 macro_f1 0.5815 包含 unknown=0 support 拖累;active 3 class mean F1 0.775。

Per-attr metrics (test set)

attrbest.ptSWA-4
APF1PRthrvalid APF1PRthr
has_open0.99890.98720.98170.99270.17116400.99860.98340.99100.97580.131
has_close0.97240.92920.92780.93050.90116400.97080.92280.90950.93640.938

Training history

eptrain_lossval_mAPval_macroF1val_open_APval_close_AP
10.49270.89650.87920.7950.998
20.09940.99590.97770.9921.000
30.02190.99900.98730.9990.999
40.00960.99960.99190.9991.000
50.01130.99910.98910.9990.999
60.00540.99950.99240.9991.000
70.00480.99680.97700.9940.999
80.00420.99970.99471.0001.000
90.00730.99930.98820.9990.999
100.00460.99950.99310.9991.000
110.00270.99950.99430.9991.000
120.00310.99920.98960.9990.999
130.00120.99960.99360.9991.000
140.00170.99960.99410.9991.000
150.00140.99960.99410.9991.000
160.00120.99960.99390.9991.000
170.00050.99960.99410.9991.000
180.00100.99970.99391.0001.000
190.00050.99960.99390.9991.000
200.00070.99960.99361.0001.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
  }
}