Skip to content

6장. 질문의 나무 — 트리와 앙상블

이 장의 질문: 점수 합산이 아닌 다른 방식으로도 배울 수 있는가? 스무고개식 학습기(결정 트리)를 이해하고, 평범한 학습기 여럿을 묶어 강력한 하나로 만드는 앙상블의 원리 — 그리고 왜 이것이 테이블 데이터의 현재 챔피언인지를 배운다.

전제: 4장(과적합, 편향-분산), 5장(분류).

스무고개로 배우기

의사가 환자를 진단하는 방식을 떠올려 보라. "열이 있습니까?" — 예. "기침은요?" — 아니오. "발진이 있습니까?" — 예. 질문마다 가능성의 공간이 절반씩 잘려 나가고, 몇 번의 갈림길 끝에 진단이 나온다.

결정 트리(decision tree)는 정확히 이 구조를 데이터에서 배운다. 뿌리에서 시작해 "특징 하나에 대한 예/아니오 질문"으로 데이터를 두 갈래로 쪼개고, 각 갈래에서 또 쪼개기를 반복해, 잎(말단)에 도착하면 그 잎에 모인 훈련 데이터의 다수결(분류) 또는 평균(회귀)으로 답한다.

그렇다면 학습이란 어떤 질문을 어떤 순서로 던질 것인가를 정하는 일이다. 좋은 질문의 기준은 직관적이다 — 쪼갠 뒤 각 갈래가 최대한 순수해지는(한 클래스로 쏠리는) 질문이 좋은 질문이다. 순수함의 반대, 즉 뒤섞임의 정도를 재는 잣대가 지니 불순도나 엔트로피다. 숫자로 감을 잡자. 어떤 노드에 악성 50 : 양성 50이 섞여 있다(최악의 혼돈). 질문 A로 쪼갰더니 (45:5)와 (5:45)가 됐다 — 거의 순수해졌으니 훌륭한 질문. 질문 B로 쪼갰더니 (25:25)와 (25:25)다 — 아무것도 나아지지 않은 무의미한 질문. 트리 학습 알고리즘은 매 노드에서 모든 특징의 모든 절단점을 훑어 불순도를 가장 많이 줄이는 질문을 탐욕적으로 고른다. 그게 전부다.

트리의 미덕은 뚜렷하다. 사람이 읽을 수 있고(경로가 곧 규칙이다 — "열 있음 그리고 발진 있음이면 홍역 의심"), 특징의 크기 조정이 필요 없으며(질문은 대소 비교일 뿐이라 단위에 무관하다), 숫자·범주가 뒤섞인 지저분한 현실 데이터를 개의치 않는다.

그리고 치명적 약점이 하나 있다. 혼자 두면 반드시 과적합한다. 쪼개기를 막지 않으면 트리는 잎마다 훈련 데이터 한두 개만 남을 때까지 자라서 훈련 집합을 통째로 암기한다 — 4장에서 배운 고분산 모델의 전형이다. 게다가 데이터가 조금만 바뀌어도 초반 질문이 바뀌고, 초반 질문이 바뀌면 트리 전체가 뒤바뀐다. 깊이 제한이나 가지치기로 달랠 수는 있지만, 진짜 해법은 다른 데서 왔다.

앙상블: 불안정함을 무기로

여기서 머신러닝 역사상 가장 우아한 반전이 나온다. 트리의 약점 — 데이터에 민감해 이리저리 흔들리는 고분산 — 을 고치는 대신 이용하는 것이다.

핵심 통찰은 통계학의 오래된 사실이다. 서로 독립적인 추정치들을 평균내면 분산이 줄어든다. 동전을 한 번 던지면 앞면 비율이 0 아니면 1이지만, 천 번 던져 평균내면 0.5 근처에 안정적으로 모인다. 오차도 마찬가지다 — 각자 다른 방향으로 틀리는 모델 100개를 평균내면, 오차들이 서로 상쇄되어 평균은 진실 근처에 남는다.

