# [12-1] 비식별 종단 EHR 시계열 기반 급성 정신건강 위기 조기 탐지 — 설계 명세서

| 항목 | 내용 |
| --- | --- |
| 참조 하네스 | `prevent12/t121.py` (표준 라이브러리 전용) · 신경망 인터페이스 `torch_ref/t121_model.py` |
| 고정 입력 | `fixtures/t121_generator.json` (잠금 해시는 `prevent12/_contract.py`의 `INPUT_LOCK_SHA256`) |
| 단위 시험 | `tests/test_prevent12.py`의 `Task121Tests` 12건과 `StatsTests` 5건 · Hypothesis 규격 7건 · PyTorch 시험 3건 |
| 실행·감사 | `python3 -B -m prevent12.orchestrate --output evidence/prevent12-run.json` 뒤 `python3 -B -m prevent12.audit --run evidence/prevent12-run.json --output evidence/prevent12-audit.json` (재현 기록) |
| 자료 범위 | 코드가 만든 합성 시퀀스만 사용. MIMIC-IV·MIMIC-IV-Note 원자료와 파생 특징은 이 저장소에 없다 |

2026-11-14 기준. 비식별 종단 기록의 정형 이벤트 시계열로 급성 위기 사건을 미리 알리고, 전문의의 대면 평가 순서를 정하는 데 쓰는 통계·머신러닝 파이프라인의 명세다. 경보는 사람의 평가를 대신하지 않는다.

이 문서의 수치는 세 종류다. **계획 수치**는 내부 연구 목표(재현율 90% 이상)다. **가상 시험 실측**은 prevent12 참조 구현을 고정 합성 입력으로 돌린 값이다. 외부 코호트 실측과 감사자 서명은 이 문서에 없다.

## 안전 경계

- 입력은 표준 코드, 정수 등급, 간격·지연 일수, 사전 추출 수치 벡터뿐이다. 임상노트 원문, 자유 기술, 사건 서술은 전처리 경계 밖으로 나오지 않는다.
- 위기 사건은 추상 이벤트 `CRISIS_EVENT` 하나로 다룬다. 어떤 진단·사건 코드가 여기에 속하는지는 승인된 연구자가 관리하는 외부 구성(`CRISIS_CODESET`)이며, 이 문서와 코드에 목록을 싣지 않는다.
- 합성 시퀀스는 수치·범주형 로그다. 문장을 만들지 않는다.

## 평가 등록부와의 관계

평가 등록부는 12-1의 정답을 "기준 정신건강 진료 직후 24시간 안에 독립 판정으로 확인한 첫 급성 위기 사건"으로, 분할을 기관 단위(평가 기관 25%)와 환자 해시 80:20으로 정했다. 행 명부는 아직 없다(보류).

- 이 명세의 예측 지평 $H$와 되돌아보는 창 $L$은 구성값이다. 등록부 정의로 판정할 때는 둘 다 1일로 둔다.
- 등록부의 "완전 추적에서 사건이 없을 때만 음성"은 2.4–2.5절에서 창 안에 검열된 대상을 음성으로 세지 않고 가중으로 보정하는 것과 같은 원칙이다.
- 기관 분할은 대상 누수를, 3.3절의 as-of 분할은 미래 정보 누수를 막는다. 기관이 둘 이상인 자료에서는 둘을 함께 쓴다. MIMIC-IV는 단일 기관 자료라 등록부의 기관 조건을 채우지 못한다. 따라서 MIMIC-IV에서의 시간 분할 평가는 파이프라인 검증용이고 등록부 종점의 판정에는 쓰지 않는다.

## 1. 비식별 종단 특징 스키마와 합성 이벤트 규격

### 1.1 자료 적합성 (원문 대조 결과)

| 항목 | 확인한 사실 | 설계 반영 |
| --- | --- | --- |
| 날짜 | MIMIC-IV는 환자마다 하루 단위 무작위 이동을 적용한다. `anchor_year_group`이 실제 연도 구간(3년 단위)을 알려 준다. | 시간 분할은 `anchor_year_group` 기준 근사 연도로 한다(3.3절). 모든 시각은 지표 시점 이후 상대 일수 `t_day`로 저장한다. |
| C-SSRS | MIMIC-IV v2.2 공개 demo의 `d_items` 4,014행에 C-SSRS·자살사고 정형 항목이 없다. v3.1에서 늘어난 81개 항목은 자격 인증 없이 볼 수 없어 확인하지 못했다. | `cssrs_grade`는 결측 허용 필드다. MIMIC-IV 유래 행은 `null`과 결측 마스크로 들어가고, 합성 시퀀스에서만 값이 찬다. |
| 추적 구간 | MIMIC-IV는 입원·응급 자료다. MIMIC-IV-Note v2.2는 퇴원 요약 331,794건과 영상 판독 2,321,355건이다. | 외래 추적 간격은 재내원 간격으로 대신한다. 정신과 종단 기록과 위기 발생 시각은 출처 등록부대로 따로 확보해야 한다. |

