Skip to content

Latest commit

 

History

History

generalized-anxiety-disorder

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

README.md

범불안장애 (Generalized Anxiety Disorder) — QSP 모델

One corticolimbic gain, four factors, four clocks — and a fifth clock inside the ruler.

GAD QSP mechanistic map


0. 한 줄 요약 (The claim in one line)

이 모델은 불안을 하나의 무차원 피질–변연계 이득(corticolimbic gain)

        E_amy × S_glu
Φ  =  ───────────────────────────
      C_pfc·(1 + e_ex·EXPECT) × I_gaba

으로 쓴다. 분자에 두 인자, 분모에 두 인자가 있는 비(ratio) 이며, 네 인자는 각각 다른 약물군이 서로 다른 시간상수로 움직인다. 그리고 이 모든 것은 HAM-A라는 포화형(saturating) 척도를 통해 읽히는데, 그 척도는 자기 자신의 다섯 번째 시계(기대효과 + 평균회귀)를 얹는다.

인자 의미 움직이는 약물 시간상수(모델 계산값)
I_gaba GABA-A 억제 효율 (분모) 벤조디아제핀 0.5 d (효과 t50 2.5 d)
S_glu 시냅스전 글루타메이트 방출확률 (분자) 프레가발린 (α2δ-1) 2.0 d (효과 t50 4.5 d)
C_pfc 전전두엽 하향 조절 용량 (분모) SSRI/SNRI, CBT 40 d (효과 t50 35 d)
E_amy 편도체/BNST 흥분 구동 (분자) CBT, 만성 5-HT 수 주
EXPECT+FLUCT 기대효과 + 등록 시점 평균회귀 (모든 팔에 공통) 가장 빠름 — 8주 위약효과의 57%가 1주에

세 가지 결과가 이 대수식에서 가정이 아니라 계산으로 나온다 — 그리고 세 가지 사전 기대는 반증되어 그대로 보고된다.


1. 이 디렉토리의 파일 (Files)

파일 내용
gad_qsp_model.dot · .svg · .png 기계론적 지도 — 206 노드 · 19 클러스터 · 301 엣지
gad_python_reference.py 실행 가능한 참조 구현 (49 ODE). README·mrgsolve·Shiny의 모든 숫자는 여기서 나온다
gad_calibrate.py 보정. 5개 파라미터, 6개 숫자. 어떤 시도가 왜 실패했는지까지 기록
gad_analysis.py → gad_reference_output.txt 12개 시나리오 블록 전체 실행 결과 (472행)
gad_mrgsolve_model.R mrgsolve 모델 (50 구획). 참조 구현을 식 단위로 옮긴 것
mkmrgsolve.py 위 R 파일 생성기 — 보정값·초기조건이 어긋날 수 없게 만든다
gad_shiny_app.R Shiny 대시보드 (12 탭)
gad_references.md · mkrefs.py 118개 문헌 / 113개 고유 PMID, 전부 PubMed에서 실시간 조회
gad_calibration.json · gad_attractor_cache.npz 보정 결과와 무투약 어트랙터 캐시
calib.log · calib_stage1_joint.log 보정 로그 (실패한 첫 시도 포함)

렌더링·실행:

dot -Tsvg gad_qsp_model.dot -o gad_qsp_model.svg
dot -Tpng -Gdpi=150 gad_qsp_model.dot -o gad_qsp_model.png
python3 gad_calibrate.py      # 5개 파라미터 재보정
python3 mkmrgsolve.py         # gad_mrgsolve_model.R 재생성
python3 gad_analysis.py       # gad_reference_output.txt 재생성
python3 mkrefs.py             # gad_references.md 재생성
Rscript -e 'shiny::runApp("gad_shiny_app.R")'

2. 무엇을 적합(fit)했고 무엇을 예측(predict)했는가

적합된 파라미터는 5개뿐이다.