문제는 "서로 다르게 틀리는" 모델 100개를 어디서 구하느냐다. 같은 데이터로 같은 알고리즘을 100번 돌리면 똑같은 모델 100개가 나올 뿐이다. 두 가지 해법이 두 가지 계보를 낳았다.

배깅(bagging)과 랜덤 포레스트 — 무작위로 다르게 만든다. 훈련 데이터에서 중복을 허용해 무작위로 다시 뽑은(부트스트랩) 표본으로 트리를 하나씩 키운다. 표본이 다르니 트리가 다르다. 랜덤 포레스트는 한 술 더 떠, 각 갈림길에서 특징도 무작위 일부만 후보로 준다 — 지배적인 특징 하나가 모든 트리의 첫 질문을 독점해 트리들이 닮아 버리는 것을 막는 장치다. 트리 수백 그루의 다수결/평균이 최종 답이다. 트리가 예민할수록(깊을수록) 개별 분산은 크지만 평균이 그것을 지워 준다 — 고분산 학습기의 분산을 평균으로 죽이는 전략이다. 튜닝에 둔감하고 병렬화가 쉬워, "일단 기준선부터"라는 상황의 최고의 친구다.

부스팅(boosting) — 실수를 순서대로 보완한다. 반대 철학이다. 이번엔 얕은(약한) 트리에서 시작한다. 첫 트리가 예측하고, 두 번째 트리는 첫 트리가 틀린 만큼(잔차) 을 예측하도록 학습하고, 세 번째는 남은 오차를… 이렇게 이어 붙인 합이 최종 모델이다. 각 단계가 이전까지의 부족함을 메우므로, 이것은 저표현력 학습기의 편향을 누적으로 깎는 전략이다. 그리고 여기에 2장의 렌즈를 대면 아름다운 그림이 보인다 — "잔차를 맞추는 트리를 더한다"는 것은 사실 함수 공간에서의 경사하강이다. 파라미터를 기울기 반대로 옮기는 대신, 모델 자체에 "손실을 줄이는 방향의 작은 함수"를 한 조각씩 더해 가는 것. 그래서 이 계보의 이름이 그래디언트 부스팅(gradient boosting)이다.

두 전략의 대비를 표로 새겨 두자.

배깅 / 랜덤 포레스트부스팅 (GBDT)
재료깊은 트리 (저편향·고분산)얕은 트리 (고편향·저분산)
결합독립 학습 후 평균 (병렬)잔차를 순차 보완 (직렬)
깎는 것분산편향
성격튜닝에 둔감, 견고튜닝하면 더 강함, 과적합 주의

테이블 데이터의 챔피언

그래디언트 부스팅을 고도로 최적화한 구현체들 — XGBoost, LightGBM, CatBoost — 은 지난 10년간 정형(테이블) 데이터 예측 대회를 사실상 지배했다. 딥러닝 전성시대에 의아하게 들릴 수 있으니, 이유를 정확히 짚자.

이미지의 픽셀은 균질하다 — 모든 입력이 같은 종류(밝기)이고 이웃끼리 강한 구조가 있다. 딥러닝은 그런 구조를 파고드는 데 최적화되어 있다(13장). 반면 테이블의 열들은 이질적이다 — 나이, 연봉, 가입일, 지역 코드가 한 줄에 섞여 있고 열 사이에 공간적 구조가 없다. 이런 데이터에서는 "연봉이 5천만 원 이상인가?" 같은 절단식 질문이 매우 자연스러운 가설 형태이고, 그것이 정확히 트리의 언어다. 게다가 GBDT는 수만 건 규모에서도 몇 초 만에 학습되고, 결측치를 태연히 다루며, 특징 중요도로 "무엇이 예측을 끌고 가는지"를 보여준다.

실무 감각으로 정리하면: 이미지·음성·텍스트는 딥러닝, 테이블은 GBDT부터. 이 한 줄이 수많은 시행착오를 줄여 줄 것이다.

써 보자. 코드는 허무할 만큼 짧다.