### 1.2 이벤트 행 스키마 (Parquet `events.parquet`, 한 행 = 한 이벤트)

| 필드 | 형식 | 허용값 | 뜻 |
| --- | --- | --- | --- |
| `subject_token` | string | `SYN-[0-9A-F]{8}` 또는 키 해시 토큰 | 재식별 불가 대상 토큰 |
| `seq` | int32 | 0부터 연속 | 대상 내 순번 |
| `t_day` | float32 | 0 – 3650 | 지표 시점(퇴원) 이후 일수 |
| `delta_t_day` | float32 | 0 – 3650 | 직전 이벤트와의 간격 $\Delta t_i = t_i - t_{i-1}$ |
| `event_type` | enum | `VISIT_OUTPT` `VISIT_ED` `REFILL` `CSSRS_ASSESS` `CRISIS_EVENT` | 이벤트 종류 |
| `setting` | enum | `OUTPT` `ED` `PHARM` | 발생 장소 범주 |
| `cssrs_grade` | int8, 결측 허용 | 0 – 5 | C-SSRS 사고 심각도 정수 등급 |
| `mpr_90d` | float32, 결측 허용 | 0 – 1.5 | 최근 90일 약물 보유율 $\mathrm{MPR}_{90}(t)=\min\{1.5,\ \tfrac{1}{90}\sum \text{공급일수}\}$ |
| `refill_delay_day` | int16, 결측 허용 | 0 – 365 | 처방 리필 지연 일수 |
| `sleep_hours` | float32, 결측 허용 | 0 – 24 | 수면 시간 집계 |
| `hr_cv` | float32, 결측 허용 | 0 – 2 | 심박 변동계수(활력징후 변동 채널) |
| `dx_codes` | list&lt;string&gt; | ICD 형식 `[A-Z][0-9]{2}(\.[0-9A-Z]{1,4})?`, 최대 16 | 진단·처치 표준 코드 |
| `cui_counts` | list&lt;[string, uint8]&gt; | CUI `C[0-9]{7}`, 빈도 1 – 255, 최대 64쌍 | 비식별 임상 개념 빈도 벡터(희소) |
| `concept_emb` | list&lt;float32&gt;[D], 결측 허용 | 각 성분 절댓값 16 이하 | 오프라인에서 뽑은 개념 임베딩(참조 구현 D = 8, 운영 D는 구성값) |

모델 입력 텐서는 이 행을 대상별로 묶어 만든다.

| 텐서 | 모양 | 내용 |
| --- | --- | --- |
| `types` | (B, L) int | 이벤트 종류 색인, 0은 패딩 |
| `t`, `delta_t` | (B, L) float | 상대 시각과 간격 |
| `numeric`, `observed` | (B, L, C) float | 수치 채널(등급, MPR, 지연, 수면, `hr_cv`)과 결측 마스크 |
| `concept` | (B, L, D) float | 개념 임베딩 |
| `cui_index`, `cui_count` | 희소 | $\log(1+c)$로 변환한 개념 빈도 |
| `follow_up`, `event` | (B,) | 추적 종료 시각 $T_n$과 사건 지시자 $\delta_n$ |

변화량 채널은 텐서 단계에서 만든다. 순응도 변화는 $\Delta\mathrm{MPR}(t)=\mathrm{MPR}_{90}(t)-\mathrm{MPR}_{90}(t-90)$, 수면·활력징후 변동은 개인 기저선 대비 표준화 잔차와 최근 창의 변동계수다. 원 행에는 집계값만 두고 파생값은 결측 마스크와 함께 계산한다.

행 예시(합성값, 참조 구현 출력 그대로):

```json
{"subject_token":"SYN-00000000","seq":1,"t_day":21.4968,"delta_t_day":1.7121,
 "event_type":"VISIT_OUTPT","setting":"OUTPT","cssrs_grade":null,"mpr_90d":null,
 "refill_delay_day":null,"sleep_hours":6.88,"hr_cv":0.074,"dx_codes":["F33.1"],
 "cui_counts":[],"concept_emb":null}
```

### 1.3 영원문(Zero-raw-text) 규칙