파라미터 적합 대상
fluct0 = 3.85, kfl = 2.00 /d 위약군 곡선의 모양 — Khan 2011 (PMID 21694613) 1주 −5.94 / 8주 −11.10, Rickels 2005 (PMID 16143734) 4주 −8.40
k5ht_eff = 0.126 에스시탈로프람–위약 차 −2.45 (Slee 2019 NMA, PMID 30712879)
emax_pgb = 0.094 프레가발린–위약 차 −2.79 (Slee 2019 NMA)
emax_a2 = 0.571 알프라졸람 1.5 mg–위약 차 −2.50 (Rickels 2005)

dvisit = 0.30과 e_ex = 0.55는 적합하지 않고 구조적으로 고정했다. 이유는 §6.

적합 결과 (6개 숫자):

  placebo week 1        :   -5.75   target   -5.94
  placebo week 4        :   -9.60   target   -8.40      <-- 미스
  placebo week 8        :  -10.09   target  -11.10      <-- 미스
  escitalopram 10 delta :   -2.45   target   -2.45
  pregabalin 300 delta  :   -2.79   target   -2.79
  alprazolam 1.5 delta  :   -2.50   target   -2.50

위약군 잔차는 구조적이다. 두 시험의 위약 곡선은 −5.94 → −8.40 → −11.10으로 거의 직선인데, 이 모델의 위약 반응은 4주 무렵 정체한다. 정직하게 말하면 이 모델은 8주까지 계속 떨어지는 위약 곡선을 만들지 못한다.

나머지는 전부 out-of-sample. 아래 §3–§5의 모든 숫자가 그렇다.


3. 예측 성적표 (Out-of-sample scorecard)

3.1 Slee 2019 Lancet 네트워크 메타분석 (PMID 30712879) — 8주 위약대비 차

약물 모델 보고값
에스시탈로프람 10 mg −2.45 −2.45 ← 적합
프레가발린 300 mg −2.79 −2.79 ← 적합
벤라팍신 ER 150 mg −4.24 −2.69 과대예측
둘록세틴 60 mg −2.53 −3.13 과소예측
케티아핀 XR 150 mg −0.57 −3.60 큰 미스
부스피론 45 mg −0.27 (효과 있으나 표본 작음) 과소예측

SNRI 두 개의 방향이 서로 반대로 틀렸다는 점이 의미 있다 — NET 점유율 곡선 (EC50 260 ng/mL vs 46 ng/mL)이 벤라팍신에 너무 관대하고 둘록세틴에 너무 인색하다.

3.2 Khan 2011 케티아핀 XR (PMID 21694613) — 이 모델의 가장 큰 실패

팔 1주 모델 1주 보고 8주 모델 8주 보고
위약 −5.75 −5.94 −10.09 −11.10
케티아핀 50 −6.24 −7.47 −10.61 −13.31
케티아핀 150 −6.18 −8.19 −10.66 −13.54
케티아핀 300 −6.10 −7.23 −10.68 −11.87

모델은 케티아핀에 거의 효과를 주지 않는다. 이 모델에서 케티아핀의 유일한 항불안 경로는 노르케티아핀의 NET 억제(150 mg에서 점유율 0.295)인데, 실제 케티아핀은 5-HT2A/2C 길항, α1 차단, H1 차단을 통해 작동하며 이 모델에는 그 경로가 없다. 보고된 역-U자 용량반응(300 mg < 150 mg)도 재현하지 못한다 — §9의 가상 집단에서 이상반응 기반 탈락을 넣어도 −10.16(300) vs −9.88(150)으로 여전히 단조롭다. 이것은 파라미터 문제가 아니라 구조의 결손이며, 그대로 보고한다.

3.3 Allgulander 2006 무작위 중단 시험 (PMID 16316482) — 모델의 결정적 시험

급성기 보정만 가지고, 12주 개방표지 → 반응자 무작위 배정 → 76주 추적을 설계 그대로 시뮬레이션한 결과:

모델 보고값
개방표지 반응자 비율 65% 76%
76주 재발률, 에스시탈로프람 계속 17% 19%
76주 재발률, 위약 전환 66% 56%
위험비 (위약/약물) 3.83 4.04

급성기 보정은 이 숫자들을 전혀 본 적이 없다. 약을 끊으면 C_pfc가 자기 시간상수 (30 d)를 따라 도로 내려가고, 그것이 두 팔을 갈라놓는다 — 76주 시점 Φ_n 1.14 (계속) 대 1.41 (위약).

