본문 바로가기

데이터와 함께 탱고를/머신러닝

Gradient Boost

이 글은 StatQuest with Josh Starmer 의 StatQuest: Gradient Boost Part1 영상을 보고 정리한 글이다.
모든 사진과 설명에 대한 출처는 여기에 있다.

이번 글에서는, Boosting 중, 비교적 최근에 많이 쓰이는 Gradient Boost 에 대해 정리해보려고 한다.
Kaggle 에서 많이보이는 XGboost 와 Light GBM 이 Gradient Boost 를 바탕으로 나온 모델이다.
사실상 현재 제일 많이쓰이는 Tree 계열의 모델을 이해하는데 기초적인 지식을 쌓는다고 볼 수 있다.

 

1. AdaBoost 다시 상기해보기.

Gradient Boosting 은 이전에 포스팅한 AdaBoost 와 비슷한 부분이 있기 때문에, 먼저 AdaBoost 를 빠르게 상기하고 넘어가자.

AdaBoost 의 핵심은 다음과 같았다.

  1. Stump 중, Gini Impurity 가 낮은 Stump 를 택하여, 먼저 예측한 뒤,
  2. 데이터셋의 Sample Weight 를 업데이트 시키고,
  3. 이 Sample Weight 을 고려하여 새로운 데이터셋을 만든 후,
  4. 다시 이 데이터셋으로, 트리가 완성될 때까지 1~3을 반복한다.

즉, 핵심은 Stump 와 Sample Weight 의 개념이었다.

 

2. Gradient Boost

Gradient Boost (GB 라 부르겠다.) 는 시작부터 조금 다른데, Stump 가 아닌, 하나의 Leaf Node 로 시작한다.

그리고 이 Leaf Node 의 값은, 초기 예측 값이다.
이 값을 바탕으로, 새로운 Tree 를 만들고, 또 그 값을 바탕으로 Tree 를 만들고... 
하는 식으로, Tree 를 점점 생성할 수록, 성능이 더 향상되는 (더 잘 예측하는) 모델이 된다.

이러한 과정은 마치 AdaBoost 와 비슷하다.
다만, Stump 가 아닌 Tree 를 만들어 나간다는 점이 다르다.

자 이제 구체적으로, 어떻게 모델을 형성하고, 작동해나가는지 살펴보자.

 

3. 과정

3.1. 최초, 평균값으로 예측

자 먼저, 다음과 같은 상황이라 해보자.
데이터셋에서, 각 데이터는 한 사람의 Height, Favorite Color, Gender, Weight 값을 가지고 있고,
앞의 3개의 Feature 로 Weight 를 예측해야하는 상황이다.

Weight 를 '일반적'으로 예측하는 가장 간단한 방법은, 먼저 Weight 의 평균 값으로 예측하는 것이다.
GB 는 최초에, 데이터셋에서 Target (여기서 Weight) 의 평균을 예측 값으로 둔다.
계산하면, 71.2 라는 값이 나온다.

3.2. 예측 값과 실제 값의 오차 구하기

우리는 모든 데이터의 예측 값을 71.2 로 예측했다.
당연히, 오차가 매우 클 수밖에 없다. 이 오차(Resiudal)들을 데이터마다 계산해보면 다음과 같다.
예를 들어, 첫 데이터의 경우 88 - 71.2 = 16.8 과 같이 계산한다.

3.3. 오차 값을 예측하는 Tree 만들기

그 다음으로 해야할 일은, 이렇게 계산한 오차(Resiudal) 을, 데이터셋의 Feature 를 가지고 Tree 를 만들어 예측하는 것이다.

왜 Residuals 를 예측하지? 이상한데.. 라고 생각할 수 있다. 당연하다.
하지만 왜 이렇게 하는지, 나중에 정리할 때 보면 이해할 수 있다.
일단 따라가보자.

DT (Decison Tree) 를 만들 때 처럼, 마찬가지로 Tree 를 만들면 다음과 같이 된다.

기존 데이터셋으로 DT 를 만들어 분류하면, 위와 같은 모델이 된다.
이 때, Leaf Node (초록색 노드)에는 분류된 값들이 여러개가 있는 경우가 있는데, 이 값들은 평균을 내주어, 하나의 값으로 대체하자.