1. 허용 목록에 없는 필드가 하나라도 있으면 행 전체를 거부한다(`UNKNOWN_FIELD`).
2. 문자열이 들어가는 필드는 열거형이거나 엄격한 코드 패턴이다. 공백, 한글, 16자를 넘는 문자열은 어느 필드에도 맞지 않는다(`INVALID:<필드>`와 함께 `FREE_TEXT`).
3. 중첩 객체는 받지 않는다. 깊은 곳의 문자열도 검사한다.
4. 시퀀스 단위로 순번 연속(`SEQ_GAP`), 시간 역전(`TIME_ORDER`), 간격 불일치(`DELTA_MISMATCH`), 대상 혼입(`MIXED_SUBJECT`), 종결 사건 뒤 이벤트(`EVENT_AFTER_TERMINAL`)를 본다.
5. 실행 결과 문서의 모든 문자열도 식별자 형식이어야 한다. 실행기가 스스로 검사하고 감사기 G1이 다시 검사한다.

구현: `validate_row`, `validate_sequence`.

### 1.4 합성 이벤트 생성기 (상태전환 다변량 Hawkes 과정)

이벤트 종류 $k$의 조건부 강도:

$$\lambda_k(t)=\mu_k\,m_k\big(z(t)\big)+\sum_{j}\alpha_{kj}\,\beta_k\sum_{t_i^{j}<t}e^{-\beta_k\,(t-t_i^{j})}$$

- $z(t)\in\{\text{STABLE},\text{DETERIORATING}\}$는 잠재 상태다. 전환 시각은 $\mathrm{Exp}(\rho)$를 따르고 전환 뒤에는 기저 강도에 배수 $m_k$가 곱해진다. 수면 표식의 평균도 함께 내려간다.
- $\alpha_{kj}$는 종류 $j$ 이벤트 하나가 낳는 종류 $k$ 이벤트의 기대 수(분지 행렬 $A$)다. $\alpha=0$이면 구간별 포아송 과정이 된다.
- 정상성 조건은 스펙트럼 반경 $\rho(A)<1$이다. 불러올 때 $\lVert A^{64}\rVert_\infty^{1/64}<1$로 검사하고 어기면 중단한다.
- 표본 추출은 Ogata 세선화다. 지수 커널이라 여기 성분을 $E_k \leftarrow E_k e^{-\beta_k \Delta}$, 종류 $j$ 발생 시 $E_k \leftarrow E_k+\beta_k\alpha_{kj}$로 갱신한다. 이벤트 사이와 상태 전환점 사이에서는 강도가 줄기만 하므로 현재 총강도가 지배율이다.
- 관측 종료는 첫 `CRISIS_EVENT`, 무작위 중도절단 $C\sim\mathrm{Exp}(c)$, 180일 중 가장 이른 시각이다.
- 하위집단 `G_A` `G_B` `G_C`는 추상 토큰이다. `G_B`에는 선행 이벤트의 20%가 기록에서 빠지는 관측 결손을 일부러 넣었다(3.1절 감사가 이를 잡는지 본다).

고정 입력: t121_generator.json. 구현: `simulate_path`, `make_subjects`.

### 1.5 합성 시퀀스 검증기

| 검사 | 통계량 | 기준 |
| --- | --- | --- |
| V1 스키마 | 전 행 `validate_sequence` | 거부 0건 |
| V2 분지 | $\lVert A^{64}\rVert_\infty^{1/64}$, 행 합 최댓값 | 둘 다 1 미만 |
| V3 보정자 잔차 | $Z_k=(N_k-\Lambda_k)/\sqrt{\Lambda_k}$, $\Lambda_k=\sum_n\int_0^{T_n}\lambda_k$ | $\lvert Z_k\rvert\le 3.5$ |
| V4 시간 재척도화 | 긴 검증 경로에서 종류별 처음 $M_k$개 간격 $\Lambda_k(t_i)-\Lambda_k(t_{i-1})$의 $\mathrm{Exp}(1)$ 적합(KS) | $p\ge 0.01$ |
| V5 음성 대조 | $\alpha=0$ 모형으로 같은 검정 | 반드시 기각 |

- V3은 관측 종료 시각이 정지 시각이어도 성립한다($N_k-\Lambda_k$가 마팅게일). 그래서 중도절단된 연구 시퀀스에 그대로 쓴다. $\Lambda_k$는 생성기 상태를 쓰지 않고 이벤트 목록에서 정의대로 다시 적분한다(`compensators`). 생성기는 $O(K)$ 재귀, 검증기는 종류쌍별 합이라 두 구현이 다르다.
- V4에서 간격 수를 미리 고정한 이유: 창 끝에 걸친 간격을 버리면 남은 간격이 짧은 쪽으로 치우친다. $M_k$번째 이벤트 시각은 정지 시각이므로 그 앞 간격은 정확히 독립 $\mathrm{Exp}(1)$이다.
- 실제 자료의 집계값에 맞춘 합성 자료를 쓸 때는 최근접 기록 거리와 소속 추론 공격 AUC를 추가로 본다. 이 검사는 실제 자료가 있어야 하므로 계획 항목이고 실행하지 않았다.