3.4 정신적/신체적 하위척도 해리 (Rickels 2005)

Rickels는 유의성 패턴으로 보고했다: 프레가발린은 정신·신체 둘 다 유의, 알프라졸람은 정신만 유의(신체 p = 0.21). 모델은 그 방향을 재현한다 — 위약대비 차의 신체/정신 비가 프레가발린 1.33, 알프라졸람 0.89. S_glu는 근긴장 항목을 직접 먹이지만 I_gaba는 Φ를 통해서만 신체 항목에 닿기 때문이다.


4. 반증된 세 가지 사전 기대 (Three priors the model refuted)

이 저장소의 규칙상, 모델을 만들기 전에 세운 기대가 계산에 의해 무너지면 조용히 지우지 않고 그대로 적는다.

(1) "SSRI 용량반응이 평평한 것은 SERT 점유 쌍곡선 때문이다" — 아니다. 점유율은 확실히 평평해진다 (10 mg 0.744 → 20 mg 0.853, 상대 +15%). 그런데 HAM-A 차는 −2.45 → −4.23로 73% 커진다. 재흡수 항이 바닥에 가까워지면서 세포외 5-HT가 가파르게 오르기 때문이다 (1.98 → 2.62). Baldwin 2006 (PMID 16946363)은 20 mg가 10 mg보다 유의하게 낫지 않다고 보고했는데, 모델은 1.8점의 우위를 예측한다. 임상적 평탄성은 이 모델 안에 없는 무언가(가장 유력하게는 20 mg에서의 탈락)에서 와야 한다.

(2) "병용은 척도 포화 때문에 하위가산(sub-additive)이다" — 반대다. Φ는 세 쌍 모두에서 정확히 곱셈적이다 (오차 −0.4%, −1.2%, −0.7%). 이게 이 섹션의 강한 결과다. 그런데 HAM-A에서는 107%, 115%, 112% — 초가산 (super-additive) 이다. HAM-A 연결함수는 효과가 작을 때 볼록하고 바닥에 가까워져야 오목해지는데, GAD 시험의 3–4점짜리 효과는 볼록 구간에 있다. 따라서 임상적 예측이 뒤집힌다: GAD 병용요법은 단독요법 차의 합을 넘어야 한다.

(3) "Φ가 비(ratio)이므로 중증일수록 약물–위약 차가 커진다" — 상쇄된다. 경증/중등도/중증 3분위에서 차이는 −1.68 / −1.76 / −1.46으로 평평하고 비단조다. 중증 환자는 척도의 더 가파른 곳에 있지만 위약 반응도 함께 크다 (−12.34 대 −8.21). 중증 환자 선별로 검정력을 얻는다는 논리는 이 모델에서 따라 나오지 않는다.


5. 그래도 남는 것 (What survives)

(a) 점유–효과 간극이 계산으로 나온다. SERT는 0.5일만에 절반 차단되고 HAM-A는 35일만에 절반 움직인다 — 70배. 이건 적합된 게 아니라 느린 두 단계의 직렬 연결이다:

단계 t50
SERT 점유 0.5 d
5-HT1A 자가수용체 탈감작 (게이트) 10.5 d
세포외 5-HT 14.5 d
BDNF 23.5 d
C_pfc 40.0 d
HAM-A 35.0 d

같은 점유율(0.574 → 0.744)에서 급성 5-HT 상승은 12.9%, 만성은 98.6%. 게이트가 열려서다. 그래서 발현 곡선이 지수함수가 아니라 S자다.

(b) 다섯 번째 시계는 차이를 줄이지 않는다. 파묻는다. 1주 시점 위약군은 −5.75점 움직이는데 그 위에 얹히는 최대 약물 증분은 −1.75점이다. 개별 환자를 1주에 관찰하는 임상의는 무엇을 처방했든 다섯 번째 시계를 보고 있다. 약물의 시계는 오직 차이에서만 보인다.

