무엇을 하려는 연구인가
기계학습을 이용한 개인 맞춤 의료에서 관심을 끄는 것은 치료 효과를 높이면서 위험한 처방의 가능성을 줄이는 일이다. 전자의무기록이 쌓이면서 나이, 성별, 임상 이력, 검사 결과 같은 환자별 정보로 처방을 최적화할 기회가 생겼다.
랜덤포레스트, XGBoost, 서포트 벡터 머신 같은 알고리즘이 관습적 접근보다 높은 예측 정확도를 보인다는 보고가 이어졌다. 약물 분류와 표적 예측을 돕는 연구도, 약물 안전성 분류에 기계학습을 쓴 연구도 있다.
원저자들의 진단은 이렇다. 기존 연구들은 환자 데이터의 한 측면이나 특정 약물 계열에만 집중했고, 총체적 약물 추천 모형을 위해 임상·인구학·검사 데이터를 두루 통합하지 못했다.
그래서 이 연구는 로지스틱 회귀, 결정트리, 랜덤포레스트, SVM, XGBoost를 임상·인구학·검사 데이터에 함께 적용한다. 다만 뒤에서 보겠지만, 실제로 쓴 데이터는 변수 여섯 개다.
데이터
2.4.3 어느 변수가 약과 관련되는가
| 변수 쌍 | 상관 | 계수 | 해석 |
|---|---|---|---|
| Na_to_K – Drug | 0.59 | 가장 강하다. 심혈관 건강과 연결된 핵심 예측 변수다 | |
| BP – Na_to_K | 0.37 | 상호작용 가능성. 랜덤포레스트 같은 모형에 유리하다 | |
| BP – Drug | 0.33 | 중간 정도. 혈압이 약물 선택에 영향을 준다 | |
| Sex – Drug | 0.099 | 매우 낮다 | |
| Cholesterol – Drug | 0.056 | 약하다. 직접적 영향이 거의 없다 | |
| Age – Drug | 0.048 | 매우 낮다. 단독으로는 예측력이 없다 |
원문 2.3절은 이렇게 적는다. “이 약물 분류는 혈압, 콜레스테롤, 나트륨–칼륨 비율 같은 요인의 조합에 근거한다.”
즉 예측 대상이 독립적인 임상 결과가 아니라 같은 변수들에서 파생된 값이라는 뜻이다. 그렇다면 이 과제는 ‘환자의 반응을 예측하는 일’보다 데이터를 만든 규칙을 되찾는 일에 가깝다. Na_to_K가 상관 0.59로 압도적인 것도 그렇게 보면 자연스럽다.
이 점이 성능 수치를 읽는 방식을 바꾼다. 90퍼센트 정확도는 임상 예측의 성취가 아니라 규칙 복원의 성취일 수 있다. 원저자들도 이 데이터셋을 “개념 증명”으로 규정하고 일반화 가능성의 한계를 인정한다.
전처리와 검증 설계
- 결측값 — 없었다. 대치나 삭제가 필요하지 않았다.
- 범주형 인코딩 — 라벨 인코딩을 썼다. 성별은 M=1, F=0. 혈압과 콜레스테롤은 LOW/NORMAL/HIGH를 0/1/2로. 표적인 약물도 0–4로 부호화했다. 원문은 순서 관계를 가정하지 않도록 원핫 인코딩도 고려했으나, 데이터셋이 작고 범주 구분이 명확해 라벨 인코딩으로 충분하다고 판단했다고 적는다.
- 스케일링 — 수치형인 Age와 Na_to_K에
StandardScaler를 적용해 평균 0, 표준편차 1로 z점수 정규화했다. - 클래스 불균형 — 다루지 않았다. SMOTE, 무작위 언더샘플링, 클래스 가중치를 소개하되 “데이터의 자연스러운 분포를 보존하기 위해” 원래의 불균형을 유지했다고 밝힌다.
- 하이퍼파라미터 — 튜닝하지 않았다.
격자 탐색이나 무작위 탐색을 쓰지 않고
scikit-learn(XGBoost는 자체 파이썬 API)의 기본값을 그대로 썼다. 매개변수 최적화의 영향을 배제한 공정한 기준선 비교가 목적이다.
원문 4.1절은 5겹 층화 교차검증을 썼다고 적는다. 데이터를 다섯 등분해 네 개로 학습하고 하나로 시험하는 방식이니 시험 집합은 20퍼센트다.
그런데 5절은 “각 폴드에서 데이터의 70퍼센트로 학습하고 나머지 30퍼센트로 시험했다”고 적는다. 5겹 교차검증과 70대 30 분할은 서로 다른 절차다.
그리고 뒤에 나올 분류 보고서들의 지지도(support) 합계는 5+3+3+11+18 = 40이다. 200명의 20퍼센트다. 20퍼센트라는 숫자는 5겹 교차검증과 맞고 ‘30퍼센트’와는 맞지 않는다. 또한 지지도 40은 한 번의 분할에서 나온 수치이지 다섯 폴드의 평균이 아니다.
정리하면, 표 13.3의 종합 지표는 5겹 평균이라고 적혀 있고 표 13.4–13.8의 클래스별 보고서는 한 번의 분할처럼 보인다. 둘의 관계가 원문에 설명되어 있지 않다.
점수판
다섯 모형을 네 지표로 비교한다. 정확도, 정밀도, 재현율, F1이다. 원문도 지적하듯 정확도는 클래스 불균형 앞에서 오해를 부른다. drugY가 전체의 절반 가까이인데 drugB와 drugC는 8퍼센트씩이므로, 대부분을 다수 클래스로 몰아넣기만 해도 정확도는 높게 나온다.
5.2 모형별로 무엇이 달랐나
- XGBoost — 모든 지표에서 가장 좋았다. 정확도 0.900, 정밀도 0.916, 재현율 0.900, F1 0.892. 클래스 0(drugA)에서 완벽했고 클래스 3, 4에서도 높은 F1을 냈다. 다만 클래스 1(drugB)에서 F1 0.50, 낮은 재현율을 보였다.
- 결정트리 — 정밀도가 가장 높았다(0.932). 잘못된 예측을 줄인다는 뜻이다. 그런데 F1은 0.859로 XGBoost보다 낮다. 클래스 3(drugX)에서 재현율이 0.55로 떨어지고, 클래스 2는 재현율 1.00인데 정밀도가 0.38이다.
- 랜덤포레스트 — 균형 잡힌 성능(정확도 0.875, F1 0.834)을 보였지만 클래스 1에서 F1 0.50, 클래스 2에서는 F1 0.00이다.
- 로지스틱 회귀 — 기준선으로서 무난하다(정확도 0.825, F1 0.801). 클래스 0, 1, 3, 4에서는 잘하지만 클래스 2에서 완전히 실패한다.
- SVM — 가장 나쁘다. 정확도 0.675, F1 0.580. 다섯 클래스 중 셋(0, 1, 2)에서 F1이 0이다. 사실상 drugX와 drugY 두 클래스만 예측한다.
5.3 혼동행렬
최고 성능 모형인 XGBoost의 혼동행렬을 보면 drugA 5개, drugB 1개, drugC 2개, drugX 11개, drugY 17개를 맞혔다. 오분류 가운데 drugC 두 개가 drugB로 예측된 사례가 있다.
원문은 이어서 “랜덤포레스트는 drugA 5개, drugB 1개, drugC 3개, drugX 11개, drugY 18개를 맞혔다”고 적는다.
그런데 랜덤포레스트의 분류 보고서(표 13.4)는 클래스 2(drugC)의 재현율을 0.00으로 적는다. 지지도가 3인데 재현율이 0이면 맞힌 것은 0개다. ‘세 개를 맞혔다’는 서술과 정면으로 어긋난다.
XGBoost 쪽은 표와 정확히 맞는다. 재현율 × 지지도를 계산하면 5, 1, 2, 11, 17로 본문 서술과 일치한다. 랜덤포레스트 한 문장만 어긋난 것으로 보인다.
5.5절은 “결정트리는 정밀도가 높다(표 13.5)”고 적지만 표 13.5는 로지스틱 회귀의 보고서다. “랜덤포레스트는 견고하다(표 13.6)”고 하지만 표 13.6은 결정트리다. “SVM은 잘 작동하지 않는다(표 13.7)”고 하지만 표 13.7은 XGBoost다.
표 자체의 내용은 정확하다. 5.2절의 클래스별 서술과 표를 대조해 보면 모두 맞는다. 어긋난 것은 5.5절의 상호 참조뿐이다. 이 정리본의 점수판은 표의 실제 내용을 기준으로 만들었다.
어느 변수가 결정했나
모형의 해석가능성을 높이고 입력 변수의 임상적 관련성을 확인하기 위해 랜덤포레스트와 XGBoost의 특징 중요도를 계산했다. 두 모형이 성능이 좋았고, 특징 기여도에 대한 내재적 추정값을 제공하기 때문이다. 로지스틱 회귀와 SVM은 특히 비선형 상호작용에 대해 직접적인 특징 중요도를 주지 않는다.
랜덤포레스트는 Na_to_K(0.547)를 압도적 1위로, XGBoost는 혈압(0.407)을 1위로 놓는다. 콜레스테롤도 랜덤포레스트에서는 0.046으로 거의 무시되지만 XGBoost에서는 0.200으로 3위다.
원문은 “Na_to_K와 BP가 가장 중요한 속성”이라고 둘을 묶어 요약한다. 틀린 요약은 아니다. 다만 두 모형이 서로 다른 순위를 낸다는 사실 자체가 중요한 정보인데 그 점은 짚히지 않는다.
상관 분석(0.59 대 0.33)은 Na_to_K 쪽 손을 들어 준다. 모형이 다르면 ‘어느 변수가 결정했는가’라는 질문의 답도 달라진다는 것을 이 대목이 우연히 보여 준다.
원문은 특징 중요도 외에 SHAP과 LIME 같은 도구로 설명가능성을 높일 수 있다고 덧붙인다. SHAP은 각 예측에 대한 특징 기여도를 단일 수치로 주고, LIME은 해석 가능한 대리 모형으로 국소적으로 근사해 개별 예측을 설명한다. 임상 환경에서 의료진이 모형의 약물 추천을 해석하고 믿을 수 있게 하는 데 값진 방법이라는 것이 원문의 평가다.
한계와 향후 과제
원저자들이 꼽는 한계는 넷이다. 작은 데이터셋 크기, 약물 범주의 불균형, 중년에 편중된 연령 분포, 그리고 SVM의 낮은 성능이 시사하는 전처리 절차의 개선 필요다.
향후 과제로 제시된 것
- 더 큰 데이터셋 — 실제 건강 상태의 다양성을 담아 예측을 정확하게 만든다.
- 오버샘플링과 SMOTE — 약물 집단별 환자 수의 균형을 맞춰 drugB와 drugC 같은 드문 약물의 예측을 개선한다.
- 모형 튜닝 — 커널이나 정규화 매개변수를 조정한다.
- 추가 환자 정보 — 생활 습관이나 병력 같은 정보를 더한다.
- 그래프 신경망 — 비유클리드 데이터를 표현할 수 있으므로 환자 특징과 약물 반응 사이의 복잡한 연관을 기술하는 데 적합하다.
이 장이 남기는 것
XGBoost의 정확도 0.900과 drugB 재현율 0.33은 같은 모형의 성적이다. 클래스별 보고서를 보지 않으면 뒤의 숫자는 보이지 않는다. 원문이 F1을 정확도보다 선호한다고 명시한 것도 그래서다.
SVM은 다섯 클래스 중 셋에서 F1이 0이다. 감추지 않고 표에 그대로 실었다. 0.00이라는 숫자가 표에 적혀 있는 논문은 흔하지 않다.
모든 모형을 기본 설정으로 돌린 것은 공정한 기준선 비교를 위해서다. 타당한 선택이다. 다만 그렇다면 결론은 ‘XGBoost가 최고’가 아니라 ‘기본 설정에서 XGBoost가 최고’여야 한다.
5겹 교차검증과 “70대 30 분할”이 함께 적혀 있고, 랜덤포레스트 혼동행렬 서술이 표 13.4와 어긋나고, 5.5절의 표 참조가 밀려 있다. 표를 직접 보는 편이 안전하다.
이 장은 이 책에서 가장 작은 연구다. 환자 200명, 변수 여섯 개, 공개 데이터셋 하나. 앞선 장들이 인용한 논문 하나의 각주만도 못한 규모다.
그런데 이 책에서 가장 검증하기 쉬운 장이기도 하다. 데이터의 출처가 밝혀져 있고, 전처리 절차가 적혀 있고, 다섯 모형의 네 지표가 소수점 여섯 자리까지 실려 있고, 클래스별 정밀도·재현율·F1·지지도가 다섯 개의 표로 나와 있다. 그래서 앞의 판단 블록에서 지적한 불일치들을 읽는 사람이 직접 찾아낼 수 있다. 앞선 열두 장에서는 대개 그럴 수 없었다.
가장 중요한 대목은 5.1절의 한 문단이라고 본다. “정확도는 클래스 불균형 앞에서 오해를 부른다”는 지적, 그리고 그 지적을 자기 결과에 그대로 적용해 클래스별 보고서를 다섯 개 다 실은 것. 이 책의 여러 장이 90퍼센트, 95퍼센트, 98퍼센트 같은 숫자를 인용했다. 그 숫자들 뒤에 이런 표가 있었는지는 대부분 알 수 없다.
규모가 작다는 것과 정직하다는 것은 다른 문제다. 이 장은 규모가 작고, 결론도 소박하고, 편집에 어긋난 곳이 있다. 그래도 0.00을 표에 적어 넣었다. 그 점은 기억해 둘 만하다.