## 2. 시간 감쇠 어텐션 위험 모형과 재현율 임계치

### 2.1 사건 표현과 시간 감쇠 어텐션

질의 시각 $t$까지의 이력 $\mathcal{H}_t=\{(t_i,c_i,x_i,m_i,u_i): t_i\le t\}$에서

$$h_i=f_\theta\big([\,e_{c_i};\ u_i;\ x_i\odot m_i;\ m_i\,]\big),\qquad a_i^{(k)}(t)=\operatorname*{softmax}_{i:\,t_i\le t}\Big(\tfrac{q_k^{\top}W_k h_i}{\sqrt{d}}-\operatorname{softplus}(\gamma_k)\,(t-t_i)\Big),\qquad z(t)=\bigoplus_{k}\sum_i a_i^{(k)}(t)\,V_k h_i$$

$e_c$는 종류 임베딩, $u$는 개념 임베딩, $x$와 $m$은 수치 채널과 결측 마스크다. 헤드마다 학습되는 감쇠율 $\operatorname{softplus}(\gamma_k)$가 오래된 사건의 가중을 지수적으로 낮춘다. $t_i>t$인 사건은 마스크한다(누수 차단). 이력이 비면 $z(t)=0$이다.

### 2.2 급성 전조 변곡점 항

표준화한 수치 채널 $\tilde x_i$에 양측 CUSUM을 둔다.

$$g^{+}_i=\big[g^{+}_{i-1}+\tilde x_i-\kappa\big]_+,\qquad g^{-}_i=\big[g^{-}_{i-1}-\tilde x_i-\kappa\big]_+,\qquad c(t)=\big[g^{+}_{n(t)};\,g^{-}_{n(t)}\big]$$

$\kappa$는 학습되는 여유값이다. 개인 기저선은 인과적으로 잡는다. 관측 3개가 모이기 전에는 모집단 평균을 쓰고, 그 뒤에는 처음 3개 관측을 모집단 평균 쪽으로 수축한 값으로 고정한다. 나중의 수준 이동이 기저선에 흡수되지 않는다.

같은 대상의 연속 예측 사이에는 로그 위험 경로 $\eta_i$의 총변동 벌점 $\Omega_{TV}=\sum_i\lvert\eta_i-\eta_{i-1}\rvert$을 둔다. 경로가 구간별 상수에 가까워지고, 도약 지점이 변곡점 후보가 된다.

### 2.3 연속시간 위험과 중도절단 우도

질의 시각 이후 구간 $0=\tau_0<\dots<\tau_J$에서 위험이 구간별 상수라고 둔다.

$$\lambda_j=\operatorname{softplus}\big(g_j([\,z(t);\,c(t)\,])\big),\qquad S(u\mid\mathcal{H}_t)=\exp\Big(-\sum_{j=1}^{J}\lambda_j\,\big\lvert[\tau_{j-1},\tau_j)\cap[0,u)\big\rvert\Big),\qquad r_H(t)=1-S(H\mid\mathcal{H}_t)$$

우측 중도절단을 반영한 로그 우도와 학습 목적함수:

$$\ell(\theta)=\sum_n\Big[\delta_n\log\lambda_{j(T_n)}-\sum_{j}\lambda_j\,\big\lvert[\tau_{j-1},\tau_j)\cap[0,T_n)\big\rvert\Big],\qquad \mathcal{L}=-\ell+\lambda_{TV}\,\Omega_{TV}+\lambda_2\lVert\theta\rVert_2^2$$

사건이 없는 대상($\delta_n=0$)은 생존 항으로만 기여한다. 구현 인터페이스: torch_ref/t121_model.py.

| 모듈 | 입력 → 출력 |
| --- | --- |
| `EventEmbedding` | `types (B,L)`, `concept (B,L,D)`, `numeric (B,L,C)`, `observed (B,L,C)` → `h (B,L,dim)` |
| `TimeDecayAttention` | `h`, `t (B,L)`, `t_query (B,)`, `valid (B,L)` → `z (B,dim)`, `weights (B,L,heads)` |
| `ChangePointFeatures` | `numeric·observed (B,L,C)`, `usable (B,L)` → `c (B,2C)` |
| `LongitudinalRiskNet` | 위 전부 → `hazards (B,J)`; `risk(hazards, H)` → `(B,)` |
| `censored_nll` | `hazards`, `time (B,)`, `event (B,)` → 스칼라 |