(c) 검정 민감도(assay sensitivity)가 유도된다. e_ex만 쓸어보면 (약리는 한 줄도 안 바뀐다):

e_ex 위약 ΔHAM-A esc10 차 pgb300 차 lzp3 차
0.00 −3.85 −1.57 −2.03 −1.75
0.55 −10.09 −2.45 −2.79 −2.91
1.00 −16.95 −3.10 −3.20 −3.17
1.50 −20.03 −0.04 −0.21 −0.09

기대효과가 매우 큰 사이트에서는 약리가 동일한데도 측정 가능한 효과가 사라진다. 기대가 C_pfc를 올리고, C_pfc는 Φ의 분모에 있고, HAM-A는 Φ의 포화함수이기 때문이다. 실패한 다기관 시험의 흔한 사인(死因)이 여기서 가정이 아니라 결과로 나온다.

(d) 벤조디아제핀: 아단위 하나가 두 개의 시계를 만든다. 로라제팜 3 mg/d 지속 투여에서

1일 14일 168일
α1 풀 R_a1 (진정) 0.895 0.380 0.377
α2/3 풀 R_a2 (항불안) 0.999 0.972 0.892

진정은 2주 만에 42% 사라지는데 항불안 풀은 168일에도 0.892다. 이것이 "진정에는 내성이 붙지만 항불안 효과에는 거의 안 붙는다"는 임상 관찰의 아단위 수준 설명이다.

(e) 벤조 브릿지는 준 만큼 돌려받는다. 에스시탈로프람에 로라제팜 3주를 얹으면 1주에 −1.76점을 벌지만, 감량 구간에서 DEPEND가 풀리면서 6주에는 −0.22, 12주에는 −0.01로 수렴한다.


6. 식별 불가능성을 두 번 만났다 (Two identifiability failures, recorded)

이 파일들에는 실패한 시도가 지워지지 않고 남아 있다. gad_calibrate.py의 독스트링과 calib_stage1_joint.log를 보라.

  1. 첫 번째 합동 적합은 위약 1주를 구조적으로 놓쳤다. kfl(등록 시점 평균회귀의 감쇠율)을 손으로 0.075/d에 고정해 두었기 때문이다. 기대효과 항은 WORRY·SLEEPD· AUTON을 거쳐야 하므로 원리적으로 빠를 수 없고, 빠를 수 있는 건 FLUCT뿐인데 그게 묶여 있었다. kfl을 풀자 1주가 맞았다.

  2. 위약 반응의 "실제 하향조절"과 "선택 편향"은 세 개의 요약 숫자로 분리되지 않는다. fluct0, kfl, dvisit을 함께 적합하자 최적화기는 dvisit을 하한 (0.02)으로 밀어붙이고 위약 반응 전체를 가산적 FLUCT 항(9.72점, τ 5.8 d)에 넣어버렸다. 세 숫자만 보면 완벽한 적합이지만, 그렇게 하면 §5(c)의 검정 민감도 논증이 의존하는 생물학적 기대 경로가 조용히 꺼진다. 그래서 dvisit과 e_ex는 적합하지 않고 구조적으로 고정하고, 대신 §5(c)에서 명시적으로 쓸어본다. 이 저장소에서 기대효과 크기에 의존하는 모든 주장은 구조적 선택에 대한 주장이며, 그렇게 표시했다.

kfl은 결국 상한(2.0/d, τ 0.35 d)에 붙었다. 즉 적합은 등록 시점 상승분이 사실상 즉시 사라지기를 원한다 — 실제 증상 변동이라기보다 기저점수 인플레이션 이라는 뜻이다. 이것도 그대로 적어둔다.


7. 구축 중 발견해서 고친 결함 (Defects found and fixed)

