koreashin commited on
Commit
966f1f2
·
verified ·
1 Parent(s): 2c784e0

v5b: train/val split + early stopping (OOD AUC 0.987)

Browse files
Files changed (3) hide show
  1. README.md +73 -36
  2. stage5_full.pt +2 -2
  3. stage6_vitalguard.pt +1 -1
README.md CHANGED
@@ -7,20 +7,22 @@ tags:
7
  - elderly-monitoring
8
  - imu
9
  - heart-rate
 
10
  license: mit
11
  ---
12
 
13
- # SISA-RoutineGuard
14
 
15
  **노인 일상 패턴 이상 감지 시스템** (Galaxy Watch + Jetson Orin Nano)
16
 
17
- 4-tier hierarchical SSM-Informed Softmax Attention 모델로 노인의 24시간 wearable 데이터에서 routine anomaly를 감지합니다.
 
18
 
19
- ## 모델 구성
20
 
21
- | Component | Params | 위치 |
22
- |---|---|---|
23
- | PatchEncoder | 0.22M | Phone (ONNX) |
24
  | MinuteEncoder | 48.09M | Jetson |
25
  | FeatureAdapter | 0.66M | Jetson |
26
  | HourSlotEncoder | 142.60M | Jetson |
@@ -28,34 +30,36 @@ license: mit
28
  | QueryRefiner | 97.65M | Jetson |
29
  | VitalGuard | 12.01M | Jetson |
30
  | OutputHeads | 1.58M | Jetson |
31
- | **Full model** | **444.66M** | Total |
32
 
33
- ## 학습 데이터
34
- - **CAPTURE-24** (Oxford, 151 subjects × 24h wrist accelerometer)
35
- - **ArWISE V3** (CASAS, 10 subjects × 9 days, 76 days raw)
36
- - **PPG-DaLiA** (UCI, 15 subjects)
37
- - **WESAD** (Schmidt 2018, 15 subjects)
38
- - **MHEALTH** (UCI, 10 subjects)
39
 
40
- ## 학습 단계 (Plan v1.4)
 
 
 
 
 
 
 
41
 
42
- 1. **Stage 1 — PatchEncoder**: reconstruction MSE on CAPTURE-24 + ArWISE V3 raw acc
43
- 2. **Stage 2 — MinuteEncoder + FeatureAdapter**: alignment + InfoNCE on real CAPTURE-24
44
- 3. **Stage 3 — HourSlotEncoder**: slot context + cross-day contrastive (real ArWISE features)
45
- 4. **Stage 4 — HistoryEncoder + QueryRefiner**: day order + neighbor slot alignment
46
- 5. **Stage 5 — Full model**: synthetic anomaly injection on real distribution
47
- 6. **Stage 6 — VitalGuard**: HR regression on PPG-DaLiA + WESAD + MHEALTH
48
 
49
- ## Files
 
 
 
50
 
51
- - `stage1_patch.pt` — PatchEncoder weights (Phone deploy)
52
- - `stage2_minute.pt`, `stage2_adapter.pt` — MinuteEncoder + Adapter
53
- - `stage3_hourslot.pt` HourSlotEncoder
54
- - `stage4_history.pt`, `stage4_refiner.pt` — History + QueryRefiner
55
- - `stage5_full.pt` Full model fine-tuned with anomaly injection
56
- - `stage6_vitalguard.pt` VitalGuard module
57
- - `patch_encoder.onnx` Phone deploy ONNX (880KB)
58
- - `normalizer.pkl` Feature normalizer
 
 
59
 
60
  ## Inference
61
 
@@ -66,15 +70,48 @@ from src.models.full_model import SISARoutineGuard
66
  model = SISARoutineGuard().cuda().eval()
67
  state = torch.load("stage5_full.pt", map_location="cpu")["model"]
68
  model.load_state_dict(state, strict=False)
69
-
70
- # Merge Stage 6 VitalGuard
71
  vg = torch.load("stage6_vitalguard.pt", map_location="cpu")["model"]
72
  model.vitalguard.load_state_dict(vg, strict=False)
 
 
 
 
 
 