**참조 모형(표준 라이브러리).** 가상 시험에서는 위 모형의 특수형을 쓴다. 헤드 하나, 감쇠율 고정, 값이 채널 가중 $w_c$인 가법 위험이다.

$$\lambda(s\mid\mathcal{H})=\mu+\sum_{i:\,t_i<s}w_{c_i}\,\beta\,e^{-\beta(s-t_i)},\qquad \ell=\sum_n\Big[\delta_n\log\lambda(T_n)-\mu T_n-\sum_c w_c A_{nc}\Big],\quad A_{nc}=\sum_{i\in c}\big(1-e^{-\beta(T_n-t_i)}\big)$$

EM 갱신은 사건 대상의 책임도 $p_{n0}=\mu/\lambda(T_n)$, $p_{nc}=w_cK_{nc}/\lambda(T_n)$ ($K_{nc}=\sum_{i\in c}\beta e^{-\beta(T_n-t_i)}$)로 $\mu\leftarrow\sum_n\delta_n p_{n0}/\sum_n T_n$, $w_c\leftarrow\sum_n\delta_n p_{nc}/\sum_n A_{nc}$다. 우도는 단조 증가한다. 변곡점 경보(`CP_ALARM`)는 이력의 한 채널로 들어가 가중을 받는다. $\beta$는 격자에서 학습 우도가 가장 큰 값을 고른다. 점수는 $s(t)=1-\exp\{-c\,[\mu H+(1-e^{-\beta H})\sum_i w_{c_i}e^{-\beta(t-t_i)}]\}$다.

### 2.4 Neyman–Pearson 기준 재현율 임계치

추적 중에는 점수가 이벤트마다 바뀐다. 위기 사건 $n$의 **사전 탐지**를 "사건 시각 $T_n$ 직전 $L$일 안에 점수가 임계치 이상이었던 적이 있다"로 정의한다.

$$m_n=\max_{u\inT_n-L,\,T_n)}s_n(u),\qquad \mathrm{Recall}(\theta)=P\big(m\ge\theta\mid \text{위기 사건}\big)$$

**정리.** 보정 집합의 양성 점수 $m_1,\dots,m_n$이 독립이고 분포가 연속이면, $\hat\theta=m_{(k)}$($k$번째로 작은 값)일 때

$$P\big(\mathrm{Recall}(\hat\theta)<1-\alpha\big)=P\big(\mathrm{Bin}(n,\alpha)\le k-1\big)=\sum_{j=0}^{k-1}\binom{n}{j}\alpha^{j}(1-\alpha)^{n-j}$$

*증명.* 양성 점수의 분포함수를 $F$라 하면 누락률은 $F(\hat\theta)=F(m_{(k)})=U_{(k)}\sim\mathrm{Beta}(k,\,n-k+1)$이다. $U_{(k)}>\alpha$는 $U_i\le\alpha$인 표본이 $k-1$개 이하라는 것과 같고 그 개수는 $\mathrm{Bin}(n,\alpha)$다. 동점이 있으면 등호가 부등호(보수적)로 바뀐다. ∎

따라서 $k^{*}=\max\{k:\ \sum_{j=0}^{k-1}\binom{n}{j}\alpha^{j}(1-\alpha)^{n-j}\le\delta\}$로 두고 $\hat\theta=m_{(k^{*})}$로 정하면 확률 $1-\delta$ 이상으로 $\mathrm{Recall}\ge 1-\alpha$다. 이는 음성 표본으로 1종 오류를 묶는 NP 우산 알고리즘을 양성 쪽으로 뒤집은 것이다. $k^{*}$가 있으려면 $(1-\alpha)^n\le\delta$여야 한다.

| $\alpha$ | $\delta$ | 필요한 최소 양성 수 $\lceil\ln\delta/\ln(1-\alpha)\rceil$ |
| ---: | ---: | ---: |
| 0.10 | 0.05 | 29 |
| 0.10 | 0.10 | 22 |
| 0.10 | 0.05/3 (세 집단 Bonferroni) | 39 |
| 0.05 | 0.05 | 59 |

**중도절단 보정.** 추적이 일찍 끊긴 대상의 사건은 관측되지 않으므로 관측된 양성은 이른 사건 쪽으로 치우친다. 검열 생존함수의 Kaplan–Meier 추정 $\hat G$로 가중 $w_n=1/\hat G(T_n^-)$를 주고, 유효 표본 수 $n_{\text{eff}}=(\sum w)^2/\sum w^2$의 정수부 $n'$로 $k^{*}$를 구한 뒤 가중 경험분포에서 허용 누락 비율 $(k^{*}-1)/n'$을 넘지 않는 가장 큰 점수를 $\hat\theta$로 잡는다. 가중이 모두 같으면 위 정리와 일치한다. 가중이 다를 때는 근사이며, 유한 표본 보증은 무가중 경우에만 증명된다. 그래서 합성 자료에서 생성기가 아는 잠재 사건(검열로 가려진 사건 포함)의 재현율과 대조한다(4절).