Python 참조 구현을 실제로 돌려보지 않았다면 전부 그럴듯한 채로 남았을 것들:

  1. HPA 축이 발산했다. CRH → 코르티솔 → GR 하향조절 → 되먹임 약화 → CRH의 루프 이득이 1을 넘었다. 과잉 코르티솔이 모든 하류 효과에 x/(1+0.5x)로 들어가도록 바꿔 유계로 만들었다.
  2. 질환 루프 전체의 이득도 1을 넘었다. 편도체 → 수면결핍 → 편도체가 발산. Φ의 모든 하류 결과가 phi_n이 아니라 포화 초과항 z = (Φn−1)/(1+(Φn−1)/3)을 읽도록 하고, E_amy에 로지스틱 천장(EAMAX = 3), SLEEPD에 천장(4)을 걸었다.
  3. CBT 창(window)이 서로를 덮어썼다. 한 번의 실행에 CBT 팔이 둘 이상 있으면 나중 것이 앞 것을 끄고 있었다 — "CBT 단독" 팔이 위약과 수치적으로 완전히 동일하게 나와서 발각됐다. 누적으로 고쳤다.
  4. 약효를 절대 변화량에 적합했다. 그 결과 알프라졸람의 총 변화(−10.9)는 정확히 맞추면서 위약대비 차는 두 배 넘게 틀렸다. 위약 모델의 오차를 약물 파라미터가 전부 흡수한 것이다. 차이(difference) 에 적합하도록 바꿨다.
  5. 프레가발린이 점수에 닿는 경로가 둘이었다. 직접 증상완화 항(b_pgb, h_pgb)이 크게 잡혀 있어서 보정이 emax_pgb를 0.029로 밀어버렸다 — 즉 S_glu가 아무 일도 안 하는데 약은 듣는 상태. "S_glu는 프레가발린의 인자"라는 주장이 공허해진다. 직접 경로를 줄이고 구조적 선택임을 명시했다.
  6. 질환 중증도의 눈금이 3분의 1만큼 어긋나 있었다. DIS = 1의 안정 HAM-A가 25.9였는데, 시험이 보고하는 24–27은 등록 시점 점수다. 등록 기준은 변동의 꼭대기를 선별한다. kdis_*를 2.5로 나눠 안정 점수 19.4 / 등록 점수 23.1이 되도록 고쳤다. 가상 집단이 없었으면 못 봤을 오류다.

8. 수치 검증 (Verification)

  • 적분기: 손으로 쓴 RK4(dt = 30분, 피험자에 대해 벡터화)를 scipy LSODA (rtol 1e-9)와 대조 — 7일간 에스시탈로프람 10 mg QD + 프레가발린 300 mg BID 이후 HAM-A 상대오차 1.3e-06, 최악의 상태변수 1.1e-03(감쇠 중인 흡수 구획).
  • 스텝 크기: dt를 절반(1/96 d)으로 줄여도 HAM-A는 2.0e-05만 움직인다.
  • 어트랙터: 무투약 평형점은 dt = 1/8, 1/12, 1/24에서 소수점 4자리까지 동일 (평형점은 RK4 사상의 고정점이므로 스텝에 무관).
  • mrgsolve 이식: $MAIN의 초기조건은 참조 구현의 어트랙터를 DIS의 3차식으로 적합한 것이며 최대 상대오차 5.7e-03(SLEEPD). 생성기(mkmrgsolve.py)가 보정값과 초기조건을 함께 써넣으므로 두 구현이 어긋날 수 없다.

정직한 한계 하나: 이 환경에 R 툴체인이 없어서 gad_mrgsolve_model.R과 gad_shiny_app.R은 실행되지 않았다. R 파일은 Python 참조 구현을 식 단위로 대조해 작성했으나 그 자체로 검증되지는 않았다. 또한 mrgsolve에는 방문 시점의 이산적 기대효과 갱신을 도즈로 표현할 방법이 없어, 빠르게 감쇠하는 VISCUE 구획 (kvis = 48/d)으로 같은 사상을 근사했다 — 헤더에 명시했다.


9. 모델 구조 (Structure)

49개 ODE (mrgsolve에서는 VISCUE 포함 50 구획):