73
  ```
74
 
75
- 코드: https://github.com/tlstngud/sisa-routineguard (private)
 
 
 
 
 
76
 
77
- ## 평가
78
- - forward_replay inference: **448 ms / batch=2** (RTX 4090)
79
- - pytest 57/69 통과
80
- - 9 시나리오 normal/shift 시연 검증
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  - elderly-monitoring
8
  - imu
9
  - heart-rate
10
+ - edge-deployment
11
  license: mit
12
  ---
13
 
14
+ # SISA-RoutineGuard v5b
15
 
16
  **노인 일상 패턴 이상 감지 시스템** (Galaxy Watch + Jetson Orin Nano)
17
 
18
+ 4-tier hierarchical anomaly detector with **SISA backbone** (SSM-Informed Softmax Attention).
19
+ Train/val split + early stopping 적용한 production ckpt.
20
 
21
+ ## 모델 사이즈 — **444.66M params** (목표 250-370M 초과)
22
 
23
+ | Component | Params | Deploy |
24
+ |---|---:|---|
25
+ | PatchEncoder | 0.22M | **Phone (ONNX)** |
26
  | MinuteEncoder | 48.09M | Jetson |
27
  | FeatureAdapter | 0.66M | Jetson |
28
  | HourSlotEncoder | 142.60M | Jetson |
 
30
  | QueryRefiner | 97.65M | Jetson |
31
  | VitalGuard | 12.01M | Jetson |
32
  | OutputHeads | 1.58M | Jetson |
33
+ | **Total** | **444.66M** | |
34
 
35
+ ## 성능 (OOD: HAR-70+ 노인 70-95세, 학습 X)
 
 
 
 
 
36
 
37
+ | 시나리오 | Mean | AUC | Reason acc |
38
+ |---|---:|---:|---:|
39
+ | Normal | 0.0004 | — | — |
40
+ | walk_missing | 0.9995 | **1.000** | 0% |
41
+ | prolonged_inactivity | 0.9987 | **1.000** | 5% |
42
+ | routine_time_shift | 0.9995 | **1.000** | **100%** ✓ |
43
+ | activity_drop | 0.7145 | 0.950 | 28% |
44
+ | **Overall** | — | **0.987** | — |
45
 
46
+ ## Train/Val Split + Early Stopping
 
 
 
 
 
47
 
48
+ - Train/Val: 80/20 split (seed=42)
49
+ - Train samples: 3,277 / Val: 819
50
+ - **Best epoch = 1, val_loss = 0.2814** (saved)
51
+ - Early stop at epoch 13 (patience=10)
52
 
53
+ ## 학습 데이터
54
+
55
+ | Dataset | Subjects | Duration | Stage |
56
+ |---|---:|---|---|
57
+ | CAPTURE-24 | 151명 | 24h wrist 100Hz | 1, 2 |
58
+ | ArWISE V3 | 10명 | 9일, 76일 raw | 1, 3, 4, 5 |
59
+ | PPG-DaLiA | 15명 | 2.5h wrist | 6 |
60
+ | WESAD | 15명 | 1.7h wrist+chest | 6 |
61
+ | MHEALTH | 10명 | 53m 23ch | 6 |
62
+ | **HAR-70+** | **18명 70-95세** | **테스트만 (OOD)** | — |
63
 
64
  ## Inference
65
 
 
70
  model = SISARoutineGuard().cuda().eval()
71
  state = torch.load("stage5_full.pt", map_location="cpu")["model"]
72
  model.load_state_dict(state, strict=False)
 
 
73
  vg = torch.load("stage6_vitalguard.pt", map_location="cpu")["model"]
74
  model.vitalguard.load_state_dict(vg, strict=False)
75
+
76
+ # forward_replay (90 history × 60 min + 3 today × 60 min)
77
+ out = model.forward_replay(history_features_norm, today_features_norm,
78
+ day_offset, slot_pos, day_type,
79
+ history_mask, today_mask)
80
+ # 448 ms / batch=2 on RTX 4090
81
  ```
82
 
83
+ ## ONNX (Phone deploy)
84
+ ```python
85
+ import onnxruntime as ort
86
+ sess = ort.InferenceSession("patch_encoder.onnx", providers=["CPUExecutionProvider"])
87
+ out = sess.run(None, {"acc": acc_array}) # [6, 250, 3] → [6, 256]
88
+ ```
89
 
90
+ ## Files
91
+ | File | Size | Stage |
92
+ |---|---:|---|
93
+ | stage1_patch.pt | 879 KB | 1 |
94
+ | stage2_minute.pt | 192 MB | 2 |
95
+ | stage2_adapter.pt | 2.7 MB | 2 |
96
+ | stage3_hourslot.pt | 570 MB | 3 |
97
+ | stage4_history.pt | 567 MB | 4 |
98
+ | stage4_refiner.pt | 390 MB | 4 |
99
+ | **stage5_full.pt** | **1.78 GB** | **5 (val-split best)** |
100
+ | stage6_vitalguard.pt | 48 MB | 6 |
101
+ | patch_encoder.onnx | 880 KB | Phone |
102
+ | normalizer.pkl | 405 B | Feature normalizer |
103
+
104
+ ## 한계
105
+
106
+ 1. 합성 anomaly만 학습 — 진짜 노인 이상 (낙상, 치매) 미검증
107
+ 2. Reason multi-class 1~2개만 정확 (routine_time_shift 100%, 나머지 28% 이하)
108
+ 3. VitalGuard ground-truth HR 평가 미실시
109
+
110
+ ## 코드
111
+ https://github.com/tlstngud/sisa-routineguard (private)
112
+ - PRESENTATION.md 상세 발표 자료 포함
113
+
114
+ ## Reference
115
+ - Plan v1.4 (강원대 SUNRISE 연구실 캡스톤)
116
+ - CAPTURE-24: Walmsley 2021 (DOI 10.5287/bodleian:NGx0JOMP5)
117
+ - ArWISE V3: CASAS / Diane Cook (Zenodo 15803341)
stage5_full.pt CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:f22774a6633ec1a2d0ab21964160252000dc77cc3b5732806dbbae31ab1cf99b
3
- size 1779230774
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:f7d67630c8ee0e9991e39b4bd197d57b0c8fc458d776c1d418ca6c0ada1141a8
3
+ size 1779230838
stage6_vitalguard.pt CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:c84cbf1ab835ef10f72a8524a990debaf7233dab27750e22888dcd6406a2f2b6
3
  size 48077842
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:1ec37c9faed7e15d48376099f32ae5df39b2469a66ab0edc66677e814a446251
3
  size 48077842