← 모델 목록
수업 실습 2026-08-30 · tabular-classification
그래디언트 부스팅 계열 (CatBoost)

CatBoostClassifier (catboost)

CatBoost 구독 이탈 예측 (ML 미니대회 분류 트랙 · 튜닝·시드 앙상블)
모델
이전 트리의 오차를 다음 트리가 보정해 가는 부스팅 모델. auto_class_weights Balanced로 소수 클래스에 가중치
사용 목적
수업 ML 미니대회 분류 트랙에서 가장 강했던 모델을 튜닝·시드 앙상블로 끌어올리며 리더보드 점수를 비교하려고 사용
코드
mnmms/mldl
가중치
없음
val_auc77.1%
f134.0%
cv5_auc78.4%
실험6회 · 대표 r1
학습 시간없음
추론 CPU / GPU측정 안 함

데이터

  • 대회 제공 train 90,000 · 양성 10.71%
  • valid 18,000 (무작위) · 5-fold CV · 시간 분할
  • 리더보드: test 25,000 (2026-01~04)

학습

  • iterations 300 · lr 0.05 · depth 6
  • Optuna F1 100 trials 약 13분
  • CPU · catboost 1.2.10

결과

  • valid AUC 0.771 (첫날 4개 모델 중 최고)
  • 리더보드 0.780122 (2등) → 시드 앙상블 0.780712
  • 튜닝은 모두 노이즈 수준 (±0.0016)

배운 점

  • F1로 튜닝하면 AUC는 오히려 떨어짐
  • 로컬 검증이 리더보드 순위를 예측하지 못함
  • 점수 차이 < AUC 표준오차 약 0.008
개요용도 의도한 용도: 미니대회 제출 모델 (r1·r3·r4·r5·r6을 차례로 제출) 대상 사용자: 해당 없음 (학습용) 의도하…

용도

  • 의도한 용도: 미니대회 제출 모델 (r1·r3·r4·r5·r6을 차례로 제출)
  • 대상 사용자: 해당 없음 (학습용)
  • 의도하지 않은 용도: 실제 구독 이탈 예측 (합성 데이터)

모델 정보

항목 값
베이스 모델 직접 구현 (처음부터 학습)
크기 · 변형 r1 CatBoostClassifier(iterations=300, learning_rate=0.05, depth=6, loss_function='Logloss', auto_class_weights='Balanced', random_state=42)
리비전 catboost 1.2.10, optuna 4.9.0 (uv.lock 기준)
아키텍처 대칭 트리를 순서대로 더하는 그래디언트 부스팅. r4~r6은 같은 설정을 시드만 바꿔 학습한 모델들의 확률 평균
학습 방식 처음부터 학습
프롬프트 · 에이전트 구성 해당 없음
데이터결정 트리 카드 와 같은 데이터·전처리입니다. 확보 방식 공개 데이터셋 그대로 (수업 대회 제공 합성 데이터) 출처 mini-…

결정 트리 카드와 같은 데이터·전처리입니다.

