sisa-routineguard / README.md
koreashin's picture
Add ONNX exports (7 stages, 1.4GB) for Jetson Nano inference
a1f45db verified
---
language: ko
library_name: pytorch
tags:
- anomaly-detection
- wearable-sensors
- elderly-monitoring
- imu
- heart-rate
- edge-deployment
- onnx
- jetson-nano
license: mit
---
# SISA-RoutineGuard v5b — ONNX Edition
**노인 일상 패턴 이상 감지** (Galaxy Watch + Jetson Orin Nano Super)
**ONNX exports** for fast Jetson inference (TensorRT compatible).
## 📦 ONNX Models (Jetson deploy)
| File | Size | Stage | Input | Output |
|---|---:|---|---|---|
| **patch_encoder.onnx** | 0.9 MB | 1 (Phone) | acc [6, 250, 3] | tokens [6, 256] |
| **minute_encoder.onnx** | 192.5 MB | 2 | patch_tokens [B, 6, 256] | minute_embed [B, 768] |
| **feature_adapter.onnx** | 2.7 MB | 2 | feature [B, 12] | embed [B, 768] |
| **hourslot_encoder.onnx** | 570.9 MB | 3 | minute_embeds [B, 60, 768] | slot [B, 1024], slot_minutes [B, 60, 1024] |
| **history_encoder.onnx** | 567.7 MB | 4 | slot_embeds [B, 90, 1024] + meta | history_embeds [B, 90, 1024] |
| **vitalguard.onnx** | 48.2 MB | 6 | vital_features [B, 60, 5] + hrv | hr_residual_z + trend + context |
| **output_heads.onnx** | 6.3 MB | — | cls_pooled [B, 1024] | anomaly + reason + confidence |
> **QueryRefiner ONNX** 는 cross-attention shape 복잡으로 미지원 (PyTorch ckpt만).
**Total ONNX: ~1.4 GB**
## 🚀 Jetson Inference Example
```python
import onnxruntime as ort
import numpy as np
# TensorRT EP (Jetson에서 자동 가속)
providers = [
'TensorrtExecutionProvider', # Jetson Orin Nano TensorRT
'CUDAExecutionProvider', # fallback CUDA
'CPUExecutionProvider', # last resort
]
# 1. Phone 측 PatchEncoder (Phone ONNX)
phone_sess = ort.InferenceSession("patch_encoder.onnx", providers=['CPUExecutionProvider'])
patches = phone_sess.run(None, {"acc": acc_array}) # [6, 250, 3] → [6, 256]
# 2. Jetson Pipeline
me_sess = ort.InferenceSession("minute_encoder.onnx", providers=providers)
minute = me_sess.run(None, {"patch_tokens": patches.reshape(1, 6, 256)})[0]
hs_sess = ort.InferenceSession("hourslot_encoder.onnx", providers=providers)
slot, slot_minutes = hs_sess.run(None, {"minute_embeds": minute_batch}) # [B, 60, 768]
# ... history, query, heads chain
```
## 🎯 모델 사이즈 — **444.66M params**
| Component | Params | Deploy |
|---|---:|---|
| PatchEncoder | 0.22M | **Phone (ONNX)** |
| MinuteEncoder | 48.09M | Jetson |
| FeatureAdapter | 0.66M | Jetson |
| HourSlotEncoder | 142.60M | Jetson |
| HistoryEncoder | 141.86M | Jetson |
| QueryRefiner | 97.65M | Jetson |
| VitalGuard | 12.01M | Jetson |
| OutputHeads | 1.58M | Jetson |
| **Total** | **444.66M** | — |
## 📊 성능 (OOD: HAR-70+ 노인 70-95세, 학습 X)
| 시나리오 | Score | AUC | Reason |
|---|---:|---:|---:|
| Normal | 0.0004 | — | — |
| walk_missing | 0.9995 | **1.000** | 0% |
| prolonged_inactivity | 0.9987 | **1.000** | 5% |
| routine_time_shift | 0.9995 | **1.000** | **100%** ✓ |
| activity_drop | 0.7145 | 0.950 | 28% |
| **Overall** | — | **0.987** | — |
## 🔧 Train/Val Split + Early Stopping
- Train/Val: 80/20 (3,277 / 819 samples)
- **Best epoch = 1, val_loss = 0.2814** (saved)
- Early stop at epoch 13 (patience=10)
- Overfitting 방지 검증됨
## 📁 PyTorch checkpoints (학습 reproducibility용)
| File | Size | Purpose |
|---|---:|---|
| stage1_patch.pt | 879 KB | PatchEncoder (also ONNX) |
| stage2_minute.pt | 192 MB | MinuteEncoder (also ONNX) |
| stage2_adapter.pt | 2.7 MB | FeatureAdapter (also ONNX) |
| stage3_hourslot.pt | 570 MB | HourSlotEncoder (also ONNX) |
| stage4_history.pt | 567 MB | HistoryEncoder (also ONNX) |
| stage4_refiner.pt | 390 MB | QueryRefiner (PyTorch only) |
| stage5_full.pt | 1.78 GB | Full model (val-split best) |
| stage6_vitalguard.pt | 48 MB | VitalGuard (also ONNX) |
| normalizer.pkl | 405 B | Feature normalizer |
## 학습 데이터
CAPTURE-24 (151) + ArWISE V3 (10명/76일) + PPG-DaLiA (15) + WESAD (15) + MHEALTH (10).
**HAR-70+ (18명 70-95세)는 OOD 평가에만 사용.**
## Code
https://github.com/tlstngud/sisa-routineguard (PRESENTATION.md 포함)