#오즈코딩스쿨 AI 헬스케어 해커톤 Last Day

Kyul Lee·2026년 3월 19일

포트폴리오

목록 보기
6/6

[해커톤 회고] 난임 환자 임신 성공 여부 예측 AI — 전체 과정 총정리

🏥 DACON 난임 환자 임신 성공 여부 예측 AI 해커톤
Team Beemo | 평가지표: ROC-AUC | 최고 LB: 0.74216


들어가며

해커톤이 끝났다. 5일 동안 밤을 새워가며 실험하고, 실패하고, 다시 시도했다.
이 글은 그 과정 전체를 솔직하게 기록한 회고다.

점수 자체보다 어떻게 실험했고, 무엇이 먹혔고, 무엇이 실패했는지를 중심으로 썼다.


데이터 개요

train: 256,351행 × 69열
test:  90,067행 × 68열
타겟:  임신 성공 여부 (25.83% 불균형)

의료 데이터라서 단순 분류 문제가 아니었다. 결측치의 의미, 범주의 맥락, 시술 유형에 따라 달라지는 변수 해석이 모델링만큼 중요했다.


전체 실험 결과 요약

버전CV AUCLB AUC핵심 변경
v30.740600.74198Target Encoding + 도메인 피처
v50.740620.74198클리닉 집계 피처 (K-Fold OOF)
v80.740670.74195미사용 컬럼 발굴 + LGB Optuna
v8_tuned0.740730.74200XGB/CatBoost Optuna 추가
blend v5+v80.7420550:50 블렌딩
v8plus_v7b0.740830.74216고령×단일배아이식 + Rank Norm ⭐
vclean70.73184Clean Baseline + 시간간격 피처
vclean120.73999feature_search 상위 피처

핵심 발견 1 — 시간 간격 피처가 가장 큰 점프를 만들었다

df['혼합_이식_간격'] = df['배아 이식 경과일'] - df['난자 혼합 경과일']
df['해동_이식_간격'] = df['배아 이식 경과일'] - df['배아 해동 경과일']

Clean Baseline 실험에서 이 두 피처를 추가했을 때 CV가 0.72509 → 0.73184로 +0.00675 점프했다.

이유가 뭔가 생각해보면, 혼합에서 이식까지의 간격이 길수록 배아가 5일 이상 배양된 배반포라는 뜻이다. 배반포까지 살아남은 배아는 품질이 좋다는 의학적 사실이 데이터에 고스란히 담겨있었다.


핵심 발견 2 — EDA 도메인 인사이트

데이터를 깊이 분석하면서 강력한 신호들을 발견했다.

조건임신 성공률전체 평균 대비
SET × BLASTOCYST 명시43.6%+17.8%p
Day5 × 이식 1개42.1%+16.3%p
단일 배아 이식(SET)36.6%+10.8%p
":" 포함 시술 유형7.8%-18%p (폭락)
배아 저장/기증 목적0~0.1%-25%p (사실상 실패)

특히 배아 목적이 저장/기증이면 성공률이 거의 0% 라는 발견이 강력했다. 임신을 목적으로 하지 않는 시술이니 당연한 결과였다.

이 인사이트에서 나온 피처가 v7b의 핵심이다.

# 고령 환자가 단일 배아 이식을 선택했다 = 의사가 좋은 배아라고 판단한 신호
df['고령_x_단일배아이식'] = df['고령_여부'] * df['단일 배아 이식 여부']

핵심 발견 3 — 시술 시기 코드는 단순 ID가 아니다

TRCMWS, TRDQAZ 같은 암호화된 코드가 데이터에 있었다. 처음엔 그냥 ID인 줄 알았는데, 이걸 Target Encoding으로 수치화하자마자 모델의 최상단 분기점으로 올라왔다.

어느 병원에서, 어느 시기에 시술받았는지가 임신 성공률에 엄청난 영향을 미친다는 의학적 사실을 반영하는 proxy 변수였다.

# 클리닉별 성공률
train['시술시기코드_성공률'] = OOF_target_encode('시술 시기 코드')

# 클리닉 × 나이 조합
train['클리닉_나이별성공률'] = OOF_target_encode('클리닉_나이조합')

# 클리닉 × 시술유형 조합
train['클리닉_시술유형별성공률'] = OOF_target_encode('클리닉_시술유형조합')

# 클리닉 × 난자출처 × 정자출처 (3중 조합)
train['시술시기코드_난자정자조합_te'] = OOF_target_encode('시술시기코드_난자정자조합')

핵심 발견 4 — feature_search 자동화

