v7 Peak-Aware FL Experiment Design¶
0. 배경 및 목적¶
v6 track-e v3의 patchwork(Tier 1a/1b 분할, provisional/final Branch, 5분기 자동 분류)를 폐기하고, 다음 초록의 검증에만 집중하는 clean restart phase.
대상 초록 (2026-04-19 사용자 수정판)
Accurate peak load forecasting is critical to power system operation, but household-level forecasting remains difficult due to load variability. Since consumption data are privacy-sensitive, federated learning (FL) offers a natural framework for collaborative modeling without centralized data collection.
We propose a peak-aware FL framework with two components: (i) a peak-weighted loss that emphasizes peak-time samples during training, and (ii) a dual-path architecture that combines a shared vector-quantized (VQ) codebook for federated pattern exchange with a lightweight DLinear residual for per-household personalization. We evaluate models using PAPE (Peak Absolute Percentage Error) and HR (Hit Rate), metrics tailored to peak-region accuracy.
Across a broad set of baselines, the proposed model achieves the best peak accuracy, reducing PAPE by 9.8% relative to local-only training. Notably, our light-weight model surpasses time-series foundation models, showing that loss design and personalization outweigh model scale for household peak forecasting under privacy constraints.
용도: 학술 논문 아님. 발표자료. 우선순위 = 속도 + 정확성.
환경: Umass HH 5가구 (Apt6, 15, 30, 51, 88), RTX 5070 Ti 16GB 단일, MLflow tracking.
1. 검증 대상 Claim 및 Rollback 규칙 (pre-registered)¶
| # | Claim | 통과 기준 | Rollback |
|---|---|---|---|
| C1 | FL + privacy motivation | 서술 | 없음 |
| C2 | peak-weighted loss 효과 | A1 vs A0 paired Wilcoxon p<0.05 | "asymmetrically weighted" |
| C3 | VQ codebook 기여 (federated pattern exchange) | A3 vs A1 bootstrap 95% CI 하한 > 0 | "(ii)" 구절 재구성 |
| C4 | DLinear residual 기여 (personalization) | A3 vs A4 paired Wilcoxon p<0.05 | "local adaptation head" |
| C5 | best across baselines | A3 vs {B0,B1,B2,B3,B4} Wilcoxon + Bonferroni 다수 PASS | "competitive peak accuracy" |
| C6 | PAPE 9.8% reduction vs local-only | (B0 − A3) / B0 bootstrap 95% CI 하한 > 5% | 실측 CI median % 교체 |
| C7 | light-weight surpasses TSFM | 단계 6 Chronos + TimeMoE zero-shot 평가 후 disclosure | 비교 자체 유지 + param 비율 명기 |
원칙: 결과 확인 즉시 자동 rollback 적용. orchestrator override 금지.
2. 사전 등록 사항 (단계 0, override 금지)¶
2.1 실험 단위¶
- Seed set: {42, 123, 456, 789, 2024} (5-seed paired)
- 가구: Apt6, 15, 30, 51, 88
- Tin/Tout: 96h → 24h
- Train/Val/Test split: 시계열 순서 고정 (v6 split 계승)
2.2 Metric 정의 (단일 코드 경로 강제)¶
단일 소스: src/peak_analysis/v7/metrics.py. 모든 v7 스크립트는 이 모듈을
import해야 한다 (stage-0 v7_0419_stage0_preregistration.py, stages 1~4
v7_runner.py 공통). 정의 drift 발생 시 definition_hash() 값이 바뀌며,
pre-registration 시점과 불일치하면 fail-fast 트리거.
PAPE_v7:
- 대상 시점: 실제값 ≥ Q90 (각 가구 train+val 분포의 90 percentile)
- 계산: mean(|y_true − y_pred| / y_true × 100) (대상 시점만)
- Degenerate case: y_true의 std < 1e-8이면 NaN 반환 (G2 policy)
- 대상 시점이 없거나 y_true 모두 0에 가까우면 NaN
HR_v7 (Hit Rate):
- K = 12 (일 24시간 중 상위 50%, 단일 값 고정)
- 계산: |argsort_K(y_true) ∩ argsort_K(y_pred)| / K per day, mean across days and households
Golden tensor 5쌍 (stage-0 2026-04-19 v2 pre-registered, 단계 1~4 전 코드 경로 sanity):
| ID | y_true | y_pred | expected PAPE | expected HR | 비고 |
|---|---|---|---|---|---|
| G1 | [1,2,10,3] |
[1,2,8,3] |
20.000000 | 1.000000 | toy; Q90=7.9 trigger 1개 |
| G2 | [5,5,5,5] |
[4,5,6,5] |
NaN | NaN | degenerate-variance (std=0) → NaN by policy |
| G3 | Apt6 test 첫 7일 (168h, start=0) | y_pred = y_true (perfect) | 0.000000 | 1.000000 | q90=2.918 |
| G4 | Apt6 test 첫 7일 (168h, start=0) | const = mean(block) = 1.088576 | 67.342534 | 0.619048 | q90=2.918 |
| G5 | Apt15 test 첫 14일 (336h, start=384, hits≥12) | uniform(min(train+val), max(train+val)), seed=42 | 64.279282 | 0.511905 | q90=1.721; 14d로 n_hits=2→13 (seed 편차 44% 감소) |
재현 규칙 요약:
- 첫 블록 선택: extract_first_block(test_vals, q90, block_hours, min_hits) — 24h-aligned 슬라이딩, q90-hit≥min_hits인 첫 블록
- G3/G4: min_hits=1, block_hours=168
- G5: min_hits=12, block_hours=336 (critic M1 대응, n=2 대신 n≥12 샘플)
- G5 RNG: np.random.default_rng(42).uniform(low, high, shape); low/high는 train+val min/max
- Gate 1 assertion: atol=1e-6
- y_true / y_pred ndarray는 stage-0 run의 artifact golden_tensors/{G3,G4,G5}_y_{true,pred}.npy로 freeze됨
정의 해시: definition_hash() = sha256(이 모듈 소스 || DEFINITION_HASH_PAYLOAD JSON) 상위 16 hex. 2026-04-19 v2 기준 = 8be2bd2f691deed0. 단계 1~4 모든 MLflow run은 이 해시를 param으로 로깅하며 불일치 시 fail-fast.
2.3 통계 방법론¶
- Paired Wilcoxon signed-rank test (각 5-seed paired)
- Bootstrap 95% CI (1000 resamples)
- Bonferroni correction (k = claim 수)
- Primary metric = PAPE / Secondary = HR
2.4 Fail-fast Threshold (per-run hook, 7-metric) — v2 2026-04-19 critic-revised¶
설계 원칙 전환 (critic C3 대응): v1의 "v6 historical max × 1.5"는 accepted 표본이 n=4 (그중 3개는 2-epoch prototype)이라 대표성 없음. v2는 per-run val divergence + static train ceiling 조합으로 전환.
| Metric | Threshold | 근거 / 구현 |
|---|---|---|
final_train_loss |
> 3.0 (static sanity ceiling) | v6 converged runs (MIN_STEPS≥10) max=0.541 × ~5.5배; catastrophic divergence 차단 목적 |
nan_step_count |
> 0 | 학습 중 NaN 발생 즉시 fail |
final_val_loss / initial_val_loss (epoch 5+ moving avg ratio) |
> 1.5 | per-run silent divergence 탐지. run-local 기준이라 표본 편향 무관 |
n_nan_predictions |
> 0 | 예측 단계 NaN 즉시 fail |
final_codebook_util (VQ cell만) |
< 0.05 | WARNING (FAIL 아님), v6 near-collapse 3~6% 기준 |
pape_definition_hash |
mismatch | 단일 코드 경로 강제, 정의 drift 차단 |
scaler_space_signature |
mismatch | normalization leakage 차단 |
v6 stage-0 재산출 통계 요약 (MIN_STEPS≥10 converged filter 적용, n=22):
- final_train_loss 분포 (n=3, track-e-tier0은 2-epoch proto로 대부분 탈락): p50=0.324, p95=0.520, max=0.541
- final_val_loss 분포 (n=22): p50=0.336, p95=0.353, max=0.403, min=0.278
- final_val_loss / initial_val_loss 분포 (n=22): p50=0.929, p95=1.001, max=1.001
→ 관찰: v6 converged runs은 val loss가 초기 대비 완만하게만 개선된다.
1.5× 임계는 "명확한 divergence"만 포착 (보수적 설계).
- Gate 5 metric 근거 (§3 단계 0.5 참조, 2026-04-20 redesign):
위 final_val_loss / initial_val_loss 분포(p50=0.929)는 "divergence 여부"를 가리는
§2.4 지표로만 쓰이며, Gate 5 convergence 판정에는 쓰이지 않는다. Gate 5는 새
rel_decrease = (mean(vl[:3]) − mean(vl[-3:])) / mean(vl[:3]) 지표를 사용하며,
v6 n=22 back-test 결과 p10=0.0017 / p05=−0.0005 / p50=0.0350로부터 PASS/WARNING/FAIL
cutoff가 empirical하게 도출된다. 두 지표는 상호 보완적이며 중복되지 않는다.
기각된 대안: - Option A (P95 × 1.5): n=3 표본, 기각. - Option C (v6 historical max × 1.5 = 2.63): v1 사용, 2-epoch prototype epoch-1 loss에 근거하여 대표성 없음, 기각.
2.5 MLflow 로깅 의무 (전 실험 공통)¶
- per-epoch/round train_loss, val_loss (
mlflow.log_metric(step=)) - best checkpoint (
mlflow.log_artifact) - test y_true.npy + y_pred.npy (
mlflow.log_artifact) - 가구별 + avg PAPE, HR, MSE, MAE (
mlflow.log_metric) - 7-metric fail-fast 지표 (
mlflow.log_metric) - config 전체 (
mlflow.log_params) — pape_definition_hash, scaler_space_signature 포함
3. 실험 단계¶
단계 0 — 사전 등록 (D+0, ~0.5h)¶
- 위 §2 전체 항목을 코드/문서 양쪽에 확정 기록
- Golden tensor 5쌍 expected 값 표 작성 (실제 값 채움)
- v6 historical loss range 추출 → fail-fast threshold 확정
단계 0.5 — Vertical Slice Smoke Test (D+0~1, 12 runs, ~2h)¶
- 호출:
uv run python -m experiments.federated.v7_runner --mode=smoke --households=Apt6,Apt_max --cells=B0,B2,A3 --seeds=42,43,123 - 가구: Apt6 + Apt88 (
Apt_max_load). Stage-0 v2 (2026-04-19) 기준: 5개 peak-load metric (daily_max_mean, daily_max_median, daily_max_p95, overall_max, overall_p95) 모두에서 Apt88이 1위 (critic M2 민감도 검증 통과). variability(std, CV)는 Apt51이 1위지만 "extreme high-load"와는 다른 축이라 plurality vote에서 제외. - Cells: B0 (Local), B2 (Ditto λ — 가장 risky regularization), A3 (full proposed)
6 Critical Gates (모두 PASS/WARNING 시 단계 1 진입; FAIL 1개라도 있으면 HOLD):
1. PAPE/HR 정의 코드 경로 동일 (hash + golden tensor expected 값 assertion)
2. VQ + DLinear scaler space 일치 (std ratio ∈ [0.5, 2.0] + unit assertion)
3. MLflow artifact 완전성 (best.ckpt, y_true.npy, y_pred.npy, per-epoch loss, 7-metric 모두 기록)
4. Figure가 mlflow.search_runs() 직접 query로 그려지고 PNG EXIF에 run_id 임베드
5. 수렴성 — monotonic-decrease metric (2026-04-20 v3 redesign):
rel_decrease = (mean(val_loss[:3]) − mean(val_loss[-3:])) / mean(val_loss[:3])
- PASS: rel_decrease ≥ 0.0017 (v6 n=22 converged-run P10; TPR 86.4% on v6)
- WARNING: 0.0 ≤ rel_decrease < 0.0017 (borderline, v6 P05~P10 구간)
- FAIL: rel_decrease < 0.0 (net increase — 수렴 방향 반대)
- 전제: len(val_loss) ≥ 6. 미만이면 ERROR 처리.
- smoke / full 공통 metric. Block size=3은 smoke 최소 10 rounds에서 초기/말미 각 3개를 안정적으로 분리.
- 근거: outputs/v7_stage05/v6_gate5_backtest.json (2026-04-20).
Legacy moving/initial < 0.5는 v6 n=22 중 0건 PASS(false-positive rate 1.0)로 사실상 불가능한 임계였으며 폐기.
6. Paired 구조 sanity (동일 seed의 모든 cell이 동일 train/val/test split data hash)
FAIL 처리: Q2 정책에 따라 자동 engineer 호출 + 사용자 알림 동시. 수정 후 단계 0.5 재실행. 재smoke 사이클 최대 2회.
§2.4 val-divergence와 Gate 5의 관계 (중복·충돌 없음):
- §2.4 final_val_loss / initial_val_loss > 1.5 = divergence detector (per-run hook, 1회 판정).
- §3 Gate 5 rel_decrease = convergence verifier (smoke aggregate, 3-tier).
- 두 지표는 서로 다른 끝단(발산 vs 정체)을 보호. 한 쪽이 다른 쪽을 대체하지 못한다.
예: rel_decrease = 0 + ratio = 1.0은 §2.4에서는 PASS이지만 §3 Gate 5는 WARNING.
단계 1 — Baseline 5종 × 5-seed (D+1~2, 25 runs, ~3h 병렬)¶
| ID | 방법 | 하이퍼파라미터 |
|---|---|---|
| B0 | Local DLinear | fixed default |
| B1 | FedAvg + DLinear | fixed default |
| B2 | FedProx + DLinear | μ = 0.01 |
| B3 | FedRep (shared encoder + local head) | fixed default |
| B4 | Ditto | λ = 0.1 |
- 호출:
v7_runner.py --mode=main --phase=baseline --cells=B0,B1,B2,B3,B4 --seeds=42,123,456,789,2024 --households=all - 2-way 병렬 (DLinear-only + Fed methods)
- Early checkpoint: B0 5-seed 완료 시 자동 점검. 5/5 PASS면 B1~B4 진행. NaN 1개 발생 시 Q1 정책(Option A) — 동일 seed 재실행 1회. 재실행 후에도 5/5 미달 시 stop-and-wait + 부분 분석 보고서 자동 생성.
단계 2 — Ablation 5종 × 5-seed (D+2~3, 20 runs, ~7h)¶
| ID | peak loss | VQ path | DLinear path | 검증 |
|---|---|---|---|---|
| A0 | SmoothL1 | ✗ | ✓ | (= B1, dedup) |
| A1 | peak-weighted | ✗ | ✓ | C2 (peak-loss 기여) |
| A2 | SmoothL1 | ✓ | ✓ | C3 mid (no peak) |
| A3 | peak-weighted | ✓ | ✓ | full proposed |
| A4 | peak-weighted | ✓ | ✗ (y_vq만) | C4 (DLinear 기여) |
- 호출:
v7_runner.py --mode=main --phase=ablation --cells=A1,A2,A3,A4 --seeds=... - Spot check: A1 첫 1 seed 완료 후 7-metric 점검 → PASS 시 잔여 진행
단계 4 — VQ 개선 3종 × 5-seed (D+3, 15 runs, ~5.5h)¶
본문 Method 섹션에 명시 (초록 변경 없음).
| ID | 기법 |
|---|---|
| V1 | A3 + EMA codebook update (γ=0.95) |
| V2 | A3 + K-means init (warm-up round=5) |
| V3 | A3 + EMA + K-means |
- 목적: codebook util이 v6의 3~6%에서 ≥ 20%로 개선되는지 검증
- Spot check: V1 첫 1 seed 완료 후 점검
단계 5 — 통계 검증 + Claim Rollback (D+3~4, ~4h)¶
- 단계 1+2+4 결과로 §1 Claim 표의 통과 기준 자동 평가
- 미통과 claim은 즉시 rollback 문구 적용 (override 금지)
- bootstrap CI median % 실측값으로 9.8% 교체 가능
단계 6 — TSFM 비교 + 발표자료 (D+4, ~8h)¶
- Chronos zero-shot + TimeMoE zero-shot on 5가구 (training 없음, inference만)
- C7 disclosure: 제안 모델 param 수 + TSFM param 수 비율 본문 명기
- 발표자료 figure: 모든 plot은 MLflow run_id 직접 query (PNG EXIF run_id 임베드)
- 산출: presentation slides + figure 폴더
4. 안전망 (3-layer)¶
- 단계 0.5 Vertical Slice Smoke (12 runs / ~2h) — 6 Critical Gate
- Per-run fail-fast hook (7-metric, 단계 1~4 전체 적용) — 이상 즉시 FAIL_AUTO 마킹 + 다음 run skip
- Cell-specific spot check (단계 1 early checkpoint + 단계 2/4 진입 시 첫 cell 1 seed)
5. 사용자 결정 (확정)¶
| Q | 채택안 |
|---|---|
| Q1 NaN seed 처리 | Option A — 동일 seed 1회 재실행. 재실행 후 5/5 미달 시 stop-and-wait |
| Q2 Gate FAIL 시 | 자동 engineer 호출 + 사용자 알림 동시 |
| Q3 Early checkpoint FAIL | stop-and-wait + 부분 분석 보고서 자동 생성 |
6. 단일 entry point 설계 (C-7 mitigation)¶
experiments/federated/v7_runner.py — 모든 단계가 동일 runner의 config flag로 호출:
v7_runner.py
--mode={smoke,main}
--phase={baseline,ablation,vq_improvement}
--cells=B0,B1,B2,B3,B4,A1,A2,A3,A4,V1,V2,V3
--seeds=42,123,456,789,2024
--households=Apt6,Apt15,Apt30,Apt51,Apt88|all
--golden-tensor-check (Gate 1 sanity)
별도 smoke 스크립트 작성 금지. smoke ↔ main 코드 경로 100% 공유.
7. Workload + 타임라인¶
| 단계 | 시간 |
|---|---|
| 0 사전 등록 | 0.5h |
| 0.5 smoke (12 runs) | 2h |
| 1 baseline (25 runs, 병렬) | 3h |
| 2 ablation (20 runs) | 7h |
| 4 VQ 개선 (15 runs) | 5.5h |
| 5 통계 + 6 TSFM + 발표자료 | 12h |
| 재smoke buffer (1 cycle) | +2~4h |
| 총 | ~32~34h ≈ 3-4일 |
8. Gate Check 요약¶
| Gate | 시점 | 통과 조건 | 실패 시 |
|---|---|---|---|
| 단계 0 사전등록 완료 | D+0 | golden tensor 표 작성 + threshold 확정 | 단계 0.5 진입 차단 |
| 단계 0.5 6-Gate | D+0~1 | 모두 PASS | 자동 engineer 호출, 재smoke 최대 2회 |
| 단계 1 early checkpoint | D+1~2 | B0 5-seed 5/5 PASS | stop-and-wait + 부분 분석 보고서 |
| 단계 2 spot check | D+2 | A1 첫 1 seed 7-metric PASS | stop-and-wait |
| 단계 4 spot check | D+3 | V1 첫 1 seed PASS | stop-and-wait |
| 단계 5 통계 | D+3~4 | claim별 자동 rollback | (override 금지) |