블록 상태변수
PK (20) 에스시탈로프람 2구획+효과부위, 벤라팍신+ODV, 둘록세틴, 프레가발린, 벤조디아제핀+효과부위, 부스피론+1-PP, 케티아핀+노르케티아핀
신경전달 (4) SHT, AUTO(5-HT1A 자가수용체), NE, A2AUTO
가소성·회로 (4) BDNF, CPFC, EAMY, TRAF(α2δ 수송)
GABA-A (3) RA1(진정, τ 2.6 d), RA2(항불안, τ 42 d), DEPEND(적응, τ 20 d)
HPA (4) CRH, ACTH, CORT, GR
증상층 (4) SNS, AUTON, SLEEPD, WORRY
시험 기계장치 (2) EXPECT, FLUCT
이상반응 (6) RNAU, RDIZZ, RH1, SEXD, WT, RACT
동반질환·위험 (2) MADRSS, CUMHAZ

측정으로 고정한 상수 (적합하지 않음):

상수 값 출처
에스시탈로프람 SERT EC50 5 ng/mL (10 mg에서 점유 0.80) PET/TDM (PMID 38287888, 27557550)
벤라팍신 NET EC50 260 ng/mL → 75–225 mg에서 점유 0.21–0.44 Arakawa 2019, 측정 8–61% (PMID 30649319)
벤조 결합부위 EC50 96 ng/mL 로라제팜 등가 → 항불안 용량에서 점유 ~20% Atack 2007 [¹¹C]플루마제닐 (PMID 17164474)
프레가발린 t½ / 신장 청소 6.3 h / CrCl 비례 PMID 17940637, 12638396
α1 = 진정, α2/3 = 항불안, α5 = 진정 내성 구조 knock-in 연구 (PMID 15282283)

시나리오 17개가 gad_reference_output.txt에 있다: 무투약 자연경과 · 네 시계 비교 · Rickels 4주 5팔 · Khan 8주 4팔 · 용량반응 스윕(에스시탈로프람 4용량, 벤라팍신 3용량 × CYP2D6 3표현형, 둘록세틴 2용량, 부스피론) · 위약/기대효과 스윕 · 벤조 12주 후 급중단 vs 4주 감량 vs 지속 · 병용 3쌍 · 벤조 브릿지 · CBT 단독/병용 · 가상 집단 6팔 (n = 200, 탈락·LOCF) · Allgulander 무작위 중단 (n = 260 → 169×2, 76주) · 신기능/CYP2D6/복약순응도 · 적분기 검증.


10. Shiny 대시보드 (12 탭)

환자·처방 → PK/점유율 → 네 인자 → 네 시계 → 임상 종말점 → 시험 시뮬레이터 → 시나리오 비교 → 용량반응 → 벤조디아제핀(내성·반동) → 이상반응 → 검정 민감도 스윕 → 재발 예방. 각 탭은 위 §3–§5의 계산을 대화형으로 다시 만들도록 짜여 있다.


11. 참고문헌

gad_references.md — 118개 항목 / 113개 고유 PMID, 20개 섹션. 모든 제목·저널·연도·저자·PMID는 mkrefs.py가 NCBI esearch + esummary로 실시간 조회한 것이며 기억에서 쓴 것이 아니다. 각 항목에는 모델이 그 논문에서 무엇을 가져왔는지(intent) 가 함께 적혀 있어서, 검색이 의도와 다른 논문을 집어온 경우 한눈에 보이게 했다(전부 맞지는 않는다 — 그것이 이 표기의 목적이다).

⚠️ E-utilities의 기본 정렬은 관련도가 아니라 날짜다. sort=relevance를 빼면 "불안과 심혈관 위험"에 2026년 탈모 메타분석이 걸린다. 실제로 첫 빌드에서 그렇게 됐고, mkrefs.py에 그 사고 기록과 함께 주석으로 남겼다.


⚠️ 면책 (Disclaimer)

교육·연구 목적의 QSP 모델입니다. 공개 문헌과 임상시험 데이터를 바탕으로 구성했으나 독립적으로 검증·인증되지 않았으며, 실제 임상 의사결정, 처방, 또는 규제 제출에 직접 사용해서는 안 됩니다. 특히 §3.2(케티아핀), §4(반증된 사전 기대), §6(식별 불가능성), §8(R 코드 미실행)에 적힌 한계를 읽지 않고 이 모델의 숫자를 인용하지 마십시오.