구현: [`np_order_index`, `np_threshold`, `censoring_km`, `peak_before`.

### 2.5 경보 정밀도와 보정 오차

재현율 제약은 임계치를 낮추면 언제나 채울 수 있다. 그래서 다음 값을 함께 고정해 보고하고, 재현율 제약을 지킨 모형들 가운데 이 값으로 고른다.

- **경보 에피소드 정밀도.** 점수가 $\theta$를 넘은 시각을 경보 시작으로 보고(재경보 대기 30일), 시작 뒤 $H$일 안에 사건이 있으면 참, $H$일을 사건 없이 지나면 거짓으로 센다. 창 안에서 검열된 에피소드는 가중 $1/\hat G$로 보정한다.
- **경보 부담.** 환자 100인·월당 경보 시작 수.
- **보정 오차.** 고정 랜드마크 일($L\in\{30,90\}$)에 위험군에 남은 대상의 예측 $p_i$, 결과 $y_i$, 가중 $w_i=\hat G(L)/\hat G(T_i^-)$ 또는 $\hat G(L)/\hat G(L+H)$로 $\mathrm{ECE}=\sum_b\big\lvert\sum_{i\in b}w_ip_i-\sum_{i\in b}w_iy_i\big\rvert/\sum_i w_i$ (등빈도 10구간). 척도 $c$는 보정 집합에서 가중 평균 예측이 가중 관측률과 같아지게 정한다. 단조 변환이라 순위와 NP 임계치의 의미는 그대로다.

## 3. 임상 안전 거버넌스와 편향 감사

### 3.1 하위집단 재현율 격차 (Equal Opportunity)

$$\mathrm{TPR}_g(\theta)=\frac{\sum_{n\in g,\ \text{양성}}w_n\,\mathbb{1}[m_n\ge\theta]}{\sum_{n\in g,\ \text{양성}}w_n},\qquad \Delta_{EO}=\max_g\mathrm{TPR}_g-\min_g\mathrm{TPR}_g$$

| 판정 | 조건 |
| --- | --- |
| `INSUFFICIENT_N` | 집단 양성 수가 29 미만. 격차 계산에서 빼고 따로 보고한다. |
| `BELOW_TARGET` | $\mathrm{TPR}_g<1-\alpha$ |
| `GAP_EXCEEDS_TOLERANCE` | 평가 가능한 집단 사이 $\Delta_{EO}>0.05$ |
| `NOT_ASSESSABLE` | 평가 가능한 집단이 둘 미만 |

각 집단의 구간은 $n_{\text{eff}}$를 쓴 Wilson 구간이다. 완화 절차는 집단별 NP 임계치 $\hat\theta_g$(수준 $\delta_g$)를 구해 공용 임계치를 $\min(\hat\theta,\min_g\hat\theta_g)$로 낮추는 것이다. 낮춘 뒤의 경보 부담을 반드시 함께 보고한다. 임계치로 격차를 메우는 데는 한계가 있다(4절). 구현: `equal_opportunity`.

### 3.2 불확실 예측의 의료진 검토 큐 라우팅

위에서부터 처음 맞는 규칙을 적용한다.

| 순서 | 조건 | 경로 | 사유 코드 |
| ---: | --- | --- | --- |
| 1 | 모형 출력 없음, NaN·무한대, 모형 장애 | `CLINICIAN_REVIEW` | `MODEL_UNAVAILABLE` |
| 2 | 최근 C-SSRS 등급이 경계 등급(구성값, 참조 4) 이상 | `ALERT_PRIORITY` | `RULE_CSSRS` |
| 3 | $s\ge\hat\theta$ | `ALERT_PRIORITY` | `SCORE` |
| 4 | $0.8\,\hat\theta\le s<\hat\theta$ | `CLINICIAN_REVIEW` | `NEAR_THRESHOLD` |
| 5 | 부트스트랩 앙상블 표준편차가 상한 이상 | `CLINICIAN_REVIEW` | `HIGH_UNCERTAINTY` |
| 6 | 이력 이벤트가 최소 수 미만 | `CLINICIAN_REVIEW` | `SPARSE_HISTORY` |
| 7 | 그 밖 | `ROUTINE` | `BELOW_BAND` |

성질: (a) 모형이 답하지 못한 대상은 `ROUTINE`으로 가지 않는다. (b) 점수가 오르면 경로 우선순위가 내려가지 않는다. (c) 결정론적 등급 규칙은 모형 점수와 무관하게 경보한다. 구현: `route`.

### 3.3 시간축 순차 분할 (as-of 분할)

임계치는 **동결일**에 그날까지 볼 수 있는 정보만으로 정하고, 시험 대상은 동결일 이후에 등록된 사람만 쓴다.

```python
def temporal_split(subjects, cut_train, cut_calib, freeze_lag):
    """train: index_day < cut_train (cut_train 시점까지 관측된 것만)
    calib: cut_train <= index_day < cut_calib (동결일 = cut_calib + freeze_lag 시점까지)
    embargo: cut_calib <= index_day < 동결일 (어디에도 쓰지 않음)
    test: index_day >= 동결일 (연구 종료까지)"""

def as_of(subject, cut):      # cut 시점에 관측 가능한 추적 한계와 사건 지시자
    available = cut - subject.index_day
    return min(subject.end, available), subject.event and subject.end <= available
```

무결성 검사(`split_integrity`): 대상 토큰이 겹치지 않는다. 학습에 쓴 정보의 최대 시각이 학습 절단일 이하다. 보정에 쓴 정보의 최대 시각이 동결일 이하다. 시험 대상의 최소 등록일이 동결일 이상이다. 절단일 뒤에 일어난 사건은 `as_of`가 "아직 사건 없음"으로 돌려준다.

MIMIC-IV에 적용할 때는 등록일을 `anchor_year_group`의 중앙 연도 + (입원 연도 − `anchor_year`)로 근사하고 환자 단위로 나눈다. 구간 폭이 3년이라 학습·보정·시험 사이에 구간 하나를 엠바고로 둔다.

### 3.4 운영 통제

- 임계치·모형·구성 파일은 해시로 동결하고 바꿀 때마다 2.4절 보정과 3.1절 감사를 다시 한다.
- 운영 중에는 랜드마크 관측 대 예측 비, 판정이 확정된 사건의 재현율, 집단별 경보율을 추적한다.
- 경보는 평가 순서를 정하는 데만 쓴다. 조치는 대면 평가를 한 전문의가 정한다.

## 4. 가상 시험 실측 (합성 입력, 2026-11-14)

재실행 방법과 해시는 prevent12 기록. 이 값은 파이프라인이 설계대로 움직이는지 본 것이고 실제 위기 탐지 성능이 아니다.

| 항목 | 값 |
| --- | --- |
| 합성 대상·행 | 3,000명, 40,601행, 스키마 거부 0건 |
| 분지 행렬 | 스펙트럼 반경 상계 0.154, 행 합 최댓값 0.4 |
| 보정자 잔차 $Z_k$ | −0.96 ~ 2.11 (기준 3.5 이내) |
| 시간 재척도화 KS | $p$ = 0.33 ~ 0.98 (7종류), 음성 대조($\alpha=0$)는 기각 |
| 분할 | 학습 829 / 보정 1,051 / 엠바고 160 / 시험 960, 누수 검사 5종 통과 |
| 적합 | $\beta$ = 0.1, 가중: `CSSRS_HIGH` 0.079, `VISIT_ED` 0.057, `CP_ALARM` 0.020, `REFILL_LATE` 0.015, 나머지 0에 가까움 |
| NP 임계치 | 보정 양성 170, $n_{\text{eff}}$ = 162.3, $k^{*}$ = 10, $\hat\theta$ = 0.03811 (기저 점수 0.0214보다 위) |
| **시험 재현율** | **0.9155** (IPCW), 무가중 0.9162, 양성 167건 |
| 잠재 정답 대조 | 0.9324 (검열로 가려진 사건까지 포함) |
| 재현율 단측 95% 하한 | 0.873 (시험 표본의 Wilson 하한) |
| 경보 에피소드 정밀도 | 0.0788 (2,037건) |
| 경보 부담 | 환자 100인·월당 46.1건 |
| 보정 오차 ECE | 시험 0.0202, 보정 0.0268, 관측/예측 0.922 |
| 경로 | 경보 679 / 검토 50 / 일상 231, 사람 검토까지 포함한 재현율 0.934 |
| 집단별 재현율 | `G_A` 0.946, `G_B` 0.872(`BELOW_TARGET`), `G_C` 0.930 → 격차 0.073, `GAP_EXCEEDS_TOLERANCE` |
| 완화 후 | 공용 임계치 0.02136(기저 점수 수준) → 세 집단 1.0, 경보 부담 84.7건, 정밀도 0.042 |

읽는 법:

- 시험 점추정은 목표를 넘지만 시험 표본의 단측 하한은 0.873이다. NP 보증은 모집단 재현율에 대한 것이고, 양성 167건짜리 시험 집합의 추정 오차와는 다른 문제다.
- 재현율 0.9를 지키는 대가가 경보 부담 46건과 에피소드 정밀도 8%로 나온다. 이 합성 세계에서는 재현율 제약이 임계치를 낮은 쪽으로 민다.
- 관측 결손을 넣은 `G_B`를 감사가 잡아냈다. 집단별 임계치로 메우려 하면 임계치가 기저 점수까지 내려가 사실상 상시 경보가 된다. 이 경우 고칠 것은 임계치가 아니라 기록 결손이다.
- 변곡점 경보 채널이 0이 아닌 가중을 받았다. 잠재 상태 전환의 직접 효과를 수면 표식의 CUSUM이 일부 설명한다는 뜻이다.

## 5. IEC 62304 추적

분류는 IEC 62304:2006+AMD1:2015의 위험 기반 분류를 따른다. 이 단위는 전문의 대면 평가를 전제로 우선순위만 정하므로 잠정 Class B로 두고, 최종 분류는 위험관리 결과로 확정한다. 표준 본문(4.3절)은 유료라 열지 못했고 분류 문구는 2차 요약으로 확인했다.

| 요구 | 단위 | 검증 | 위험 통제 |
| --- | --- | --- | --- |
| SRS-121-01 원문 텍스트 유입 금지 | `validate_row`, `free_text_paths` | `test_schema_admits_generated_rows_and_rejects_raw_text`, 감사 G1 | 재식별·민감 서술 유출 |
| SRS-121-02 합성기가 선언한 과정과 일치 | `simulate_path`, `compensators` | `test_generator_matches_its_compensator_and_rejects_a_wrong_model`, V3–V5 | 잘못된 합성 자료로 한 검증 |
| SRS-121-03 중도절단 반영 우도 | `fit_hazard`, `censored_nll` | `test_em_likelihood_is_monotone_and_finds_the_precursors`, `test_censored_likelihood_matches_the_closed_form` | 추적 손실에 의한 위험 과소추정 |
| SRS-121-04 재현율 보증 임계치 | `np_order_index`, `np_threshold` | `test_np_threshold_keeps_recall_with_declared_confidence`(모의 2,000회), 감사 G3의 유리수 재계산 | 위기 누락 |
| SRS-121-05 미래 정보 차단 | `as_of`, `temporal_split`, 어텐션 마스크 | `test_as_of_split_hides_the_future`, `test_events_after_the_query_time_cannot_change_the_prediction` | 낙관적 성능 추정 |
| SRS-121-06 불확실 예측의 사람 검토 | `route` | `test_routing_never_sends_the_unknown_to_routine`, Hypothesis `test_routing_is_total_and_fail_safe` | 모형 장애 시 무경보 |
| SRS-121-07 집단 격차 감사 | `equal_opportunity` | `test_equal_opportunity_audit`, 감사 G3 | 특정 집단의 체계적 누락 |

## 6. 확인한 원문

이번 세션의 하위 작업자가 2026-11-14에 원문을 열어 대조했다.

- NP 우산 알고리즘의 순서통계량 임계치와 위반 확률 상계, 최소 표본 식. 원문은 음성 표본의 1종 오류를 다루며 본 명세는 이를 양성 쪽으로 뒤집었다. 원문 본문의 예시 숫자 두 개는 식과 맞지 않아 인용하지 않고 식으로 계산했다. [Tong, Feng, Li (2018)](https://arxiv.org/abs/1608.03109)
- `anchor_year_group`의 뜻과 날짜 이동 방식. [MIMIC-IV patients 표](https://mimic.mit.edu/docs/iv/modules/hosp/patients.html) · [MIMIC-IV v2.2](https://physionet.org/content/mimiciv/2.2/)
- MIMIC-IV-Note v2.2의 노트 종류와 건수. [PhysioNet](https://physionet.org/content/mimic-iv-note/2.2/)
- `d_items`에 C-SSRS 정형 항목이 없음(v2.2 demo 4,014행). [d_items](https://physionet.org/files/mimic-iv-demo/2.2/icu/d_items.csv.gz)
- C-SSRS 사고 심각도 5개 유형과 "사고 없음 = 0" 파생 점수. [Columbia 채점 안내](https://cssrs.columbia.edu/wp-content/uploads/ScoringandDataAnalysisGuide-for-Clinical-Trials-1.pdf)

Hawkes 과정의 세선화·시간 재척도화, Kaplan–Meier, IPCW, CUSUM은 교과서 결과를 썼고 이번에 원문을 따로 열지 않았다. 그 대신 4절의 수치 검사(보정자 잔차, KS, 모의 2,000회 적중률)로 구현을 확인했다.
