T2D 리스크 스크리너
한국 국민건강보험(NHIS) 데이터를 기반으로 구축한 보정된 당뇨 스크리닝 도구입니다. 환자 스스로 인지하기 전에 공복혈당(FPG) 검사가 필요한 대상자를 사전에 플래그합니다.
한눈에 보기
- 분야: 임상·헬스케어 ML — 한국 건강보험공단(NHIS) 건강검진 공개 데이터(약 100만 명) 기반 학습
- 역할: 개인 프로젝트, CDS 403 포트폴리오, 2026년 봄 학기
- 기술 스택: Python, CatBoost, scikit-learn, SHAP, FastAPI, Pydantic v2, Vanilla JS + Plotly
- 핵심 지표: ROC-AUC 0.816 | 운영 임계값에서 민감도(sensitivity) ≥ 85%
- 상태: 완료 — tysonjohnson.dev/t2d 라이브 데모
문제 / 배경
2형 당뇨병(T2D) 환자 중 약 30~40%는 진단을 받지 못한 상태로 지내고 있습니다. 한국 국민건강보험공단(NHIS)은 매년 약 100만 명의 성인 가입자를 대상으로 건강검진을 실시하며, 활력징후, 체성분, 선택적 검사 패널 등을 수집합니다. 그러나 이 데이터는 임상의가 단일 이상 수치를 발견하지 않는 한 당뇨 의뢰로 이어지지 않는 경우가 대부분입니다. 건강검진에서 수집된 전체 신호 — 허리-키 비율(waist-to-height ratio), 혈압 추이, 간 효소 수치, 지질 비율, 신장 지표 — 를 활용하여 미진단 T2D 가능성이 높은 환자를 선별하고, 공복혈당(FPG) 또는 HbA1c 확인 검사를 권고하는 것이 이 프로젝트의 목표입니다. 한국 NHIS 데이터를 사용함으로써 특징(feature), 참조 범위, 집단 특성이 IQVIA Korea, 병원 데이터 분석팀, 공중보건 선별 프로그램이 실제로 다루는 환자군을 반영합니다.
접근 방식
2024년 NHIS 건강검진 공개 CSV 파일(약 91 MB, 약 100만 행)을 수집하여 원시 검진 항목에서 40개의 특징을 엔지니어링했습니다. 파생 체성분 지수(BMI, 허리-키 비율, 체중 보정 허리 지수), 혈역학 복합 지수(맥압, 평균 동맥압), 간 기능 비율(AST/ALT), 우편향 검사 수치의 로그 변환(GGT, 중성지방, 간 효소), 전체 지질 패널 비율 등이 포함됩니다. 선택적 검사 항목별로 이진 결측 플래그를 추가하여 값뿐만 아니라 결측 여부에서도 학습할 수 있도록 했습니다.
데이터셋은 클래스 불균형 상태입니다(양성 약 7.9%, 약 12:1 비율). 층화 60/20/20 분할을 적용하고, 리샘플링 대신 CatBoost 내부에서 역 클래스 빈도 가중치를 사용하여 보정 목표값의 정직성을 유지했습니다.
동일한 홀드아웃 테스트 분할에서 6개 후보 모델을 평가했습니다 — CatBoost, PyTorch Tabular Net, sklearn MLP, 로지스틱 회귀, SVM(RBF), 의사결정 트리. CatBoost와 Tabular Net은 ROC-AUC에서 사실상 동점(0.817 vs. 0.816)이었지만, CatBoost를 선택한 이유는 예측당 정확한 SHAP 값을 네이티브로 빠르게 계산할 수 있기 때문입니다. 임상 스크리닝 도구에서는 모든 양성 스크린 결과에 어떤 입력이 영향을 미쳤는지에 대한 투명한 설명이 필요합니다. 딥러닝 모델에서 동등한 SHAP를 계산하려면 느린 대리 모델(KernelSHAP)이 필요합니다. 또한 CatBoost는 CPU에서 무시할 수준의 비용으로 실행되어, 배포 시 GPU 의존성이 없습니다.
CatBoost 원시 시그모이드 출력은 순위는 잘 매겼지만 7.9%의 기저율 대비 낮은 확률에서 과신(overconfident)하는 경향이 있었습니다. 검증셋 로짓에 Platt 스케일링(1-파라미터 로지스틱 회귀 적합)을 적용하여 경험적 양성률에 맞게 확률을 보정했습니다. 운영 임계값(0.066)은 민감도 85% 이상을 달성하는 최솟값으로 검증셋에서 튜닝되었으며, 이는 비대칭 임상 비용을 반영합니다: 스크리닝을 놓치면 환자가 FPG 검사를 받을 기회를 잃게 됩니다.
서빙 레이어는 커밋된 모델 번들(약 1.6 MB:
catboost_model.cbm, calibrator.pkl, metadata.json,
global_shap.json)을 기반으로 하는 FastAPI 앱입니다.
Vanilla JS 싱글 페이지 프론트엔드가 검진 입력값을 수집하고 API를 호출하여
보정된 확률, 위험 등급, 예측별 SHAP 워터폴 차트(Plotly), 임상 권고사항을 렌더링합니다.
결과
홀드아웃 20% 테스트 슬라이스(n ≈ 200k)에서 평가한 결과:
| 지표 | 값 |
|---|---|
| ROC-AUC | 0.816 |
| PR-AUC (Average Precision) | 0.273 |
| Brier 점수 | 0.064 |
| 운영 임계값 | 0.066 (민감도 ≥ 85%) |
주요 결정 사항 / 학습 내용
데이터 누출 방지. FPG는 레이블을 정의하는 데 사용된 값입니다
(has_diabetes = FPG ≥ 126 mg/dL).
이를 특징 세트에서 제외하는 것은 필수적이었습니다 — 포함할 경우 모델은 레이블을 단순 재임계화하는 것에 불과하며, 진정한 스크리너가 될 수 없습니다.
간접적 대사 지표만으로 강력한 신호를 구축하는 것이 실질적인 엔지니어링 과제였습니다.
모델 선택은 제품 결정입니다. 동점 PyTorch Tabular Net 대신 CatBoost를 선택한 것은 리더보드 성능 때문이 아닙니다 — AUC 차이는 0.001에 불과했습니다. 제품이 요구하는 것 — GPU 없이 빠르고 정확한 예측별 설명 — 때문이었습니다. 임상 맥락에서 설명 없는 블랙박스 점수는 사실상 사용할 수 없습니다.
보정은 제품 관점의 사고입니다. 환자 순위는 잘 매기지만(좋은 AUC) 실제 기저율이 7.9%일 때 0.4를 출력하는 모델은 임상의가 수치를 확인하는 순간 신뢰를 잃게 됩니다. Platt 스케일링은 작은 추가 작업 — 홀드아웃 로짓에 로지스틱 회귀 한 번 — 이지만, 도구가 표시하는 확률이 단순한 순위가 아니라 실제로 신뢰할 수 있는 확률임을 보장합니다.
한계점
이 프로젝트의 범위와 한계에 대해 솔직하게 명시합니다.
- 단일 한국 코호트, 단일 연도. 모든 학습 데이터는 2024년 NHIS 무작위 표본에서 가져온 것입니다. 다른 집단, 연도, 의료 시스템에서의 성능은 검증되지 않았습니다.
- 레이블 노이즈. 한 시점에서의 FPG ≥ 126 mg/dL는 이미 진단받았지만 혈당 조절이 불량한 일부 T2D 환자를 "미진단"으로 잘못 분류할 수 있습니다. NHIS 공개 데이터에는 치료 이력이 포함되지 않기 때문입니다.
- 선택적 검사의 선택 편향. 지질 및 간 효소 패널은 임상의 재량으로 처방되었습니다. 검사가 누락된 환자는 평균적으로 검사를 받은 환자보다 건강하므로, 모델은 검사 결측을 경미한 건강 신호로 학습합니다. 검사 항목이 모두 공란인 경우 위험도가 과소평가될 수 있으며, 프론트엔드에 경고 문구가 표시됩니다.
- 연령 구간의 조잡함. NHIS는 연령을 5년 단위 구간으로만 공개하며, 모델은 구간 중앙값을 사용합니다.
- 임상 검증 미완료. 이 프로젝트는 연구 포트폴리오 작업입니다. 진단 도구가 아니며 전향적 검증을 거치지 않았습니다.
기술 스택
- 모델링: Python, CatBoost, scikit-learn (Platt 보정, 층화 분할, 평가)
- 설명 가능성: SHAP (CatBoost 네이티브 정확 SHAP)
- API: FastAPI, Pydantic v2, Uvicorn
- 프론트엔드: Vanilla JS, Plotly (SHAP 워터폴 차트)
- 데이터: 한국 NHIS 2024 건강검진 데이터 (data.go.kr)
링크
- GitHub: github.com/tysonjohnsondev/t2d-screener
- 라이브 데모: tysonjohnson.dev/t2d
- 데이터셋: 한국 NHIS 2024 건강검진 데이터