본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.
본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.
이미지 로딩 중...
AI Generated
2025. 12. 6. · 15 Views
XGBoost 완벽 마스터
머신러닝 경진대회의 강자 XGBoost를 처음부터 끝까지 완벽하게 마스터하는 가이드입니다. 그래디언트 부스팅의 원리부터 하이퍼파라미터 튜닝, 실전 활용까지 초급자도 쉽게 따라할 수 있도록 설명합니다.
목차
- XGBoost_소개와_설치
- 기본_모델_학습과_예측
- DMatrix와_Native_API
- 조기_종료로_과적합_방지
- 하이퍼파라미터_튜닝
- 피처_중요도_분석
- 불균형_데이터_처리
- 교차_검증과_모델_안정성
- 모델_저장과_배포
- GPU_가속_활용하기
1. XGBoost 소개와 설치
김개발 씨는 회사에서 고객 이탈 예측 모델을 만들어 달라는 요청을 받았습니다. 여러 알고리즘을 시도해 보았지만 성능이 만족스럽지 않았습니다.
그때 선배가 "XGBoost 써봤어요?"라고 물었습니다.
XGBoost는 eXtreme Gradient Boosting의 약자로, 여러 개의 약한 학습기를 순차적으로 결합하여 강력한 예측 모델을 만드는 앙상블 기법입니다. 마치 여러 명의 전문가가 차례로 의견을 내면서 이전 전문가의 실수를 보완하는 것과 같습니다.
Kaggle 경진대회에서 수많은 우승을 차지하며 그 성능을 입증했습니다.
다음 코드를 살펴봅시다.
# XGBoost 설치 및 기본 임포트
# pip install xgboost
import xgboost as xgb
import numpy as np
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
# 샘플 데이터 로드
data = load_iris()
X, y = data.data, data.target
# 학습/테스트 데이터 분리
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
print(f"학습 데이터: {X_train.shape}, 테스트 데이터: {X_test.shape}")
김개발 씨는 입사 6개월 차 데이터 분석가입니다. 어느 날 팀장님이 다가와 이렇게 말했습니다.
"김개발 씨, 우리 고객 이탈 예측 모델 정확도가 너무 낮아요. 다음 주까지 개선해 볼 수 있을까요?" 김개발 씨는 밤새 여러 알고리즘을 시도해 보았습니다.
로지스틱 회귀, 결정 트리, 랜덤 포레스트까지. 하지만 성능은 크게 나아지지 않았습니다.
지친 표정으로 커피를 마시고 있을 때, 옆자리 박시니어 씨가 말을 걸었습니다. "혹시 XGBoost 써봤어요?" 그렇다면 XGBoost란 정확히 무엇일까요?
쉽게 비유하자면, XGBoost는 마치 릴레이 달리기와 같습니다. 첫 번째 주자가 달리고 나면, 두 번째 주자는 첫 번째 주자가 놓친 거리를 보완합니다.
세 번째 주자는 다시 두 번째 주자의 부족한 부분을 채웁니다. 이렇게 여러 주자가 순차적으로 달리면서 각자의 약점을 보완해 나가는 것입니다.
XGBoost 이전에도 부스팅 알고리즘은 존재했습니다. 하지만 기존 알고리즘들은 속도가 느리고 메모리 사용량이 많았습니다.
대용량 데이터를 처리하기 어려웠고, 과적합 문제도 심각했습니다. 2016년 Tianqi Chen이 XGBoost를 발표하면서 상황이 바뀌었습니다.
정규화를 통해 과적합을 방지하고, 병렬 처리로 속도를 획기적으로 개선했습니다. 더불어 결측치 자동 처리 기능까지 갖추면서 실무에서 바로 사용할 수 있는 알고리즘이 되었습니다.
위의 코드를 살펴보겠습니다. 먼저 xgboost 라이브러리를 임포트합니다.
sklearn의 load_iris 함수로 붓꽃 데이터를 불러오고, train_test_split으로 학습용과 테스트용 데이터를 8:2 비율로 나눕니다. 이것이 XGBoost를 시작하기 위한 기본 준비입니다.
실제 현업에서 XGBoost는 어디에 쓰일까요? 금융권에서는 신용 평가와 사기 탐지에 활용됩니다.
이커머스에서는 고객 이탈 예측과 추천 시스템에 사용됩니다. 제조업에서는 품질 예측과 설비 고장 예측에 적용됩니다.
설치할 때 주의할 점이 있습니다. GPU 버전을 사용하려면 별도의 설정이 필요합니다.
또한 파이썬 버전과의 호환성도 확인해야 합니다. pip install xgboost 명령어로 간단히 설치할 수 있지만, 가상환경을 사용하는 것을 권장합니다.
다시 김개발 씨의 이야기로 돌아가 봅시다. 박시니어 씨의 조언을 듣고 XGBoost를 설치한 김개발 씨는 기대감에 부풀었습니다.
과연 이 알고리즘이 문제를 해결해 줄 수 있을까요? 다음 장에서 본격적으로 XGBoost 모델을 학습시켜 보겠습니다.
실전 팁
💡 - 가상환경에서 설치하면 버전 충돌을 방지할 수 있습니다
- GPU 버전 사용 시 CUDA 설치가 필요합니다
2. 기본 모델 학습과 예측
XGBoost를 설치한 김개발 씨는 이제 본격적으로 모델을 만들어 보려고 합니다. 하지만 코드를 어떻게 작성해야 할지 막막했습니다.
박시니어 씨가 옆에서 차근차근 알려주기 시작했습니다.
XGBoost 모델 학습은 크게 두 가지 방식으로 할 수 있습니다. Scikit-learn API를 사용하면 기존에 익숙한 fit/predict 패턴으로 쉽게 시작할 수 있습니다.
Native API는 더 세밀한 제어가 가능하지만 학습 곡선이 있습니다. 초보자에게는 Scikit-learn API부터 시작하는 것을 권장합니다.
다음 코드를 살펴봅시다.
import xgboost as xgb
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
# 데이터 준비
X, y = load_iris(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
# XGBoost 분류기 생성 및 학습
model = xgb.XGBClassifier(
n_estimators=100, # 트리 개수
max_depth=3, # 트리 최대 깊이
learning_rate=0.1, # 학습률
random_state=42
)
model.fit(X_train, y_train)
# 예측 및 평가
predictions = model.predict(X_test)
accuracy = accuracy_score(y_test, predictions)
print(f"정확도: {accuracy:.4f}")
김개발 씨가 모니터 앞에 앉았습니다. 박시니어 씨가 의자를 끌어와 옆에 앉으며 말했습니다.
"자, XGBoost는 두 가지 방식으로 사용할 수 있어요. 먼저 쉬운 방법부터 시작해 볼까요?" Scikit-learn API는 마치 자동차의 오토매틱 기어와 같습니다.
복잡한 내부 동작을 몰라도 운전할 수 있습니다. fit 메서드로 학습하고, predict 메서드로 예측합니다.
이미 sklearn을 사용해 본 개발자라면 익숙한 패턴입니다. 반면 Native API는 수동 기어와 같습니다.
더 세밀한 제어가 가능하지만, 그만큼 배워야 할 것도 많습니다. DMatrix라는 특별한 데이터 구조를 사용하고, xgb.train 함수로 학습합니다.
처음에는 Scikit-learn API로 시작하고, 익숙해지면 Native API를 배우는 것이 좋습니다. 코드를 한 줄씩 살펴보겠습니다.
XGBClassifier를 생성할 때 세 가지 중요한 파라미터를 설정합니다. n_estimators는 만들 트리의 개수입니다.
100개의 트리가 순차적으로 학습되면서 서로의 오차를 보완합니다. max_depth는 각 트리의 최대 깊이입니다.
깊이가 깊을수록 복잡한 패턴을 학습할 수 있지만, 과적합의 위험도 커집니다. 보통 3에서 10 사이의 값을 사용합니다.
learning_rate는 각 트리가 기여하는 정도를 조절합니다. 값이 작을수록 천천히 학습하지만 더 정교한 모델을 만들 수 있습니다.
보통 0.01에서 0.3 사이의 값을 사용합니다. fit 메서드를 호출하면 학습이 시작됩니다.
내부적으로 100개의 트리가 순차적으로 만들어지면서, 각 트리는 이전 트리들이 틀린 부분에 집중합니다. 마치 시험 오답노트를 만들어 공부하는 것과 같습니다.
predict 메서드는 학습된 모델로 새로운 데이터를 예측합니다. 모든 트리의 예측을 종합하여 최종 결과를 도출합니다.
분류 문제에서는 클래스 레이블을, 회귀 문제에서는 연속값을 반환합니다. 실무에서는 분류와 회귀 문제를 구분해야 합니다.
고객이 이탈할지 아닐지 예측하는 것은 분류 문제입니다. XGBClassifier를 사용합니다.
반면 고객의 예상 구매액을 예측하는 것은 회귀 문제입니다. XGBRegressor를 사용합니다.
박시니어 씨가 말했습니다. "어때요, 생각보다 간단하죠?" 김개발 씨는 고개를 끄덕였습니다.
하지만 아직 궁금한 것이 많았습니다. 저 파라미터들은 어떻게 정해야 할까요?
다음 장에서 하이퍼파라미터 튜닝에 대해 알아보겠습니다.
실전 팁
💡 - 분류 문제는 XGBClassifier, 회귀 문제는 XGBRegressor를 사용합니다
- 처음에는 기본 파라미터로 시작하고 점진적으로 튜닝하세요
3. DMatrix와 Native API
며칠 후, 김개발 씨는 더 큰 데이터셋을 다루게 되었습니다. 수백만 건의 데이터를 처리하는데 속도가 너무 느렸습니다.
박시니어 씨가 말했습니다. "이제 Native API를 배워볼 때가 됐네요."
DMatrix는 XGBoost에서 사용하는 최적화된 데이터 구조입니다. 메모리 효율성이 뛰어나고 처리 속도가 빠릅니다.
Native API와 함께 사용하면 대용량 데이터도 효율적으로 다룰 수 있으며, 조기 종료나 사용자 정의 목적 함수 같은 고급 기능을 활용할 수 있습니다.
다음 코드를 살펴봅시다.
import xgboost as xgb
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
# 데이터 준비
X, y = load_iris(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
# DMatrix 생성 - XGBoost 최적화 데이터 구조
dtrain = xgb.DMatrix(X_train, label=y_train)
dtest = xgb.DMatrix(X_test, label=y_test)
# 파라미터 설정
params = {
'max_depth': 3,
'eta': 0.1, # learning_rate와 동일
'objective': 'multi:softmax',
'num_class': 3
}
# 모델 학습 (Native API)
model = xgb.train(params, dtrain, num_boost_round=100)
# 예측
predictions = model.predict(dtest)
김개발 씨의 데이터는 5백만 건이 넘었습니다. Scikit-learn API로는 메모리 부족 오류가 자꾸 발생했습니다.
박시니어 씨가 키보드를 가져오며 말했습니다. "Native API를 쓰면 해결돼요." DMatrix는 마치 압축 파일과 같습니다.
같은 데이터지만 더 작은 공간에 효율적으로 저장됩니다. 일반 numpy 배열이나 pandas 데이터프레임보다 메모리를 적게 사용하면서도 처리 속도는 더 빠릅니다.
DMatrix를 생성하는 방법은 간단합니다. xgb.DMatrix 함수에 피처 데이터와 레이블을 전달하면 됩니다.
학습용 데이터와 테스트용 데이터를 각각 DMatrix로 변환합니다. 이 과정에서 데이터가 XGBoost에 최적화된 형태로 변환됩니다.
Native API에서는 파라미터를 딕셔너리로 전달합니다. eta는 Scikit-learn API의 learning_rate와 같은 의미입니다.
objective는 목적 함수를 지정합니다. 다중 클래스 분류에서는 multi:softmax를 사용합니다.
xgb.train 함수가 실제 학습을 수행합니다. 첫 번째 인자로 파라미터 딕셔너리를, 두 번째 인자로 학습용 DMatrix를 전달합니다.
num_boost_round는 학습할 라운드 수, 즉 생성할 트리의 개수입니다. Native API의 진정한 힘은 고급 기능에 있습니다.
검증 데이터셋을 지정하여 학습 과정을 모니터링할 수 있습니다. 조기 종료를 통해 과적합을 방지할 수 있습니다.
사용자 정의 목적 함수와 평가 지표도 사용할 수 있습니다. 실무에서 대용량 데이터를 다룰 때 DMatrix는 필수입니다.
특히 메모리가 제한된 환경에서 더욱 그렇습니다. 학습 속도도 눈에 띄게 향상됩니다.
김개발 씨의 5백만 건 데이터도 무리 없이 처리할 수 있게 되었습니다. 주의할 점이 있습니다.
DMatrix는 한 번 생성하면 데이터를 수정할 수 없습니다. 불변 객체이기 때문입니다.
데이터 전처리는 DMatrix를 생성하기 전에 완료해야 합니다. 또한 DMatrix를 저장하고 불러오는 기능도 있어서 반복 실험에 유용합니다.
김개발 씨가 코드를 실행했습니다. 이전에는 10분 넘게 걸리던 학습이 2분 만에 끝났습니다.
"와, 진짜 빠르네요!" 박시니어 씨가 미소 지으며 대답했습니다. "이제 조기 종료 기능도 배워볼까요?"
실전 팁
💡 - 10만 건 이상의 데이터에서는 DMatrix 사용을 권장합니다
- DMatrix는 불변 객체이므로 전처리를 먼저 완료하세요
4. 조기 종료로 과적합 방지
김개발 씨의 모델 정확도가 학습 데이터에서는 99%인데, 테스트 데이터에서는 75%밖에 나오지 않았습니다. 전형적인 과적합 증상이었습니다.
박시니어 씨가 말했습니다. "조기 종료를 써봐요."
**조기 종료(Early Stopping)**는 검증 데이터의 성능이 더 이상 개선되지 않으면 학습을 자동으로 중단하는 기법입니다. 마치 공부를 하다가 성적이 오르지 않으면 그만두는 것과 같습니다.
이를 통해 과적합을 효과적으로 방지하고 학습 시간도 절약할 수 있습니다.
다음 코드를 살펴봅시다.
import xgboost as xgb
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
# 데이터 준비
X, y = load_breast_cancer(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
# 모델 생성
model = xgb.XGBClassifier(
n_estimators=1000, # 최대 1000개 트리
max_depth=5,
learning_rate=0.1,
early_stopping_rounds=10, # 10라운드 개선 없으면 중단
eval_metric='logloss'
)
# 검증 데이터와 함께 학습
model.fit(
X_train, y_train,
eval_set=[(X_test, y_test)],
verbose=True
)
print(f"최적 트리 개수: {model.best_iteration}")
김개발 씨는 당혹스러웠습니다. 학습 데이터에서는 거의 완벽한 예측을 하는데, 왜 새로운 데이터에서는 성능이 떨어지는 걸까요?
이것이 바로 과적합입니다. 모델이 학습 데이터를 외워버린 것입니다.
과적합은 마치 시험 문제를 달달 외우는 것과 같습니다. 같은 문제가 나오면 만점을 받지만, 조금만 다른 문제가 나오면 틀립니다.
진정한 이해가 아니라 단순 암기이기 때문입니다. 조기 종료는 이 문제를 해결하는 우아한 방법입니다.
학습 중에 별도의 검증 데이터셋으로 성능을 계속 모니터링합니다. 성능이 더 이상 개선되지 않으면 거기서 학습을 멈춥니다.
더 학습해봤자 과적합만 심해지기 때문입니다. 코드에서 early_stopping_rounds=10은 10라운드 연속으로 검증 성능이 개선되지 않으면 학습을 중단한다는 의미입니다.
n_estimators=1000으로 설정했지만, 실제로는 그보다 훨씬 적은 트리에서 학습이 종료될 수 있습니다. eval_set 파라미터에 검증 데이터를 전달합니다.
학습 중에 이 데이터로 성능을 평가합니다. eval_metric은 어떤 지표로 성능을 측정할지 정합니다.
분류 문제에서는 logloss나 auc를 주로 사용합니다. verbose=True로 설정하면 학습 과정이 화면에 출력됩니다.
매 라운드마다 학습 손실과 검증 손실을 볼 수 있습니다. 학습 손실은 계속 줄어드는데 검증 손실이 늘어나기 시작하면, 그것이 과적합의 신호입니다.
학습이 끝나면 best_iteration 속성에 최적의 트리 개수가 저장됩니다. 이 정보를 활용하여 다음 학습에서는 n_estimators를 그 값으로 설정할 수 있습니다.
모델을 저장할 때도 최적 상태의 모델이 저장됩니다. 실무에서 조기 종료는 거의 필수적으로 사용됩니다.
하이퍼파라미터를 일일이 튜닝하지 않아도 적절한 복잡도의 모델을 자동으로 찾아줍니다. 학습 시간도 절약됩니다.
1000라운드를 다 돌릴 필요 없이 필요한 만큼만 학습합니다. 김개발 씨가 조기 종료를 적용했습니다.
이번에는 학습 데이터 정확도 92%, 테스트 데이터 정확도 89%가 나왔습니다. 박시니어 씨가 말했습니다.
"봐요, 이게 훨씬 건강한 모델이에요." 과적합이 해결된 것입니다.
실전 팁
💡 - early_stopping_rounds는 보통 10에서 50 사이로 설정합니다
- 반드시 학습에 사용하지 않은 별도의 검증 데이터가 필요합니다
5. 하이퍼파라미터 튜닝
모델의 기본 성능은 나쁘지 않았지만, 팀장님은 더 높은 정확도를 원했습니다. "0.5%만 더 올릴 수 있을까요?" 김개발 씨는 하이퍼파라미터 튜닝이라는 것을 시작해야 했습니다.
하이퍼파라미터는 모델 학습 전에 미리 설정해야 하는 값들입니다. XGBoost에는 수십 개의 하이퍼파라미터가 있지만, 핵심적인 몇 가지만 제대로 튜닝해도 성능을 크게 향상시킬 수 있습니다.
그리드 서치, 랜덤 서치, 베이지안 최적화 등 다양한 튜닝 방법이 있습니다.
다음 코드를 살펴봅시다.
from sklearn.model_selection import GridSearchCV
import xgboost as xgb
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
X, y = load_breast_cancer(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
# 탐색할 하이퍼파라미터 조합
param_grid = {
'max_depth': [3, 5, 7],
'learning_rate': [0.01, 0.1, 0.3],
'n_estimators': [100, 200],
'subsample': [0.8, 1.0],
'colsample_bytree': [0.8, 1.0]
}
model = xgb.XGBClassifier(random_state=42)
# 그리드 서치 수행
grid_search = GridSearchCV(
model, param_grid, cv=3, scoring='accuracy', n_jobs=-1
)
grid_search.fit(X_train, y_train)
print(f"최적 파라미터: {grid_search.best_params_}")
print(f"최고 점수: {grid_search.best_score_:.4f}")
김개발 씨는 하이퍼파라미터라는 단어를 듣고 머리가 아파졌습니다. XGBoost 공식 문서를 보니 파라미터가 수십 개나 되었습니다.
어디서부터 시작해야 할까요? 박시니어 씨가 종이에 그림을 그리며 설명했습니다.
"모든 파라미터를 다 건드릴 필요 없어요. 핵심 파라미터 몇 개만 잘 튜닝해도 충분해요." 가장 중요한 파라미터는 max_depth입니다.
트리의 최대 깊이를 결정합니다. 깊이가 깊을수록 모델이 복잡해져서 더 세밀한 패턴을 학습할 수 있습니다.
하지만 너무 깊으면 과적합이 발생합니다. 보통 3에서 10 사이에서 시작합니다.
learning_rate는 각 트리의 기여도를 조절합니다. 마치 걸음의 보폭과 같습니다.
보폭이 크면 빨리 목적지에 도착하지만 정확한 위치를 놓칠 수 있습니다. 보폭이 작으면 천천히 가지만 더 정확하게 도착합니다.
작은 learning_rate와 많은 n_estimators 조합이 보통 좋은 성능을 냅니다. subsample과 colsample_bytree는 랜덤성을 추가합니다.
subsample은 각 트리를 만들 때 사용할 데이터의 비율입니다. colsample_bytree는 각 트리에서 사용할 피처의 비율입니다.
이 랜덤성이 과적합을 방지하는 데 도움이 됩니다. GridSearchCV는 지정한 모든 파라미터 조합을 시도합니다.
위 코드에서는 3x3x2x2x2 = 72개의 조합을 테스트합니다. cv=3은 3겹 교차 검증을 의미합니다.
각 조합에 대해 3번씩 검증하므로 총 216번의 학습이 이루어집니다. n_jobs=-1은 가능한 모든 CPU 코어를 사용하라는 의미입니다.
시간이 오래 걸리는 그리드 서치에서 병렬 처리는 필수입니다. 탐색할 조합이 너무 많다면 RandomizedSearchCV를 사용하여 일부 조합만 무작위로 탐색할 수도 있습니다.
실무에서는 단계적 접근이 효과적입니다. 먼저 넓은 범위에서 대략적인 최적값을 찾고, 그 주변에서 세밀하게 탐색합니다.
또한 Optuna나 Hyperopt 같은 베이지안 최적화 라이브러리를 사용하면 더 효율적으로 탐색할 수 있습니다. 주의할 점이 있습니다.
테스트 데이터로 튜닝하면 안 됩니다. 테스트 데이터는 최종 평가에만 사용해야 합니다.
튜닝에는 반드시 검증 데이터나 교차 검증을 사용하세요. 그렇지 않으면 테스트 데이터에 과적합된 모델을 만들게 됩니다.
김개발 씨는 하룻밤 동안 그리드 서치를 돌렸습니다. 다음 날 아침, 결과를 확인했습니다.
정확도가 0.7%나 올랐습니다. 팀장님이 원하던 목표를 달성한 것입니다.
실전 팁
💡 - 처음에는 넓은 범위로 탐색하고, 점진적으로 좁혀가세요
- 탐색 시간이 오래 걸리면 RandomizedSearchCV를 고려하세요
6. 피처 중요도 분석
모델 성능은 좋아졌지만, 팀장님이 새로운 질문을 던졌습니다. "그래서 고객이 이탈하는 가장 큰 이유가 뭐예요?" 김개발 씨는 모델이 왜 그런 예측을 했는지 설명해야 했습니다.
피처 중요도는 각 변수가 예측에 얼마나 기여하는지를 나타냅니다. XGBoost는 여러 방식으로 피처 중요도를 계산할 수 있으며, 이를 통해 모델의 예측 근거를 이해하고 비즈니스 인사이트를 도출할 수 있습니다.
해석 가능한 머신러닝의 핵심 요소입니다.
다음 코드를 살펴봅시다.
import xgboost as xgb
import matplotlib.pyplot as plt
from sklearn.datasets import load_breast_cancer
# 데이터 로드 및 모델 학습
data = load_breast_cancer()
X, y = data.data, data.target
model = xgb.XGBClassifier(n_estimators=100, max_depth=3)
model.fit(X, y)
# 피처 중요도 추출
importance = model.feature_importances_
# 중요도 기준 상위 10개 피처
feature_names = data.feature_names
top_indices = importance.argsort()[-10:][::-1]
print("상위 10개 피처:")
for i in top_indices:
print(f" {feature_names[i]}: {importance[i]:.4f}")
# 시각화
xgb.plot_importance(model, max_num_features=10)
plt.tight_layout()
plt.savefig('feature_importance.png')
데이터 과학자의 역할은 모델을 만드는 것에서 끝나지 않습니다. 모델이 왜 그런 결정을 내렸는지 설명할 수 있어야 합니다.
팀장님뿐만 아니라 마케팅 팀, 경영진 등 다양한 이해관계자에게 결과를 설명해야 합니다. 피처 중요도는 마치 수사관의 증거 분석과 같습니다.
범인을 잡았다면 왜 그 사람이 범인인지 증거를 제시해야 합니다. 마찬가지로 모델이 고객 이탈을 예측했다면, 어떤 요소가 그 판단의 근거인지 보여줄 수 있어야 합니다.
XGBoost는 세 가지 방식으로 피처 중요도를 계산합니다. gain은 해당 피처를 사용했을 때 얻는 평균적인 정보 이득입니다.
weight는 해당 피처가 트리에서 분할에 사용된 횟수입니다. cover는 해당 피처가 분할할 때 커버하는 샘플의 수입니다.
feature_importances_ 속성은 기본적으로 gain 기반의 중요도를 반환합니다. 값이 클수록 그 피처가 예측에 더 큰 영향을 미친다는 의미입니다.
이 값들의 합은 1이 되도록 정규화되어 있습니다. 코드에서 argsort 함수는 중요도를 기준으로 인덱스를 정렬합니다.
[-10:]는 상위 10개를 선택하고, [::-1]는 내림차순으로 뒤집습니다. 이렇게 하면 가장 중요한 피처부터 순서대로 출력됩니다.
plot_importance 함수는 피처 중요도를 막대 그래프로 시각화합니다. max_num_features 파라미터로 표시할 피처 수를 제한할 수 있습니다.
이 그래프 한 장으로 비즈니스 미팅에서 핵심 요소를 쉽게 설명할 수 있습니다. 실무에서 피처 중요도 분석은 여러 목적으로 활용됩니다.
첫째, 비즈니스 인사이트를 도출합니다. 고객 이탈에 가장 큰 영향을 미치는 요소가 무엇인지 파악할 수 있습니다.
둘째, 피처 선택에 활용합니다. 중요도가 낮은 피처를 제거하면 모델을 단순화할 수 있습니다.
주의할 점도 있습니다. 피처 중요도는 상관관계를 보여줄 뿐 인과관계를 증명하지는 않습니다.
또한 상관성이 높은 피처들 사이에서는 중요도가 분산될 수 있습니다. 따라서 해석할 때 주의가 필요합니다.
김개발 씨는 피처 중요도 그래프를 팀장님께 보여드렸습니다. "아, 그래서 최근 구매 이력이 가장 중요하군요!" 팀장님이 고개를 끄덕였습니다.
데이터가 스토리로 바뀌는 순간이었습니다.
실전 팁
💡 - importance_type 파라미터로 gain, weight, cover 중 선택할 수 있습니다
- SHAP 값을 사용하면 더 정확한 피처 중요도를 얻을 수 있습니다
7. 불균형 데이터 처리
새로운 프로젝트가 시작되었습니다. 사기 거래 탐지 모델을 만드는 것이었습니다.
그런데 데이터를 보니 사기 거래는 전체의 0.1%에 불과했습니다. 김개발 씨는 난감했습니다.
불균형 데이터는 클래스 간 샘플 수의 차이가 큰 데이터를 말합니다. 사기 탐지, 이상 감지, 희귀 질병 진단 등에서 흔히 발생합니다.
XGBoost는 scale_pos_weight 파라미터로 이 문제를 효과적으로 다룰 수 있으며, 오버샘플링이나 언더샘플링과 결합하면 더 좋은 결과를 얻을 수 있습니다.
다음 코드를 살펴봅시다.
import xgboost as xgb
import numpy as np
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
# 불균형 데이터 생성 (1:99 비율)
X, y = make_classification(
n_samples=10000, weights=[0.99, 0.01], random_state=42
)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
# 클래스 비율 계산
neg_count = np.sum(y_train == 0)
pos_count = np.sum(y_train == 1)
scale = neg_count / pos_count
# scale_pos_weight로 불균형 보정
model = xgb.XGBClassifier(
scale_pos_weight=scale, # 양성 클래스 가중치
n_estimators=100,
max_depth=3
)
model.fit(X_train, y_train)
predictions = model.predict(X_test)
print(classification_report(y_test, predictions))
김개발 씨가 처음 만든 모델은 정확도 99.9%를 기록했습니다. 놀라운 수치처럼 보였지만, 사실 이 모델은 쓸모가 없었습니다.
모든 거래를 정상으로 예측했을 뿐이었습니다. 정상 거래가 99.9%이니 아무것도 안 해도 99.9% 정확도가 나오는 것입니다.
불균형 데이터는 마치 바늘 찾기와 같습니다. 건초더미에서 바늘을 찾아야 하는데, 모델은 그냥 "여기엔 바늘 없어요"라고 대답해버립니다.
대부분 맞는 대답이지만 정작 바늘을 찾지는 못합니다. scale_pos_weight 파라미터가 이 문제를 해결합니다.
소수 클래스의 샘플에 더 큰 가중치를 부여합니다. 양성 클래스가 1%라면, scale_pos_weight를 99로 설정합니다.
그러면 모델은 소수 클래스의 오분류에 더 큰 패널티를 받게 됩니다. 코드에서 neg_count / pos_count를 계산하여 자동으로 가중치를 설정합니다.
음성 클래스가 9900개, 양성 클래스가 100개라면 가중치는 99가 됩니다. 이렇게 하면 소수 클래스 하나를 틀리는 것이 다수 클래스 99개를 틀리는 것과 같은 비용으로 처리됩니다.
평가 지표도 달라져야 합니다. 불균형 데이터에서 정확도는 의미가 없습니다.
대신 **정밀도(Precision)**와 **재현율(Recall)**을 봐야 합니다. 정밀도는 사기라고 예측한 것 중 실제 사기의 비율입니다.
재현율은 실제 사기 중 탐지한 비율입니다. classification_report 함수가 이 모든 지표를 한 번에 보여줍니다.
F1-score는 정밀도와 재현율의 조화 평균입니다. 불균형 데이터에서는 F1-score가 주요 평가 지표가 됩니다.
실무에서는 scale_pos_weight만으로 부족할 때가 많습니다. SMOTE로 소수 클래스를 오버샘플링하거나, 언더샘플링으로 다수 클래스를 줄이기도 합니다.
또한 threshold를 조정하여 정밀도와 재현율의 균형을 맞추기도 합니다. 사기 탐지에서는 재현율이 더 중요할 수 있습니다.
사기를 놓치면 큰 손해이기 때문입니다. 반면 스팸 필터에서는 정밀도가 더 중요할 수 있습니다.
정상 메일을 스팸으로 분류하면 중요한 메일을 놓칠 수 있기 때문입니다. 비즈니스 상황에 따라 판단해야 합니다.
김개발 씨가 scale_pos_weight를 적용했습니다. 이번에는 정확도가 95%로 낮아졌지만, 사기 탐지율(재현율)이 80%로 크게 올랐습니다.
팀장님이 만족하며 말했습니다. "이제 진짜 쓸 만한 모델이네요."
실전 팁
💡 - scale_pos_weight = 음성샘플수 / 양성샘플수로 계산합니다
- 비즈니스 목표에 따라 정밀도와 재현율 중 무엇을 우선할지 결정하세요
8. 교차 검증과 모델 안정성
김개발 씨의 모델은 어떤 날은 95%, 어떤 날은 88%의 성능을 보였습니다. 같은 모델인데 왜 이렇게 들쭉날쭉한 걸까요?
박시니어 씨가 교차 검증의 중요성을 설명해 주었습니다.
**교차 검증(Cross Validation)**은 데이터를 여러 부분으로 나누어 모델을 반복 학습하고 평가하는 기법입니다. 한 번의 평가로는 우연의 영향을 배제하기 어렵지만, 여러 번 반복하면 모델의 실제 성능을 더 정확하게 추정할 수 있습니다.
또한 모델의 안정성도 확인할 수 있습니다.
다음 코드를 살펴봅시다.
import xgboost as xgb
from sklearn.model_selection import cross_val_score, KFold
from sklearn.datasets import load_breast_cancer
import numpy as np
# 데이터 로드
X, y = load_breast_cancer(return_X_y=True)
# 모델 정의
model = xgb.XGBClassifier(
n_estimators=100,
max_depth=3,
learning_rate=0.1
)
# 5-폴드 교차 검증
kfold = KFold(n_splits=5, shuffle=True, random_state=42)
scores = cross_val_score(model, X, y, cv=kfold, scoring='accuracy')
print(f"각 폴드 점수: {scores}")
print(f"평균 점수: {scores.mean():.4f}")
print(f"표준 편차: {scores.std():.4f}")
# XGBoost 내장 교차 검증
dtrain = xgb.DMatrix(X, label=y)
params = {'max_depth': 3, 'eta': 0.1, 'objective': 'binary:logistic'}
cv_results = xgb.cv(params, dtrain, num_boost_round=100, nfold=5)
print(f"\n최종 AUC: {cv_results['test-auc-mean'].iloc[-1]:.4f}")
단 한 번의 시험으로 학생의 실력을 정확히 평가할 수 있을까요? 그날따라 컨디션이 좋았을 수도, 나빴을 수도 있습니다.
여러 번 시험을 봐야 진정한 실력을 알 수 있습니다. 모델 평가도 마찬가지입니다.
K-폴드 교차 검증은 데이터를 K개의 동등한 부분으로 나눕니다. 각 부분을 한 번씩 검증 데이터로 사용하고, 나머지는 학습에 사용합니다.
이 과정을 K번 반복하면 K개의 성능 점수를 얻습니다. 5-폴드 교차 검증을 예로 들어보겠습니다.
데이터가 1000개라면 200개씩 5개 부분으로 나눕니다. 첫 번째 반복에서는 첫 번째 200개로 평가하고 나머지 800개로 학습합니다.
두 번째 반복에서는 두 번째 200개로 평가합니다. 이렇게 5번 반복합니다.
코드에서 KFold 객체를 생성합니다. n_splits=5는 5개로 나눈다는 의미입니다.
shuffle=True는 나누기 전에 데이터를 섞습니다. random_state는 재현성을 위해 설정합니다.
같은 random_state면 같은 방식으로 나누어집니다. cross_val_score 함수가 교차 검증을 수행합니다.
5개의 점수가 반환됩니다. 평균 점수가 모델의 예상 성능입니다.
표준 편차가 작을수록 모델이 안정적입니다. 표준 편차가 크다면 데이터에 따라 성능이 크게 달라진다는 의미입니다.
XGBoost는 xgb.cv라는 내장 교차 검증 함수도 제공합니다. 이 함수는 더 세밀한 제어가 가능합니다.
조기 종료와 결합하여 최적의 트리 개수를 찾을 수 있습니다. 매 라운드마다의 성능 변화도 확인할 수 있습니다.
실무에서 교차 검증은 두 가지 목적으로 사용됩니다. 첫째, 모델의 실제 성능을 추정합니다.
단일 평가보다 신뢰할 수 있는 수치를 얻을 수 있습니다. 둘째, 하이퍼파라미터 튜닝에서 사용합니다.
GridSearchCV가 내부적으로 교차 검증을 수행합니다. 표준 편차에 주목해야 합니다.
평균이 높아도 표준 편차가 크면 문제가 있습니다. 예를 들어 [95, 70, 92, 75, 88]이라면 평균은 84%이지만 편차가 너무 큽니다.
이런 경우 데이터의 특성을 다시 살펴봐야 합니다. 특정 조건에서만 성능이 떨어지는 것일 수 있습니다.
김개발 씨가 교차 검증을 수행했습니다. 다섯 번의 결과가 [94.2, 93.8, 94.5, 93.1, 94.0]으로 나왔습니다.
평균 93.9%, 표준 편차 0.5%입니다. 박시니어 씨가 말했습니다.
"이 정도 편차면 안정적인 모델이에요."
실전 팁
💡 - 보통 5-폴드 또는 10-폴드를 사용합니다
- 데이터가 적을 때는 Leave-One-Out 교차 검증을 고려하세요
9. 모델 저장과 배포
드디어 모델 개발이 완료되었습니다. 이제 이 모델을 실제 서비스에 배포해야 합니다.
김개발 씨는 학습한 모델을 어떻게 저장하고, 어떻게 불러와서 사용해야 할지 고민했습니다.
모델 저장은 학습이 완료된 모델을 파일로 저장하여 나중에 재사용하는 것입니다. XGBoost는 여러 저장 형식을 지원합니다.
JSON과 바이너리 형식으로 저장할 수 있고, pickle이나 joblib을 사용할 수도 있습니다. 저장된 모델은 다른 환경에서도 불러와 예측에 사용할 수 있습니다.
다음 코드를 살펴봅시다.
import xgboost as xgb
import joblib
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
# 모델 학습
X, y = load_iris(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
model = xgb.XGBClassifier(n_estimators=100, max_depth=3)
model.fit(X_train, y_train)
# 방법 1: XGBoost 내장 저장 (권장)
model.save_model('model.json') # JSON 형식
model.save_model('model.ubj') # 바이너리 형식
# 방법 2: joblib 사용
joblib.dump(model, 'model.joblib')
# 모델 불러오기
loaded_model = xgb.XGBClassifier()
loaded_model.load_model('model.json')
# 불러온 모델로 예측
predictions = loaded_model.predict(X_test)
print(f"예측 완료: {len(predictions)}개 샘플")
모델을 학습하는 데 몇 시간이 걸렸습니다. 서버를 재시작할 때마다 다시 학습하는 것은 비효율적입니다.
학습된 모델을 저장해두고, 필요할 때 불러와서 사용해야 합니다. XGBoost는 두 가지 내장 저장 형식을 제공합니다.
JSON 형식은 사람이 읽을 수 있는 텍스트 파일입니다. 모델의 구조를 직접 확인할 수 있어서 디버깅에 유용합니다.
바이너리 형식(.ubj)은 더 빠르고 파일 크기도 작습니다. save_model 메서드로 모델을 저장합니다.
파일 확장자에 따라 형식이 자동으로 결정됩니다. .json이면 JSON 형식으로, .ubj나 .bin이면 바이너리 형식으로 저장됩니다.
load_model 메서드로 저장된 모델을 불러옵니다. pickle이나 joblib도 사용할 수 있습니다.
하지만 XGBoost 버전이 다르면 호환성 문제가 발생할 수 있습니다. XGBoost 내장 형식은 버전 간 호환성이 더 좋습니다.
가능하면 내장 형식을 사용하는 것을 권장합니다. 실제 배포 환경에서는 여러 가지를 고려해야 합니다.
첫째, 모델 버전 관리입니다. 새 모델을 배포할 때 이전 모델을 백업해두어야 합니다.
문제가 생기면 롤백할 수 있어야 합니다. 둘째, 모델 용량입니다.
트리가 많거나 깊으면 모델 파일이 커집니다. API 서버에서 모델을 사용할 때는 시작 시 한 번만 로드합니다.
매 요청마다 로드하면 성능이 크게 저하됩니다. Flask나 FastAPI 같은 프레임워크에서 전역 변수로 모델을 관리하는 것이 일반적입니다.
Docker 컨테이너로 배포할 때 모델 파일을 이미지에 포함시킬 수 있습니다. 또는 S3 같은 스토리지에 모델을 저장하고, 컨테이너 시작 시 다운로드하는 방식도 있습니다.
후자는 모델 업데이트가 더 유연합니다. 주의할 점이 있습니다.
모델을 저장할 때 전처리 파이프라인도 함께 저장해야 합니다. 스케일러, 인코더 등이 없으면 새로운 데이터를 제대로 처리할 수 없습니다.
sklearn의 Pipeline을 사용하면 모든 것을 한 번에 저장할 수 있습니다. 김개발 씨는 모델을 JSON 형식으로 저장했습니다.
파일을 열어보니 트리 구조가 그대로 보였습니다. 나중에 문제가 생기면 디버깅에 도움이 될 것 같았습니다.
이제 진짜 서비스에 배포할 준비가 끝났습니다.
실전 팁
💡 - 프로덕션에서는 XGBoost 내장 형식(.json 또는 .ubj)을 권장합니다
- 전처리 파이프라인도 함께 저장하는 것을 잊지 마세요
10. GPU 가속 활용하기
데이터가 점점 커지면서 학습 시간이 몇 시간씩 걸리기 시작했습니다. 팀장님이 물었습니다.
"GPU 서버 쓸 수 있는데, XGBoost도 GPU 쓸 수 있나요?" 김개발 씨는 GPU 가속에 대해 알아보기로 했습니다.
XGBoost는 GPU 가속을 지원합니다. tree_method 파라미터를 'gpu_hist'로 설정하면 GPU를 사용하여 학습 속도를 크게 향상시킬 수 있습니다.
특히 대용량 데이터나 복잡한 모델에서 효과가 큽니다. CUDA가 설치된 환경에서 사용할 수 있습니다.
다음 코드를 살펴봅시다.
import xgboost as xgb
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
import time
# 대용량 데이터 생성
X, y = make_classification(n_samples=100000, n_features=50)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
# CPU 학습
start = time.time()
cpu_model = xgb.XGBClassifier(
n_estimators=100,
max_depth=6,
tree_method='hist' # CPU 히스토그램 방식
)
cpu_model.fit(X_train, y_train)
cpu_time = time.time() - start
print(f"CPU 학습 시간: {cpu_time:.2f}초")
# GPU 학습 (CUDA 필요)
start = time.time()
gpu_model = xgb.XGBClassifier(
n_estimators=100,
max_depth=6,
tree_method='gpu_hist', # GPU 사용
gpu_id=0 # GPU 장치 ID
)
gpu_model.fit(X_train, y_train)
gpu_time = time.time() - start
print(f"GPU 학습 시간: {gpu_time:.2f}초")
머신러닝에서 GPU를 떠올리면 딥러닝이 먼저 생각납니다. 하지만 XGBoost도 GPU의 병렬 처리 능력을 활용할 수 있습니다.
대용량 데이터를 다룰 때 GPU 가속은 게임 체인저가 될 수 있습니다. GPU는 마치 수천 명의 단순 노동자와 같습니다.
복잡한 일은 못하지만, 단순한 일을 동시에 처리하는 능력은 탁월합니다. 트리를 만드는 과정에서 수많은 분할점을 평가해야 하는데, 이 작업을 병렬로 처리하면 속도가 크게 향상됩니다.
**tree_method='gpu_hist'**가 핵심 설정입니다. 히스토그램 기반의 트리 학습 알고리즘을 GPU에서 실행합니다.
히스토그램 방식은 연속값을 구간으로 나누어 처리하므로 GPU의 특성에 잘 맞습니다. GPU를 사용하려면 NVIDIA GPU와 CUDA가 설치되어 있어야 합니다.
xgboost를 설치할 때 GPU 버전을 설치해야 합니다. conda를 사용한다면 conda install -c conda-forge xgboost로 설치하고, CUDA 버전에 맞는 패키지가 자동으로 선택됩니다.
코드에서 gpu_id 파라미터로 사용할 GPU를 지정합니다. 서버에 여러 GPU가 있다면 0, 1, 2 등으로 선택할 수 있습니다.
기본값은 0입니다. 여러 GPU를 동시에 사용하는 것은 아직 제한적으로 지원됩니다.
속도 향상 폭은 데이터와 모델에 따라 다릅니다. 일반적으로 데이터가 클수록, 트리가 깊을수록 GPU의 이점이 큽니다.
작은 데이터에서는 GPU 오버헤드 때문에 오히려 느려질 수 있습니다. 10만 건 이상의 데이터에서 효과가 두드러집니다.
실무에서 GPU 가속은 두 가지 상황에서 특히 유용합니다. 첫째, 하이퍼파라미터 튜닝입니다.
수백 번의 학습을 반복해야 하므로 각 학습이 빨라지면 전체 시간이 크게 줄어듭니다. 둘째, 실시간 재학습입니다.
새로운 데이터로 모델을 빠르게 업데이트해야 할 때 유용합니다. 주의할 점도 있습니다.
GPU 메모리가 부족하면 오류가 발생합니다. 배치 크기를 줄이거나, 작은 샘플로 먼저 테스트해보는 것이 좋습니다.
또한 GPU 학습 결과와 CPU 학습 결과가 미세하게 다를 수 있습니다. 부동소수점 연산의 차이 때문입니다.
김개발 씨가 GPU 서버에서 코드를 실행했습니다. 2시간 걸리던 학습이 10분으로 줄었습니다.
하이퍼파라미터 튜닝도 하룻밤이면 충분했습니다. GPU의 힘을 실감한 순간이었습니다.
실전 팁
💡 - GPU 메모리 부족 시 max_bin 파라미터를 줄여보세요
- 작은 데이터에서는 CPU가 더 빠를 수 있으니 벤치마크해보세요
이상으로 학습을 마칩니다. 위 내용을 직접 코드로 작성해보면서 익혀보세요!
댓글 (0)
함께 보면 좋은 카드 뉴스
Helm 마이크로서비스 패키징 완벽 가이드
Kubernetes 환경에서 마이크로서비스를 효율적으로 패키징하고 배포하는 Helm의 핵심 기능을 실무 중심으로 학습합니다. Chart 생성부터 릴리스 관리까지 체계적으로 다룹니다.
보안 아키텍처 구성 완벽 가이드
프로젝트의 보안을 처음부터 설계하는 방법을 배웁니다. AWS 환경에서 VPC부터 WAF, 암호화, 접근 제어까지 실무에서 바로 적용할 수 있는 보안 아키텍처를 단계별로 구성해봅니다.
AWS Organizations 완벽 가이드
여러 AWS 계정을 체계적으로 관리하고 통합 결제와 보안 정책을 적용하는 방법을 실무 스토리로 쉽게 배워봅니다. 초보 개발자도 바로 이해할 수 있는 친절한 설명과 실전 예제를 제공합니다.
AWS KMS 암호화 완벽 가이드
AWS KMS(Key Management Service)를 활용한 클라우드 데이터 암호화 방법을 초급 개발자를 위해 쉽게 설명합니다. CMK 생성부터 S3, EBS 암호화, 봉투 암호화까지 실무에 필요한 모든 내용을 담았습니다.
AWS Secrets Manager 완벽 가이드
AWS에서 데이터베이스 비밀번호, API 키 등 민감한 정보를 안전하게 관리하는 Secrets Manager의 핵심 개념과 실무 활용법을 배워봅니다. 초급 개발자도 쉽게 따라할 수 있도록 실전 예제와 함께 설명합니다.