python
from sklearn.datasets import fetch_california_housing
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestRegressor, HistGradientBoostingRegressor

X, y = fetch_california_housing(return_X_y=True)     # 캘리포니아 집값 (2만 건, 특징 8개)
X_tr, X_te, y_tr, y_te = train_test_split(X, y, test_size=0.2, random_state=42)

rf = RandomForestRegressor(n_estimators=300, n_jobs=-1).fit(X_tr, y_tr)
gb = HistGradientBoostingRegressor(max_iter=300).fit(X_tr, y_tr)
print(f"랜덤 포레스트 R²: {rf.score(X_te, y_te):.3f}")   # ~0.81
print(f"그래디언트 부스팅 R²: {gb.score(X_te, y_te):.3f}") # ~0.84

# 무엇이 집값을 끌고 가는가 — 특징 중요도
for name, imp in sorted(zip(fetch_california_housing().feature_names,
                            rf.feature_importances_), key=lambda t: -t[1])[:3]:
    print(f"{name}: {imp:.3f}")

같은 데이터에 5장의 선형 회귀를 돌려 비교해 보라(R² ~0.58). 비선형 상호작용 — "소득이 높아도 위도에 따라 효과가 다르다" 같은 관계 — 을 트리 앙상블이 자동으로 잡아내는 것을 성적 차이로 확인할 수 있다.

부스팅을 튜닝할 때의 핵심 다이얼은 세 개다. 트리 개수(많을수록 강하지만 과적합 방향), 학습률(각 트리의 기여를 줄여 천천히 배우게 — 작게 하고 트리를 늘리는 것이 정석), 트리 깊이(보통 3~8의 얕은 트리). 그리고 4장의 규율 그대로 — 검증 성적이 꺾이는 지점에서 멈춘다(조기 종료).

핵심 요약

  • 결정 트리는 "불순도를 가장 많이 줄이는 질문"을 탐욕적으로 골라 데이터를 쪼개 나가는 학습기다. 읽기 쉽고 전처리에 둔감하지만, 혼자 두면 암기(고분산)한다.
  • 앙상블: 서로 다르게 틀리는 모델들을 결합하면 오차가 상쇄된다. 배깅/랜덤 포레스트는 깊은 트리들의 분산을 평균으로 깎고, 부스팅은 얕은 트리들로 편향을 순차적으로 깎는다.
  • 그래디언트 부스팅은 "잔차를 맞추는 트리를 더하는" 함수 공간의 경사하강이다. XGBoost/LightGBM 계열은 테이블 데이터의 현재 챔피언이다.
  • 실무 어림법: 이미지·음성·텍스트 → 딥러닝. 테이블 → GBDT부터.

스스로 점검

  1. 노드에 A:B = 40:40이 섞여 있다. 질문 ①은 (40:10)/(0:30)으로, 질문 ②는 (20:20)/(20:20)으로 쪼갠다. 어느 질문이 좋은가? 그 이유를 "순수해짐"으로 설명해 보라.
  2. 랜덤 포레스트가 "각 갈림길에서 특징 일부만 후보로 준다"는 규칙을 빼면 무엇이 나빠지는가? (힌트: 평균이 분산을 줄이려면 무엇이 전제되어야 하나?)
  3. 배깅에는 깊은 트리를, 부스팅에는 얕은 트리를 쓰는 이유를 편향-분산의 언어로 각각 설명해 보라.
  4. 당신에게 고객 이탈 예측 문제(엑셀 형태, 10만 행, 열 30개)가 주어졌다. 첫 시도로 무엇을 쓰겠는가, 왜인가?

다음 장에서

지금까지는 늘 정답이 달린 데이터였다. 그런데 세상 데이터의 대부분에는 정답표가 없다. 정답 없이 데이터의 구조 자체 — 무리, 방향, 압축 — 를 찾아내는 비지도학습으로 간다. 그리고 거기서 배울 "표현을 압축한다"는 아이디어는 훗날 생성 모델(6부)의 씨앗이 된다.

7장. 정답 없이 배우기 →