드디어 진짜 Tree 하나가 완성되었다.
이제, 우리는 이 Tree 를 가지고 기존의 예측 값(71.2) 보다 더 나은 값으로 예측해보려 한다.
이는 다음과 같이 한다.

먼저, 데이터셋의 첫 번째 데이터를 보자.
Height 은 1.6이고 Favorite Color 는 Blue 이며, Gender 는 Male 이다.
Tree 에서 이 데이터는 다음과 같이 16.8로 오차(Residual) 가 나온다. (이 데이터셋을 가지고 훈련했으므로 당연하다.)

3.4. Learning rate 적용하여, 기존 예측 값 업데이트 하기

이제 이 오차값(16.8) 을 원래 예측값(71.2)에 더해주어, 원래 예측값을 업데이트 시켜주려고 한다.
그런데, 그냥 더해주면 71.2 + 16.8 = 88 이다. 원래 Weight 값과 동일하다.
그냥 더해주면, 기존 데이터셋 에는 완벽히 fitted 하겠지만, 새로운 데이터셋에는 잘 안맞을 가능성이 높다.
즉, 모델이 overfitting 되고, 다른 말로 모델의 variance 가 높아진다는 말이다.

이에 대안 방안으로, 그대로 더하지 않고 learning rate 만큼만 더해준다.
여기서 learning rate 은 0.1로 두었다.
다음을 보자.

16.8을 그대로 더하는게 아니라, 0.1을 곱해서 더한다.
그리고, 업데이트된 예측 값은 72.9가 되었다. (71.2 -> 72.9 로 변환)
원래 값이 88 임을 생각해보자.
완벽히 fitted 한 것은 아니지만, 이전보다는 오차가 줄어들었다!

자 이제 다시 이렇게 업데이트한 예측한 값으로 오차 역시 업데이트 한다.
예를 들어, 첫 번째 데이터의 오차는 88 - 72.9 = 15.1 이 될 것이다.

이런식으로 모든 오차를 다 업데이트하고, 이를 기반으로 또 새로운 Tree 를 만든다.

이렇게 만들어진 Tree 의 각각의 Leaf Node 도 하나의 값이 되도록 평균으로 대체 해준다. (이전과 동일한 과정이다.)

또 이렇게 나온 값들을 기반으로, 기존 예측 값을 learning rate 를 먹여, 또 다시 새로운 예측 값으로 업데이트 할 수 있다.
예를 들어 첫 번째 데이터는 다음과 같이 업데이트할 수 있다.

그렇다. 새로 업데이트 한 예측 값은 74.4 가 된다.
예측 값은 점점 원래 값 88에 가까워지고, 오차는 점점 줄어든다.

Gradient Boost 는 설정해놓은 탈출 조건 전까지, 이러한 과정의 반복이고,
이 과정 속에서, 원래 값에 완전히 fitted 되지는 않지만, 점점 원래 값에 가까워지게 한다.
즉, High Variance 를 피하면서, 조금씩 조금씩 학습해나가는 것이다.
여기에, Gradient Boost 의 Gradient 의 의미가 바로 여기에 있다.

3.5. 전체적인 구조

정리하면, 구조와 과정은 다음의 형태를 띄게된다.

 

4. 정리

과정을 정리하면 다음과 같다.

  1. 초기에는 평균값으로 모든 예측 값을 예측한다.
  2. 실제 값과 오차를 구해, 해당 오차를 예측하는 Tree 를 만든다.
  3. 기존 예측 값에 오차 * learning rate 를 더해서, 새로운 예측 값으로 업데이트 한다.
  4. 이 과정을 일정 Loop 동안 반복한다.

사실 보다 정확한 알고리즘 정리는 다음 사진인데....


여기서 이를 제대로 정리해보는거는 너무 어려운 일인 것 같아 생략한다.
Gradient Boost Part 2: Regression Details, 이 동영상에 아주 자세하고 친절히 설명해주니, 궁금하면 보면 좋을 것 같다.

 

5. 핵심 키워드

  • 오차(Residual) 로 만들어진 Tree
  • Learning Rate