처음엔 피처를 하나씩 수동으로 추가하고 CV를 확인했다. 비효율적이었다. 그래서 자동화 스크립트를 만들었다.

for feat, desc in CANDIDATE_FEATURES.items():
    cv    = measure_cv(BASE_FEATURES + [feat], y)
    delta = cv - base_cv
    print(f'{feat}: {delta:+.5f}')

이 스크립트로 후보 피처 40개 이상을 한 번에 측정했다. 결과:

✅ 배아_저장비율      +0.00558 ← 압도적
✅ 배아_활용률        +0.00551
✅ 난자기증자_나이_수치 +0.00068 ← 3등팀 핵심 피처
✅ 단일 배아 이식 여부 +0.00028

❌ 클리닉_나이별성공률  -0.00018
❌ 미세주입_이식률      -0.00019

직관으로 좋아 보였던 피처가 실제로는 음수 기여를 하는 경우가 많았다. 자동화 없이는 알 수 없었을 것들이었다.


핵심 발견 5 — 블렌딩은 상관관계 확인이 먼저다

블렌딩하면 무조건 좋아진다고 생각했다. 아니었다.

v5 × v8:               0.9986  (효과 거의 없음)
v5 × v8_tuned:         0.9982  (효과 거의 없음)
blend_50 × autogluon:  0.9979  (효과 거의 없음)
blend_50 × vclean7:    0.9577  ← 유일하게 낮음

같은 피처셋 기반 모델들은 상관관계가 0.998 이상이라서 블렌딩해도 평균을 내는 것에 불과했다. 진짜 다양성은 완전히 다른 피처셋에서 나온다는 걸 배웠다.


Rank Normalization — 숨겨진 강자

앙상블 방법 중 가장 효과적이었던 건 Rank Normalization이었다.

# 확률값 대신 순위값으로 정규화
r_lgb = rankdata(oof_lgb) / len(oof_lgb)
r_xgb = rankdata(oof_xgb) / len(oof_xgb)
r_cat = rankdata(oof_cat) / len(oof_cat)
ensemble = (r_lgb + r_xgb + r_cat) / 3

각 모델의 score 분포 차이를 제거하고 상대적 순서만 반영하는 방식이다. LB에서 +0.00126 효과를 확인했다.


실패 교훈

풀 스태킹 (CV 0.73481 폭락)

3개 모델의 OOF + 원본 피처 135개를 메타 모델에 전부 넣었다. 오버피팅이 일어나서 CV가 0.74 → 0.73481로 폭락했다. 메타 피처는 OOF 예측값만 사용해야 한다는 걸 배웠다.

Pseudo-Labeling (규정 위반)

test 데이터를 학습에 활용하는 방식이다. 멘토링에서 알게 됐는데 규정 위반으로 실격이다. 절대 사용 금지.

GPU 사용

25만행 규모에서 GPU가 더 빠를 것이라고 생각했다. 오히려 CPU보다 느리고 정확도도 낮았다. GPU는 수백만 행 이상에서 효과가 있다.

피처 183개로 확장

더 많은 피처가 좋다고 생각했다. 노이즈가 증가해서 CV가 오히려 낮아졌다. 피처 수보다 피처 품질이 중요하다.


최종 결론

5일 동안 실험하면서 얻은 가장 중요한 인사이트 세 가지다.

1. 데이터 해석이 모델보다 중요했다

EDA에서 발견한 의학 도메인 인사이트가 가장 큰 성능 향상을 만들었다. Day5 배반포, 저장/기증 목적 구분, 시술 시기 코드 조합 — 이것들이 핵심이었다.

2. 검증 가능한 단일 변경이 대규모 변경보다 잘 먹혔다

feature_search 자동화로 후보 피처를 체계적으로 검증했다. 기준선을 고정하고 하나씩 추가하는 방식이 가장 안정적이었다.

3. 블렌딩은 다양성이 전제되어야 효과가 있다

상관관계 0.998 이상인 모델끼리 블렌딩은 의미 없다. 진짜 다양성은 다른 피처셋 또는 다른 알고리즘에서 나온다.


"복잡한 기법보다, 데이터의 의미를 해석하고 검증 가능한 단일 변경을 쌓는 것이 핵심이었습니다."


📎 GitHub: https://github.com/Beemo-4018/infertility-prediction-ai

2개의 댓글

comment-user-thumbnail
2026년 4월 21일

꾸준히 블로그 작성하신 내용 잘 읽어보았습니다.
오즈코딩 헬스케어 과정 괜찮은가요?

1개의 답글