들어가며: 1번은 반드시 만점을 받아야 합니다
AICE Professional 시험의 1번 Tabular 문제는 회귀, 다중 분류, 그리고 이진 분류(Binary Classification) 중 하나가 출제됩니다. 이전 글에서 회귀와 다중 분류를 다뤘으니, 이번에는 이진 분류 유형을 정리합니다.
저는 1, 2번을 만점으로 통과했지만 3번 Image 문제에서 불합격한 경험이 있습니다. 1번은 세 문제 중 가장 접근하기 쉬운 문제이므로, 어떤 유형이 나와도 확실하게 30점을 확보하는 것이 합격의 기본 전략입니다.
AICE Professional 시험 구조 (복습)
| 문제 | 유형 | 배점 |
|---|---|---|
| 1번 | Tabular (정형 데이터) | 30점 |
| 2번 | Text (텍스트 데이터) | 35점 |
| 3번 | Image (이미지 데이터) | 35점 |
합격 기준은 80점 이상입니다. 한 문제라도 완전히 틀리면 사실상 불합격이므로, 1번에서 30점을 확실히 가져가야 합니다.
1번 문제: Tabular 이진 분류 — 출제 유형 분석
예상 문제 형태
약 10개 내외의 수치형 피처(age, bmi, ldl, hdl, tg, sbp, dbp, fbs, alt, ast 등)가 주어지고, 이를 기반으로 **1년 내 발병 위험 여부(0 또는 1)**를 예측하는 이진 분류 문제가 출제됩니다.
핵심 포인트는 다음과 같습니다.
- 모든 피처가 수치형이라 복잡한 전처리가 필요 없습니다
- target이 0/1 정수이므로 LabelEncoder도 불필요합니다
- 평가 지표는 Accuracy, ROC-AUC, F1-score 중 하나 이상이 제시됩니다
이진 분류는 다중 분류보다 단순하고, 회귀와 코드 구조도 거의 비슷합니다. 1번 유형 중에서는 가장 무난하게 풀 수 있는 유형입니다.
1번 문제 유형별 비교 — 한눈에 보기
시험장에서 데이터를 열었을 때, target 컬럼만 보면 어떤 유형인지 바로 판단할 수 있습니다.
| 항목 | 회귀 | 이진 분류 | 다중 분류 |
|---|---|---|---|
| target 형태 | 연속 수치 | 0 또는 1 | 3개 이상 범주 |
| 모델 | RandomForestRegressor | RandomForestClassifier | RandomForestClassifier |
| 평가 지표 | RMSE | Accuracy, ROC-AUC, F1 | Accuracy, F1 (macro) |
| LabelEncoder | 불필요 | 불필요 | 필요 (문자열 라벨 시) |
| 예측 후처리 | 수치 그대로 | 0/1 그대로 | inverse_transform 필요 |
풀이 전략: 6단계 접근법
Step 1. 데이터 로드 및 기본 설정
python
import pandas as pd
import numpy as np
from pathlib import Path
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import (
accuracy_score, roc_auc_score, f1_score,
classification_report, confusion_matrix
)
import joblib
# ── 경로 설정 ──
DATA_DIR = Path('/content/drive/MyDrive/Colab Notebooks/data')
TRAIN_CSV = DATA_DIR / '01_train.csv'
TEST_CSV = DATA_DIR / '01_test_x.csv'
# ── 제출 파일 설정 ──
PHONE = '01012345678' # 본인 전화번호로 변경
OUT_CSV = DATA_DIR / f'{PHONE}_1.csv'
OUT_PKL = DATA_DIR / f'{PHONE}_1.pkl'
TARGET_COL = 'label' # 문제에서 제시하는 타겟 컬럼명으로 변경
ID_COL = 'id'
# ── 데이터 로드 ──
train = pd.read_csv(TRAIN_CSV)
test = pd.read_csv(TEST_CSV)
Step 2. 전처리 — 이진 분류는 가장 간단합니다
python
# X, y 분리
y = train[TARGET_COL].values # 이미 0/1 정수 → LabelEncoder 불필요
X = train.drop(columns=[TARGET_COL])
# 결측치 안전장치
if X.isnull().any().any():
X = X.fillna(X.mean(numeric_only=True))
if test.isnull().any().any():
test = test.fillna(test.mean(numeric_only=True))
다중 분류에서는 LabelEncoder가 필요했지만, 이진 분류에서는 target이 이미 0과 1이므로 별도의 라벨 인코딩 없이 바로 사용할 수 있습니다. 전처리가 사실상 결측치 확인뿐이라, 가장 빠르게 모델 학습으로 넘어갈 수 있는 유형입니다.
Step 3. 검증 데이터 분리
python
X_tr, X_va, y_tr, y_va = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y
)
이진 분류에서도 stratify=y는 필수입니다. 특히 양성(1)과 음성(0)의 비율이 불균형한 경우, stratify 없이 분리하면 검증 세트의 클래스 비율이 왜곡되어 평가 지표가 부정확해집니다.
Step 4. 모델 학습 및 검증
python
clf = RandomForestClassifier(
n_estimators=500,
max_depth=None,
min_samples_leaf=2,
n_jobs=-1,
random_state=42
)
# 학습
clf.fit(X_tr, y_tr)
# 예측
va_pred = clf.predict(X_va)
va_proba = clf.predict_proba(X_va)[:, 1] # 양성 클래스(1)의 확률
# ── 평가 지표 ──
acc = accuracy_score(y_va, va_pred)
auc = roc_auc_score(y_va, va_proba)
f1 = f1_score(y_va, va_pred)
print(f'Validation Accuracy: {acc:.4f}')
print(f'Validation ROC-AUC : {auc:.4f}')
print(f'Validation F1 : {f1:.4f}')
# 상세 리포트
print('\nClassification Report:\n', classification_report(y_va, va_pred))
print('Confusion Matrix:\n', confusion_matrix(y_va, va_pred))
이진 분류에서 꼭 알아야 할 지표 세 가지를 정리합니다.
| 지표 | 계산 방식 | 핵심 포인트 |
|---|---|---|
| Accuracy | 전체 정답 비율 | 클래스 균형 시 유효, 불균형 시 과대평가 가능 |
| ROC-AUC | 확률 기반 평가 | predict_proba()[:, 1]로 양성 확률 필요 |
| F1-score | 정밀도와 재현율의 조화평균 | 불균형 데이터에서 Accuracy보다 신뢰도 높음 |
ROC-AUC 계산 시 주의: predict_proba()는 [음성 확률, 양성 확률] 두 컬럼을 반환합니다. ROC-AUC에는 **양성 클래스(1)의 확률인 [:, 1]**을 넘겨야 합니다. 이걸 [:, 0]으로 잘못 넣으면 AUC가 뒤집힌 값이 나옵니다.
Step 5. 최종 학습 및 테스트 예측
python
# 전체 데이터로 최종 학습
clf.fit(X, y)
# 테스트 예측
test_pred = clf.predict(test)
검증에서 목표 지표를 통과했다면, 전체 학습 데이터(train + validation)로 다시 학습한 뒤 테스트 예측을 수행합니다. 이렇게 하면 20%의 데이터를 추가로 활용하게 되어 최종 예측 성능이 소폭 향상됩니다.
이진 분류에서는 예측 결과가 이미 0과 1이므로, 다중 분류처럼 inverse_transform()을 할 필요가 없습니다. 그대로 제출하면 됩니다.
Step 6. 제출 파일 저장
python
# CSV 저장
if ID_COL in test.columns:
sub = pd.DataFrame({ID_COL: test[ID_COL], TARGET_COL: test_pred})
else:
sub = pd.DataFrame({'id': np.arange(len(test)), TARGET_COL: test_pred})
sub.to_csv(OUT_CSV, index=False)
print(f'Wrote: {OUT_CSV}')
# 모델 저장
joblib.dump(clf, OUT_PKL)
print(f'Wrote: {OUT_PKL}')
주의: 문제에 따라 제출 라벨이 0/1 정수인지, 클래스명 문자열(예: ‘yes’/’no’)인지 다를 수 있습니다. 문자열이 요구되면 매핑을 추가하세요:
test_pred_lbl = ['yes' if p == 1 else 'no' for p in test_pred]
성능이 안 나올 때 — 간단 튜닝 가이드
| 우선순위 | 조정 항목 | 방법 | 기대 효과 |
|---|---|---|---|
| 1 | n_estimators | 500 → 800 → 1000 | 트리 수 증가로 안정성 향상 |
| 2 | min_samples_leaf | 2 → 1 → 4 | 과적합/과소적합 균형 |
| 3 | max_depth | None → 20 → 12 | 트리 깊이 제한으로 일반화 |
| 4 | class_weight | 'balanced' 추가 | 클래스 불균형 대응 |
| 5 | max_features | 1.0 → 0.7 → ‘sqrt’ | 변수 비율 축소로 다양성 확보 |
이진 분류에서 특히 효과적인 것은 class_weight='balanced'입니다. 질병 예측 같은 문제에서는 양성(발병) 샘플이 음성보다 적은 경우가 많은데, 이 옵션 하나로 F1-score가 크게 개선될 수 있습니다.
python
clf = RandomForestClassifier(
n_estimators=500,
max_depth=None,
min_samples_leaf=2,
class_weight='balanced', # 불균형 대응
n_jobs=-1,
random_state=42
)
실전 체크리스트
시험장에서 제출 전, 이 순서대로 확인하세요.
- target 컬럼이 0/1인지 확인했는가? (문자열이면 다중 분류 코드로 전환)
train_test_split에stratify=y를 넣었는가?- 검증 Accuracy / ROC-AUC / F1이 문제 기준을 충족하는가?
- ROC-AUC 계산 시
predict_proba()[:, 1]을 사용했는가? - 최종 학습은 전체 데이터로 했는가?
- 제출 CSV의 라벨이 문제 요구 포맷(정수 or 문자열)과 일치하는가?
- 제출 CSV의 컬럼명(id, label)이 정확한가?
- pkl 파일이 정상 저장되었는가?
마무리
1번 Tabular 이진 분류는 세 가지 유형(회귀, 이진 분류, 다중 분류) 중 가장 단순한 형태입니다. LabelEncoder도 필요 없고, 예측 후처리도 간단합니다. RandomForestClassifier 하나로 충분히 만점을 받을 수 있습니다.
다만, 단순하다고 방심하면 안 됩니다. stratify 누락, predict_proba 컬럼 혼동, 제출 포맷 불일치 같은 사소한 실수로 점수를 잃을 수 있습니다.
1번은 확실히 30점을 확보하고, 2번과 3번 문제에 집중할 수 있는 여유를 만드세요.