항목 값
확보 방식 공개 데이터셋 그대로 (수업 대회 제공 합성 데이터)
출처 mini-competition/participant/classification/train.csv, test.csv
직접 수집 내용 해당 없음
이용 조건 확인 해당 없음 (수업 자료)
규모 train 90,000 (2024-01 ~ 2025-12) / test 25,000 (2026-01 ~ 04)
분할 세 가지 검증: ① 무작위 valid 18,000 (stratify, 시드 42) ② 5-fold CV ③ 시간 분할 (2025-09 이후 검증). 리더보드는 test
레이블·클래스 분포 이탈 10.71%
전처리 결측 중앙값·'missing', payment_method 제거, StandardScaler + OneHot (53열). 원본 범주형을 cat_features로 넣는 시도는 5-fold 0.7842로 원-핫(0.7852)보다 나아지지 않음 (tuning_experiments.py 실험 6)
개인정보·민감정보 처리 해당 없음 (합성 데이터)
학습하이퍼파라미터 실행별로 위 실험 기록 참고. 시드 10개는 [42, 7, 123, 2024, 99, 1, 17, 555, 88…
항목 값
하이퍼파라미터 실행별로 위 실험 기록 참고. 시드 10개는 [42, 7, 123, 2024, 99, 1, 17, 555, 888, 2026]
에폭 / 스텝 부스팅 245 ~ 466회 (실행별)
학습 시간 r2 Optuna 30 trials 약 3분(17:16:07 ~ 17:19:12) + 70 trials 약 9.6분(17:28:47) = 약 12.7분 (노트북 Optuna 로그). trial 1회(모델 1개 학습) 약 312초. 나머지 [미확인]
하드웨어 CPU (기본 설정). 장비 이름 [미확인]
프레임워크 catboost 1.2.10, scikit-learn 1.9.0, optuna 4.9.0
시드 · 재현 방법 valid 분할 시드 42 (stratify). 5-fold는 StratifiedKFold(5, shuffle=True, random_state=42). 시간 분할은 snapshot_date 2025-09-01 이전 학습 / 이후(4개월) 검증
결과r1 기본 0.7715 0.340 0.7840 0.7848 0.780122 (2등) 노트북, 커밋 3dc6080 · a3a14…
실행 valid AUC F1 5-fold AUC 시간 분할 AUC 리더보드 AUC 출처
r1 기본 0.7715 0.340 0.7840 0.7848 0.780122 (2등) 노트북, 커밋 3dc6080·a3a1452 메시지, tuning_experiments.py
r2 Optuna F1 0.7588 0.360 - - 미제출 노트북
r3 Optuna AUC 0.7731 - 0.7852 - 0.778996 (3등) 커밋 58496d9, tuning_experiments.py
r4 기본 + 10시드 - - 0.7851 - 0.780712 (3등) 커밋 3dc6080, tuning_experiments.py
r5 CV 튜닝 + 10시드 - - 0.78577 - 0.779548 (3등) 커밋 4115c61, tuning_experiments.py
r6 블렌드 - - - - [미확인] 커밋 284f2b2 ("진행 중")
  • valid 기준 혼동행렬 r1 [[11958, 4115], [690, 1237]], r2 [[13121, 2952], [857, 1070]]
  • 대표 실행은 다른 모델과 같은 valid AUC로 비교되도록 r1로 두었습니다. 리더보드 최고는 r4입니다 (사용자 확인 필요)
  • r2의 best params는 노트북 출력값입니다. tuning_experiments.py의 CONFIG_F1_TUNED(iterations 475, lr 0.0972, l2 9.80)는 다른 탐색 결과로 보입니다 [미확인]

추론 성능 (CPU / GPU)

측정 안 함.

장비 장비 이름 배치 크기 지연 시간 (샘플당, p50 / p95) 처리량 (샘플/초) 메모리 사용
CPU [미확인] - 측정 안 함 측정 안 함 측정 안 함
GPU 해당 없음 (GPU 설정 안 함) - - - -
실험 기록6회 측정 · 대표 r1

같은 모델을 설정·분류기를 바꿔 6번 측정한 기록입니다. ★ r1이(가) 대표 결과(맨 위 수치)입니다.

직전 실행에서 바뀐 설정지표 최고값
실행날짜바뀐 점iterationslearning_ratedepthl2_leaf_regclass_weightseedsval_aucf1cv5_auctime_split_aucleaderboard_auc학습 시간
★ r1
기본 설정
2026-08-30기준
l2_leaf_reg 3은 CatBoost 기본값 [🚩AI 설명]
3000.0563Balanced177.1%34.0%78.4%78.5%78.0%-
r2
Optuna F1 튜닝
2026-08-30Optuna로 iterations·learning_rate·depth·l2_leaf_reg를 F1 목적으로 100회 탐색
AUC가 기본보다 낮아 제출 전에 폐기 (tuning_experiments.py 실험 1)
4660.072785.44Balanced175.9%36.0%---12.7분
r3
Optuna AUC 튜닝 (단일 split)
2026-08-31Optuna 목적을 roc_auc_score로 바꾸고 class weight 사용 여부도 탐색
리더보드 3등으로 하락
2450.065332none177.3%-78.5%-77.9%-
r4
기본 설정 + 10시드 앙상블
2026-08-31r1 설정을 시드만 10개로 바꿔 학습하고 예측 확률을 평균
리더보드 점수가 오른 유일한 시도
3000.0563Balanced10--78.5%-78.1%-
r5
CV 튜닝(depth 4) + 10시드
2026-08-315-fold CV 기반 Optuna로 찾은 설정에 10시드 앙상블
로컬 CV는 r4보다 좋았지만 리더보드에서는 낮음
4050.04543.75none10--78.6%-78.0%-
r6
r4 + r5 블렌드
2026-08-31r4 10개 + r5 10개, 모델 20개 확률 평균
제출 점수 기록 없음 [미확인]. 이후 최종 제출은 로지스틱 회귀로 바뀜
300 / 4050.05 / 0.0456 / 43 / 3.75Balanced / none20------
val_auc 변화 실행 순서대로 · 높을수록 좋음 · 축 일부 생략
r1 · 기본 설정
77.1%
r2 · Optuna F1 튜닝
75.9%
r3 · Optuna AUC 튜닝 (단일 split)
77.3%
한계 · 배운 점한계 알려진 실패 유형: 오차 분석( error_analysis.py , 커밋 a3a1452 메시지)에서 놓친 이탈 고객(FN…

한계

  • 알려진 실패 유형: 오차 분석(error_analysis.py, 커밋 a3a1452 메시지)에서 놓친 이탈 고객(FN)은 NPS·시청 시간·세션 수가 오히려 높고 상담·결제 실패는 적은 "불만 신호 없이 만족하며 떠나는" 유형. 트리 모델이 배운 "문제 신호 = 이탈"과 어긋남
  • 편향 / 공정성 이슈: 해당 없음 (합성 데이터)
  • 성능이 떨어지는 입력 조건: train(2024~2025)과 test(2026) 사이 시간 분포 이동. 무작위 split·CV로는 이를 흉내 낼 수 없음 (tuning_experiments.py 핵심 교훈)

배운 점

tuning_experiments.py 문서 주석과 커밋 메시지에서 옮긴 내용입니다.

  • F1을 목적으로 튜닝한 모델은 실제 채점 지표(ROC-AUC)에서 기본 모델보다 낮았음 → 목적함수를 대회 지표와 맞춰야 함
  • 로컬 검증(단일 split이든 5-fold든 시간 분할이든)이 리더보드 순위를 안정적으로 예측하지 못함
  • AUC 표준오차를 sqrt(AUC*(1-AUC)/n_pos)로 대략 계산하면 약 0.008인데, 다투던 점수 차이(0.0005 ~ 0.0016)는 이보다 작아 노이즈 범위
  • 시드 앙상블은 분산이 큰 설정(depth 6, balanced)에서 효과가 컸고(+0.00102), 얕은 설정(depth 4)에서는 미미(+0.00008)
  • 결국 오차 분석 후 로지스틱 회귀로 바꿔 최종 제출 → 로지스틱 회귀 카드
사용 방법코드 셀 4개
In [1]기본 학습 (r1)
from catboost import CatBoostClassifier

model_cat = CatBoostClassifier(
    iterations=300,
    learning_rate=0.05,
    depth=6,
    loss_function='Logloss',
    random_state=42,
    auto_class_weights='Balanced',
    verbose=0
)
model_cat.fit(X_train, y_train)
cat_pred = model_cat.predict(X_val)
print(confusion_matrix(y_val, cat_pred))
print('F1 Score :', f1_score(y_val, cat_pred))
Out[1] 출력 보기
[[11958  4115]
 [  690  1237]]
F1 Score : 0.3398818519027339
In [2]Optuna F1 튜닝 결과 (r2)
study = optuna.create_study(direction='maximize')
study.optimize(objective, n_trials=30)
study.optimize(objective, n_trials=70)  # 기존 30 + 70 = 총 100 trials

print('total trials :', len(study.trials))
print('best f1 :', study.best_value)
print('best params :', study.best_params)
Out[2] 출력 보기
total trials : 100
best f1 : 0.3597243234157001
best params : {'iterations': 466, 'learning_rate': 0.07266938077686465, 'depth': 8, 'l2_leaf_reg': 5.4428683566481855}
In [3]모델별 ROC-AUC 비교 (확률 기준)
from sklearn.metrics import roc_auc_score

auc_rows = []
for name, m in models.items():
    proba = m.predict_proba(X_val)[:, 1]
    auc_rows.append((name, roc_auc_score(y_val, proba)))

pd.DataFrame(auc_rows, columns=['model', 'roc_auc']).sort_values('roc_auc', ascending=False)
Out[3] 출력 보기
                            model   roc_auc
3                    CatBoost(기본)  0.771493
1            RandomForest(배깅, 기본)  0.760560
5  RandomForest(Optuna 100trials)  0.760544
4      CatBoost(Optuna 100trials)  0.758822
2       RandomForest(max_depth=4)  0.744979
0                    DecisionTree  0.707975
In [4]시드 앙상블 (r4)
SEEDS_10 = [42, 7, 123, 2024, 99, 1, 17, 555, 888, 2026]

def seed_ensemble_predict(config, X_train_scaled, y_train_full, X_target, seeds=SEEDS_10):
    """동일 설정을 시드만 바꿔 여러 번 학습 후 예측 확률 평균 (variance 감소)."""
    probas = []
    for s in seeds:
        params = {k: v for k, v in config.items() if k != 'random_state'}
        m = CatBoostClassifier(**params, random_state=s)
        m.fit(X_train_scaled, y_train_full)
        probas.append(m.predict_proba(X_target)[:, 1])
    return np.mean(probas, axis=0)

같은 과제·데이터셋 비교 tabular-classification · 수업 미니대회: 60-day Subscription Churn (합성) · 4개

굵은 이름이 이 모델입니다. 주황 테두리가 그룹 안 최고값입니다.

val_auc 높을수록 좋음 · 축 일부 생략