다시 살펴보는 머신러닝 주요 개념 3편 – 주요 머신러닝 모델

경진대회를 푸는 데 필요한 주요 머신러닝 개념들을 요약·정리해뒀습니다. 머신러닝 이론을 기초부터 차근히 설명하려는 목적이 ‘아니므로’ 정독하실 필요는 없습니다. 문제를 풀다가 언뜻 떠오르지 않는 개념이 있을 때 참고해주세요. 총 4편으로 준비했습니다. 3편에서는 주요 머신러닝 모델을 정리했습니다. 캐글에서 가장 인기 있는 머신러닝 모델은 XGBoost와 LightGBM입니다. 또한, 비록 많이 쓰이지는 않더라도 기본적인 모델들도 알아두면 좋습니다. 이번 글에서 알아볼 모델들은 다음과 같습니다.

  • 선형 회귀
  • 로지스틱 회귀
  • 결정 트리
  • 앙상블 학습
  • 랜덤 포레스트
  • XGBoost
  • LightGBM

 

1. 선형 회귀 모델

선형 회귀(Linear Regression) 모델은 선형 회귀식4을 활용한 모델입니다. 선형 회귀 모델을 훈련한다는 것은 훈련 데이터에 잘 맞는 모델 파라미터, 즉 회귀계수를 찾는 것입니다.

코드로 선형 회귀 모델을 구현해보겠습니다. 데이터 생성 → 모델 훈련 → 회귀선 그래프 확인 순서로 진행하겠습니다.

 

1.1 데이터 생성

먼저 단순 선형 회귀식 y=2x+5에 근사하는 데이터 100개를 만들겠습니다.

import numpy as np
import matplotlib.pyplot as plt

np.random.seed(0) # 시드값 고정

w0 = 5 # y절편
w1 = 2 # 회귀 계수
noise = np.random.randn(100, 1) # 노이즈

x = 4 * np.random.rand(100, 1) # 0 ~ 4 사이 실수값 100개 생성 (x값)
y = w1*x + w0 + noise # y값

plt.scatter(x, y);

np.random.randn(100, 1)은 표준 정규분포를 따르는 데이터 100개를 생성하는 코드입니다. 데이터에 노이즈를 주기 위해 필요합니다. 에서 np.random.rand(100, 1)은 0~1 사이의 무작위 값을 100개 생성합니다. 독립변수 x값 100개를 만드는 코드입니다.

▼ 실행 결과(무작위로 생성한 선형 회귀 모델 데이터)

이상으로 노이즈가 조금 있는 데이터셋을 생성했습니다. y = 2x + 5 에 근사하는 데이터입니다.

 

1.2 모델 훈련

이 데이터를 이용해 선형 회귀 모델을 훈련해보겠습니다. 모델을 훈련하면 적절한 회귀계수와 y절편 값을 찾아줄 겁니다.

from sklearn.linear_model import LinearRegression

linear_reg_model = LinearRegression() # 선형 회귀 모델
linear_reg_model.fit(x, y) # 모델 훈련

print('y절편(w0):', linear_reg_model.intercept_)
print('회귀계수(w1):', linear_reg_model.coef_)

y절편(w0): [5.09772262]

회귀계수(w1): [[1.9808382]]

❶ y절편 값은 LinearRegression 모델의 intercept_ 속성에, ❷ 회귀계수 값은 coef_ 속성에 저장되어 있습니다. 이 값들을 출력해보니 훈련을 마친 모델의 y절편은 5.0977이고, 회귀계수는 1.9808입니다. 실제 y절편은 5, 실제 회귀계수는 2이므로 근사하게 잘 예측했네요.

 

1.2 회귀선 확인

이제 훈련한 선형 회귀 모델의 회귀선을 그려보겠습니다. 회귀선을 그리기 위해 예측값을 이용하겠습니다.

y_pred = linear_reg_model.predict(x) # 예측

plt.scatter(x, y)
plt.plot(x, y_pred); # 선형 회귀선 그리기

▼ 실행 결과(선형 회귀 모델의 회귀선)

 

회귀선이 잘 그려졌네요. 지금까지 임의로 데이터를 생성해 선형 회귀 모델을 훈련해봤습니다. 캐글 경진대회에서 단순 선형 회귀 모델을 사용할 일은 거의 없겠지만, 가장 간단한 모델이므로 기본 차원에서 알아봤습니다.

 

 

2. 로지스틱 회귀 모델

로지스틱 회귀(Logistic Regression)는 선형 회귀 방식을 응용해 분류에 적용한 모델입니다. 가령, 스팸 메일일 확률을 구하는 이진 분류 문제에 로지스틱 회귀를 사용할 수 있습니다.

????Note: 이름이 로지스틱 ‘회귀’라서 회귀 문제 에 사용할 것 같지만, 분류 문제에 사용합니다.

로지스틱 회귀는 시그모이드 함수(sigmoid function)를 활용해 타깃값에 포함될 확률을 예측합니다. 시그모이드 함수식은 다음과 같습니다.

다음은 시그모이드 함수 그래프입니다. 그래프 모양이 S자죠? 영단어 sigmoid가 ‘S자 모양의’라는 뜻입니다.

▼ 시그모이드 함수 그래프(https://en.wikipedia.org/wiki/Logistic_regression)

시그모이드 함수는 0에서 1 사이 값을 갖습니다. x값이 작을수록 0에 가깝고, 클수록 1에 가깝습니다. x가 0일 땐 0.5이고요. 이 값을 그대로 확률로 해석하면 타깃값에 포함될 확률이 구해집니다.

타깃값 예측도 간단합니다. 이진 분류 문제에선 시그모이드 값(확률)이 0.5보다 작으면 0(음성), 0.5 이상이면 1(양성)이라고 예측합니다.

▼ 로지스틱 회귀 타깃값 예측

사이킷런에서 제공하는 로지스틱 회귀 모델은 LogisticRegression입니다. 다른 사이킷런 모델과 마찬가지로 predict( ) 함수로 타깃값을 예측할 수 있고, predict_proba( ) 함수로 타깃값일 확률을 예측할 수 있습니다.

▼ 로지스틱 회귀 요약

 

 

3. 결정 트리

‘의사결정 나무’라고도 하는 결정 트리(decision tree)는 분류와 회귀 문제에 모두 사용 가능한 모델입니다. 작동 원리는 간단합니다.

  1. 우선 데이터를 가장 잘 구분하는 조건을 정합니다.
  2. 조건을 기준으로 데이터를 두 범주로 나눕니다.
  3. 나뉜각범주의데이터를잘구분하는조건을다시정합니다.
  4. 조건에 따라 각 범주에 속한 데이터를 다시 분할합니다.
  5. 이런식으로계속분할해최종결정값을구합니다.

예를 들어보겠습니다. 아침에 눈을 떴을 때 일어날지 말지를 결정하는 상황을 생각해봅시다. 스스로에게 ‘주말인가?’, ‘7시가 넘었는가?’, ‘9시가 넘었는가?’, ‘피곤한가?’와 같은 질문을 하겠죠. 질문에 ‘예/아니오’로 대답해 최종 결정을 합니다. 다음은 이 상황을 결정 트리로 도식화한 그림입니다.

▼ 결정 트리 예시

마치 스무고개하는 방식과 비슷하죠? 결정 트리에서 첫 번째 노드(그림에서 가장 위에 있는 노드)를 뿌리 노드(root node)라고 하고, 조건이 담긴 중간층 노드를 중간 노드(intermediate node), 결정 값이 담긴 마지막 노드를 말단 노드(leaf node)라고 합니다.

 

3.1 결정 트리 분할 방식

결정 트리를 만들 때는 분할 조건이 중요합니다. 조건에 따라 분할 후 만들어지는 트리 모양(과 동작 효율)이 다르기 때문입니다. 다음은 동일한 데이터를 서로 다른 조건으로 분할하는 예입니다.

▼ 결정 트리 분할 방식 비교

 

▼ 불순도 정도

 

한 범주에 데이터 한 종류만 있다면 불순도가 최소(혹은 순도가 최대)고, 서로 다른 데이터가 같은 비율로 있다면 불순도가 최대(혹은 순도가 최소)입니다.

불순도를 측정하는 지표로는 엔트로피와 지니 불순도가 있으며, 결정 트리를 만들 때 선택할 수 있습니다. 엔트로피와 지니 불순도에 대해 간단히 알아볼까요?

엔트로피(entropy)란 ‘불확실한 정도’를 뜻합니다. 예를 들어 한 범주에 데이터가 한 종류만 있다면 엔트로피는 0입니다. 어떤 데이터를 고르든 그 종류를 ‘확실하게’ 말할 수 있기 때문이죠. 반대로 서로 다른 데이터의 비율이 비등해질수록 엔트로피는 1에 가까워집니다. 다시 말해, 엔트로피 값이 클수록 불순도가 높고, 작을수록 불순도도 낮습니다. 1에서 엔트로피를 뺀 수치(1- 엔트로피)를 정보 이득(information gain)이라 하는데, 결정 트리는 정보 이득을 최대화하는 방향(엔트로피를 최소화하는 방향)으로 노드를 분할합니다.

지니 불순도(gini impurity)도 엔트로피와 비슷한 개념입니다. 지니 불순도 값이 클수록 불순도도 높고, 작을수록 불순도도 낮습니다. 엔트로피와 마찬가지로 지니 불순도가 낮아지는 방향으로 노드를 분할합니다.

 

3.2 결정 트리 구현

사이킷런으로 결정 트리를 구현할 수 있습니다. 분류용 모델은 DecisionTreeClassifier, 회귀용 모델은 DecisionTreeRegressor입니다. 여기서는 분류 모델인 DecisionTreeClassifier를 기준으로 결정 트리를 구현해보겠습니다. DecisionTreeClassifier의 파라미터는 다음과 같습니다.

  • criterion : 분할 시 사용할 불순도 측정 지표
    • ‘gini’를 전달하면 지니 불순도를 활용해 분할
    • ‘entropy’를 전달하면 정보 이득 방법으로 분할
    • 기본값 = ‘gini’
  • max_depth : 트리의 최대 깊이
    • max_depth를 규정하지 않으면 모든 말단 노드의 불순도가 0이 되거나 노드에 있는 데이터 수가 min_samples_split보다 작을 때까지 트리 깊이가 깊어짐
    • 기본값=None
  • min_samples_split : 노드 분할을 위한 최소 데이터 개수
    • 노드 내 데이터 개수가 이 값보다 작으면 더 이상 분할하지 않음
    • 정수형으로 전달하면 최소 데이터 개수를 의미함
    • 실수형으로 전달하면 전체 데이터 개수 중 최소 데이터 개수 비율을 의미. 예를 들어, 전체 데이터 개수가 100개인데 min_samples_split을 0.1로 지정했다면 10개가 노드 분할을 위한 최소 데이터 개수가 됨
    • 기본값 = 2
  • min_samples_leaf : 말단 노드가 되기 위한 최소 데이터 개수
    • 분할 후 노드 내 데이터 개수가 이 값보다 작으면 더 이상 분할하지 않음
    • 정수형으로 전달하면 최소 데이터 개수를 의미
    • 실수형으로 전달하면 전체 데이터 개수 중 최소 데이터 개수 비율을 의미
    • 기본값 = 1
  • max_features : 분할에 사용할 피처 개수
    • 정수형으로 전달하면 피처 개수를 의미
    • 실수형으로 전달하면 전체 피처 개수 중 분할에 사용될 피처 개수 비율을 의미
    • ‘auto’나 ‘sqrt’를 전달하면 ‘sqrt(전체 피처 개수)가 분할에 사용될 피처 개수임
    • ‘log2’를 전달하면 log2(전체 피처 개수)가 분할에 사용될 피처 개수임
    • None을 전달하면 전체 피처를 분할에 사용
    • 기본값 = None

결정 트리에 조건이 많을수록 분할이 많고 트리가 깊어집니다. 분할을 지나치게 많이 하면 모델이 1. 과대적합될 우려가 있으니 파라미터를 잘 조절해야 합니다. max_depth, min_samples_split, 1. min_samples_leaf가 결정 트리의 과대적합을 제어하는 파라미터입니다.

다음은 유방암 데이터셋으로 결정 트리 모델의 정확도를 측정하는 코드입니다.

from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_breast_cancer

# 유방암 데이터 세트 불러오기
cancer_data = load_breast_cancer()
# 훈련, 테스트 데이터로 분리
X_train, X_test, y_train, y_test = train_test_split(cancer_data['data'], 
                                                cancer_data['target'], 
                                                stratify=cancer_data['target'], 
                                                test_size=0.4, 
                                                random_state=42)

decisiontree = DecisionTreeClassifier(random_state=42) # 결정 트리 정의
decisiontree.fit(X_train, y_train) # 모델 훈련

accuracy = decisiontree.score(X_test, y_test) # 정확도 측정

# 테스트 데이터를 활용하여 결정 트리 모델 정확도 출력
print(f'결정 트리 정확도: {accuracy:.3f}')

결정 트리 정확도: 0.930

 

 

4. 앙상블 학습

우리는 제품을 구매할 때 다양한 후기를 보며 살지 말지를 정합니다. 후기를 하나만 보진 않죠? 가능한 한 많은 후기를 보고 제품에 대해 종합적으로 판단합니다. 문제를 풀 때도 한 명이 푸는 것보다 여러 명이 풀어서 서로 비교해보는 게 낫습니다. 전문가 한 명의 의견보다 여러 명의 종합 의견이 더 정확할 가능성이 큽니다.

머신러닝에서도 마찬가지며, 다양한 모델이 내린 예측 결과를 결합하는 기법을 앙상블 학습(ensemble learning)이라고 합니다. 앙상블 학습을 활용하면 대체로 예측 성능이 좋아집니다. 과대적합 방지 효과도 있고요. 그래서 캐글러들은 앙상블 기법을 많이 활용합니다.

앙상블 학습 유형으로는 보팅, 배깅, 부스팅 등이 있습니다. 하나씩 알아보겠습니다.

 

4.1 보팅

서로 다른 모델로 예측한 결과가 여럿 있다고 합시다. 개별 결과를 종합해 최종 결과를 결정하는 방식을 보팅(voting); 투표이라고 합니다. 보팅 기법은 하드 보팅과 소프트 보팅으로 나뉩니다.

하드 보팅(hard voting)은 ‘다수결 투표’ 방식으로 최종 예측값을 정합니다. 예를 들어 모델 세 개는 타깃값을 1로 예측하고, 모델 두 개는 0으로 예측했다고 합시다. 그러면 다수결에 의해 1이 최종 예측값으로 선정됩니다. 가장 많은 표를 얻은 개별 예측값을 최종 예측값으로 정한 겁니다.

▼ 하드 보팅

 

소프트 보팅(soft voting)은 개별 예측 확률들의 평균을 최종 예측 확률로 정하는 방식입니다.

▼ 소프트 보팅

 

그림에서 (0.5 + 0.7 + 0.9 + 0.6 + 0.8) / 5 = 0.7이므로 소프트 보팅 시 최종 예측값은 0.7이 됩니다.

일반적으로 소프트 보팅이 하드 보팅보다 성능이 좋아서, 대체로 소프트 보팅을 사용합니다.

 

4.2 배깅

배깅(bagging; 봉지에 담다)은 개별 모델로 예측한 결과를 결합해 최종 예측을 정하는 기법입니다. 배깅의 특징은 ‘개별 모델이 서로 다른 샘플링 데이터를 활용’한다는 점입니다.

  1. 전체 훈련 데이터셋에서 무작위 샘플링한 데이터로 개별 모델을 훈련합니다.
  2. 훈련된 개별 모델로 결과를 예측합니다.
  3. 개별 모델의 수만큼 1~2번 작업을 반복합니다.
  4. 각 모델이 예측한 값들을 보팅하여 최종 예측값을 구합니다.

▼ 배깅 방식

 

배깅은 원리가 간단하면서도 성능을 높일 수 있는 효과적인 기법입니다. 배깅 기법을 활용한 대표적인 모델이 랜덤 포레스트입니다.

 

4.3 부스팅

부스팅(boosting; 북돋우다)은 가중치를 활용해 분류 성능이 약한 모델을 강하게 만드는 기법입니다.

배깅은 결정 트리 1과 결정 트리 2가 서로 독립적으로 결과를 예측한 다음 보팅하여 최종 결과를 도출했습니다. 하지만 부스팅에서는 ‘모델 간 협력’이 이루어집니다. 예컨대, 이전 모델이 잘못 예측한 데이터에 가중치를 부여합니다. 다음 모델은 이전 모델이 잘못 예측한 데이터(가중치가 부여된 데이터)에 더 집중해 훈련합니다. 가중치가 부여된 데이터를 그만큼 더 중요하다고 판단해 더 잘 분류하려고 합니다. 이런 단계를 반복하면 모델 성능이 점차 향상됩니다. 다음 그림은 부스팅 방식으로 ‘+’와 ‘-’를 구분하는 예입니다. 부스팅 스텝이 총 세 번이라고 가정합니다.

▼ 부스팅 방식

 

부스팅 절차는 다음과 같습니다.

  1. ‘+’와 ‘-’로 구성된 원본 데이터셋을 준비합니다.
  2. 처음에는 모든 데이터에 동일한 가중치를 줍니다.
  3. 분류 모델 1로 ‘+’와 ‘-’를 분류합니다.
  4. 분류 모델 1이 잘못 분류한 데이터(동그라미 표시된 데이터)에 더 높은 가중치를 부여합니다.
  5. 분류 모델 2는 가중치가 부여된 데이터에 집중해 데이터를 분류합니다. 다른 데이터보다 가중치가 부여된 데이터를 더 제대로 구분하려고 노력한다는 말입니다.
  6. 분류 모델 2가 잘못 분류한 데이터에 더욱 높은 가중치를 부여합니다.
  7. 분류 모델 3은 이전 단계에서 가중치가 부여된 데이터에 집중해 데이터를 분류합니다.

이 절차대로 부스팅을 적용해 개별 분류 모델 3개를 구했습니다. 분류 모델 1, 2, 3을 결합하면 ‘+’와 ‘-’를 제대로 구분하는 모델을 만들 수 있습니다.

▼ 부스팅 훈련 시 최종 결합 모델

 

분류 모델 2는 분류 모델 1이 제대로 분류하지 못한 데이터를 더 잘 분류합니다. 마찬가지로 분류 모델 3은 분류 모델 2가 제대로 분류하지 못한 데이터를 더 잘 분류합니다. 이렇게 서로의 단점을 극복해나간 모델들을 최종적으로 결합하니 모든 ‘+’와 ‘-’를 제대로 구분하는 모델이 만들어졌습니다.

부스팅 기법을 활용한 대표적인 모델로는 5.6.6절의 XGBoost와 5.6.7절의 LightGBM 등이 있습니다.

 

 

5. 랜덤 포레스트

랜덤 포레스트를 이해하려면 결정 트리와 앙상블 학습을 알아야 합니다. ‘결정 트리’와 ‘앙상블 학습’을 참고하세요.

랜덤 포레스트(random forest)는 결정 트리를 배깅 방식으로 결합한 모델입니다. 나무(tree)가 모여 숲(forest)을 이루듯 결정 트리가 모여 랜덤 포레스트를 구성합니다. 결정 트리와 마찬가지로 랜덤 포레스트도 분류와 회귀 문제에 모두 적용 가능합니다.

랜덤 포레스트가 결과를 어떻게 예측하는지 살펴볼까요? 스팸 메일과 일반 메일을 구분하는 예를 보겠습니다. 배깅 방식의 예시이기도 합니다.

▼ 랜덤 포레스트 예측 방식

 

결정트리 A, B, C, D는 서로 다른 결정 트리입니다. ❶ 먼저 훈련 데이터셋에서 샘플링(복원추출)해서 훈련 데이터셋 A를 만듭니다. ❷ 결정 트리 A는 훈련 데이터셋 A를 활용해 훈련합니다. ❸ 테스트 데이터로 예측해서 스팸일 확률과 일반 메일일 확률을 구합니다. ❹ ****같은 방식으로 다른 결정 트리들도 훈련과 예측을 반복합니다.

각 결정 트리에서 사용하는 데이터는 전체 훈련 데이터에서 각자 샘플링합니다. 그렇기 때문에 결정 트리마다 훈련 데이터 샘플이 다릅니다. 단, 전체 훈련 데이터셋 수만큼 복원 추출하므로 샘플링한 데이터의 크기는 서로 같습니다.

❺ 마지막으로 네 개 확률의 평균을 냅니다. 스팸일 확률 평균은(40%+50%+70%+80%)/4= 60%입니다. 일반 메일일 확률 평균은 (60% + 50% + 30% + 20%) / 4 = 40%입니다. 이렇듯 결정 트리를 배깅 방식으로 결합해 랜덤 포레스트를 만듭니다.

 

5.1 랜덤 포레스트 구현

사이킷런으로 랜덤 포레스트를 구현할 수 있습니다. 분류 모델은 RandomForestClassifier, 회귀 모델은 RandomForestRegressor입니다. 여기서는 분류 모델을 구현해보겠습니다.

랜덤 포레스트는 결정 트리 묶음이라서 파라미터도 결정 트리와 거의 같습니다. RandomForestClassifier의 파라미터는 다음과 같습니다.

  • n_estimators : 랜덤 포레스트를 구성할 결정 트리 개수
    • 기본값=100
  • criterion : 분할 시 사용할 불순도 측정 지표
    • 세부 내용은 DecisionTreeClassifier와 동일
  • max_depth : 트리의 최대 깊이
    • 세부 내용은 DecisionTreeClassifier와 동일
  • min_samples_split : 노드 분할을 위한 최소 데이터 개수
    • 세부 내용은 DecisionTreeClassifier와 동일
  • min_samples_leaf : 말단 노드가 되기 위한 최소 데이터 개수
    • 세부 내용은 DecisionTreeClassifier와 동일
  • max_features : 분할에 사용할 피처 개수
    • 세부 내용은 DecisionTreeClassifier와 동일
    • 기본값 = ‘auto’

이제 랜덤 포레스트로 분류 문제를 풀어보겠습니다. 이번에도 결정 트리 구현 시 사용한 유방암 데이터셋을 사용합니다.

from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_breast_cancer

# 유방암 데이터 세트 불러오기
cancer_data = load_breast_cancer()
# 훈련, 테스트 데이터로 분리
X_train, X_test, y_train, y_test = train_test_split(cancer_data['data'], 
                                                cancer_data['target'], 
                                                stratify=cancer_data['target'], 
                                                test_size=0.4, 
                                                random_state=42)

randomforest = RandomForestClassifier(random_state=42) # 랜덤 포레스트 정의
randomforest.fit(X_train, y_train) # 모델 훈련

accuracy = randomforest.score(X_test, y_test) # 정확도 측정

# 테스트 데이터를 활용하여 랜덤 포레스트 모델 정확도 출력
print(f'랜덤 포레스트 정확도: {accuracy:.3f}')

랜덤 포레스트 정확도: 0.939

결정 트리를 사용할 때는 정확도가 0.930이었습니다. 랜덤 포레스트를 사용하니 정확도가 조금 높아졌네요.

 

 

6. XGBoost

XGBoost(extreme gradient boosting)는 성능이 우수한 트리 기반 부스팅 알고리즘입니다. 많은 캐글 우승자가 XGBoost를 사용할 정도로 성능이 좋은 모델이죠.

랜덤 포레스트는 결정 트리를 병렬로 배치하지만, XGBoost는 직렬로 배치해 사용합니다. 즉, 랜덤 포레스트는 배깅 방식, XGBoost는 부스팅 방식입니다. 부스팅 방식이기 때문에 직전 트리가 예측한 값을 다음 트리가 활용해서 예측값을 조금씩 수정합니다.

????Note: 다음 절에서 배울 LightGBM도 XGBoost와 마찬가지로 부스팅 방식입니다.

XGBoost의 주요 모듈은 C와 C++로 작성되었지만, 파이썬으로도 XGBoost를 사용할 수 있게 API를 제공합니다. 이를 ‘파이썬 래퍼 XGBoost’라고 하겠습니다. 반면, 사이킷런과 호환되는 XGBoost도 있는데 이를 ‘사이킷런 래퍼 XGBoost’라고 하겠습니다. 사이킷런 래퍼 XGBoost는 사이킷런에서 제공하는 fit( ), predict( ) 등의 메서드를 적용할 수 있습니다.

파이썬 래퍼 XGBoost와 사이킷런 래퍼 XGBoost, 둘 중 무엇을 사용하든 크게 상관없습니다. 다만 파이썬 래퍼 XGBoost를 사용하려면 별도 데이터셋을 생성해야 합니다. 그러면 모델 훈련 및 예측 부분이 더 명시적이게 됩니다. 따라서 이 책에서는 파이썬 래퍼 XGBoost로 설명하겠습니다.

파이썬 래퍼 XGBoost를 사용하려면 DMatrix 객체를 활용해 XGBoost 전용 데이터셋을 만들어야 합니다. xgboost.DMatrix( ) 파라미터는 다음과 같습니다.

  • data : xgboost.DMatrix용 데이터셋
    • 넘파이 배열, 판다스 DataFrame, scipy.sparse, os.PathLike, 문자열 타입을 전달할 수 있음(os.PathLike나 문자열이면 데이터 파일 경로를 의미)
  • label : 타깃값
    • 배열 타입을 전달할 수 있음

XGBoost 모델은 하이퍼파라미터가 많습니다. 주로 사용하는 파라미터는 다음과 같습니다. ****이 하이퍼파라미터들은 딕셔너리 형태로 train( ) 메서드의 params 파라미터에 전달하면 됩니다(XGBoost 1.4.2 기준).

  • booster : 부스팅 알고리즘
    • 트리 기반 모델일 때는 ‘gbtree’, ‘dart’를 선택하고, 선형 모델일 때는 ‘gblinear’를 선택(‘gblinear’는 성능이 나빠 잘 쓰지 않음. ‘dart’는 드롭아웃을 적용한 ‘gbtree’라고 보면됨. 때에 따라 ‘dart’가 성능이 좋은 경우가 있음)
    • 기본값 = ‘gbtree’
  • objective : 훈련 목적
    • 회귀 문제에서는 주로 ‘reg:squarederror’를 사용
    • 확률값을 구하는 이진분류에선 ‘binary:logistic’을 사용
    • 소프트맥스 함수를 사용하는 다중분류에서는 ‘multi:softmax’를 사용
    • 확률값을 구하는 다중분류에서는 ‘multi:softprob’를 사용
    • 기본값 = ‘reg:squarederror’
  • eta (learning_rate) ****: 학습률(부스팅 스텝을 반복하면서 모델을 업데이트하는 데 사용되는 비율)
    • 0~1 사이 값으로 설정할 수 있으며, 일반적으로 0.0001~0.1 사이 값을 사용
    • 기본값=0.3
  • max_depth : 개별 트리의 최대 깊이
    • 과대적합을 제어하는 파라미터
    • 트리 깊이가 깊을수록 모델이 복잡해지고 과대적합될 우려가 있음
    • 일반적으로 3~10 사이의 값을 주로 사용
    • 값이 클수록 깊이가 한 단계만 늘어나도 메모리 사용량이 급격히 많아짐( 값이 클수록 모델 훈련 속도가 느려진다는 뜻)
    • 기본값=6
  • subsample : 개별 트리를 훈련할 때 사용할 데이터 샘플링 비율
    • 0~1사이값으로설정할수있음
    • 0.5로 설정하면 전체 데이터의 50%를 사용해 트리를 생성
    • 일반적으로 0.6~1 사이 값을 사용. 더 작으면 샘플링할 데이터가 너무 적기 때문
    • 기본값=1
  • colsample_bytree : 개별 트리를 훈련할 때 사용하는 피처 샘플링 비율
    • 0~1사이값으로설정할수있음
    • subsample과 유사한 개념. subsample은 전체 데이터에서 얼마나 샘플링할지 나타내는 비율이고, colsample_bytree는 전체 피처에서 얼마나 샘플링할지 나타내는 비율
    • 예를 들어, colsample_bytree 값이 0.7이면, 개별 트리를 훈련할 때 총 피처의 70%만 사용해 훈련
    • 값이 작을수록 과대적합 방지 효과가 있음
    • subsample과 마찬가지로 0.6~1 사이 값을 주로 사용
    • 기본값=1
  • alpha (reg_alpha) : L1 규제 조정 값
    • 값이 클수록 과대적합 방지 효과가 있음
    • 기본값=0
  • lambda (reg_lambda) : L2 규제 조정 값
    • 파이썬 lambda 함수와 용어가 같아 혼동을 피하기 위해 별칭인 reg_lambda를 주로 사용
    • 값이 클수록 과대적합 방지 효과가 있음
    • 기본값=1
  • gamma (min_split_loss) : 말단 노드가 분할하기 위한 최소 손실 감소 값
    • 0 이상 값으로 설정할 수 있음
    • 손실 감소가 gamma보다 크면 말단 노드를 분할
    • 값이 클수록 과대적합 방지 효과가 있음
    • 기본값=0
  • min_child_weight : 과대적합 방지를 위한 값
    • 0이상값으로설정할수있음
    • 값이 클수록 과대적합 방지 효과가 있음
    • 기본값=1
  • scale_pos_weight : 불균형 데이터 가중치 조정 값
    • 타깃값이 불균형할 때 양성positive 값에 scale_pos_weight만큼 가중치를 줘서 균형을 맞춤(타깃값 1을 양성 값으로 간주)
    • 일반적으로 scale_pos_weight 값을(음성 타깃값 개수 / 양성 타깃값 개수)로 설정
    • 기본값=1
  • random_state : 랜덤 시드값(코드를 반복 실행해도 같은 결과가 나오게 지정하는 값)
    • 기본값=None

파이썬 래퍼 XGBoost는 모델 훈련을 위해 train( ) 메서드를 제공합니다(사이킷런의 fit( ) 메서드에 해당). xgboost.train( )의 파라미터는 다음과 같습니다.

  • params : XGBoost 모델의 하이퍼파라미터 목록
    • 딕셔너리 타입으로 전달
  • dtrain : 훈련 데이터셋
    • xgboost.DMatrix 타입으로 전달
  • num_boost_round : 부스팅 반복 횟수
    • 정수형 타입으로 전달
    • num_boost_round 값이 클수록 성능이 좋아질 수 있으나 과대적합 우려가 있음
    • num_boost_round 값이 작으면 반복 횟수가 줄어들어 훈련 시간이 짧아짐
    • 일반적으로 num_boost_round를 늘리면 learning_rate를 줄여야 함
    • 기본값=10
  • evals : 모델 성능 평가용 검증 데이터셋
    • (DMatrix, 문자열) 쌍들을 원소로 갖는 리스트 타입으로 전달. 검증 데이터셋 이름을 원하는 대로 문자열로 정하면 됨
    • 훈련을반복하면서훈련이잘되고있는지평가할때사용
    • 기본값=빈배열
  • feval : 검증용 평가지표
    • 사용자정의함수형태로전달
    • evals를 활용해 모델 성능을 검증할 때 사용할 사용자 정의 평가지표 함수
    • 예측값과 실젯값을 파라미터로 전달받아, 평가지표명과 평가점수를 반환하는 함수여야 함
    • 기본값=None
  • maximize : feval 평가점수가 높으면 좋은지 여부
    • True 또는 False 형태로 전달
  • early_stopping_rounds : 조기종료 조건
    • 정수형 타입으로 전달
    • 모델은 기본적으로 num_boost_round만큼 훈련을 반복하며, 매 이터레이션마다 evals로 모델 성능을 평가하여 성능이 연속으로 좋아지지 않는다면 훈련을 중단하는데, 훈련 중단에 필요한 최소 횟수가 early_stopping_rounds임. 즉, early_stopping_rounds동안 모델 성능이 좋아지지 않는다면 훈련을 중단
    • 과대적합을 방지하는 효과가 있음
    • 조기종료를 적용하려면 evals에 검증 데이터가 하나 이상 있어야 함. 또한, evals에 검증 데이터가 여러 개라면 마지막 검증 데이터를 기준으로 조기종료 조건을 적용
    • 대체로 eta가 작으면 early_stopping_rounds를 크게 설정하고, eta가 크면 작게 설정. 학습률이 작으면 그만큼 가중치가 천천히 갱신되므로 조기종료 조건이 커야 함.
    • 기본값=None
  • verbose_eval : 성능 점수 로그 설정 값
    • True/False 또는 정수형 타입으로 전달
    • True로 설정하면 매 부스팅 스텝마다 평가점수를 출력(False면 출력하지 않음)
    • 정수면 평가점수를 매 verbose_eval 스텝마다 출력. 예컨대, verbose_eval을 100으로 설정하면 100번, 200번, 300번과 같이 띄엄띄엄 출력
    • 출력값이 너무 많아지는 걸 방지하려고 verbose_eval을 설정
    • 기본값=True

파라미터가 참 많죠? 사실 이것도 다 소개한 게 아니지만 이 정도만 알아도 대부분 문제에서 충분합니다. 처음부터 모든 파라미터를 숙지하려고 스트레스받지 마시고, 기본적인 파라미터에 익숙해지면 점차 늘려가는 방식으로 학습하세요.

 

 

7. LightGBM

마이크로소프트에서 개발한 LightGBM은 XGBoost와 더불어 성능이 우수한 알고리즘입니다. XGBoost와 성능은 비슷하지만 훈련 속도가 더 빨라서 많은 캐글러가 가장 애용하는 머신러닝 모델입니다.

LightGBM의 분할 방식에 대해 간단히 알아보죠.

대부분 트리 기반 모델은 트리를 균형 있게 분할하며 훈련합니다. 그래야 트리 깊이가 최소화되고, 과대적합도 방지할 수 있기 때문입니다. 하지만 균형을 유지하려면 추가 연산이 필요합니다. 시간이 더 걸린다는 뜻입니다.

반면, LightGBM은 말단 노드 중심으로 예측 오류를 최소화하게끔 분할합니다. 말단 노드 중심으로 분할하면 균형을 유지할 필요가 없습니다. 균형을 맞출 필요가 없으니 추가 연산도 필요 없습니다. 따라서 균형 중심 분할에 비해 더 빠르죠. 하지만 데이터 개수가 적을 때는 과대적합되기 쉽다는 단점이 생겨서 과대적합 방지용 하이퍼파라미터를 조정해줘야 합니다.

▼ 균형 중심 분할과 말단 노드 중심 분할 비교

 

LightGBM은 XGBoost와 마찬가지로 파이썬 래퍼 모듈과 사이킷런 래퍼 모듈이 있습니다. 여기서도 파이썬 래퍼 LightGBM으로 설명하겠습니다.

 

???? XGBoost와 LightGBM의 특장점
  1. 피처 스케일링이 따로 필요 없습니다. 데이터의 절대적인 크기보다는 대소 관계에 영향을 받기 때문입니다.
  2. 레이블 인코딩을 적용해도 됩니다. 레이블 인코딩은 단점이 있다고 했지만, 트리 기반 모델의 특성상 분기를 거듭하면서 레이블 인코딩된 피처에서도 정보를 잘 추출할수 있기 때문입니다.
  3. 결측값을 알아서 처리해줍니다(그럼에도 더 명확하게 하려면 결측값을 별도로 처리하는 습관을 들이는 게 바람직합니다).

반면 선형 모델은 피처 스케일링, 결측값 처리, 원-핫 인코딩을 해줘야 일반적으로 성능이 좋아집니다.

 

파이썬 래퍼 LightGBM을 사용하려면 lightgbm.Dataset( )으로 전용 데이터셋을 만들어야 합니다. lightgbm.Dataset( )의 파라미터는 다음과 같습니다.

  • data : lightgbm.Dataset용 데이터셋
    • 넘파이 배열, 판다스 DataFrame, scipy.sparse, 문자열 등의 타입을 전달할 수 있음(문자열이면 파일 경로를 의미)
  • label : 타깃값
    • 리스트, 넘파이 1차원 배열, 판다스 Series, 열이 하나인 DataFrame 타입 또는 None을 전달할 수 있음
    • 기본값=None

파이썬 래퍼 LightGBM 모델에서 주로 사용하는 하이퍼파라미터들을 알아보겠습니다. (LightGBM 3.2.1 버전 기준).8

  • boosting_type : 부스팅 알고리즘
    • 알고리즘 종류는 ‘gbdt’, ‘dart’, ‘goss’, ‘rf’가 있음
    • 기본값 = ‘gbdt’
  • objective : 훈련 목적
    • 회귀에선 ‘regression’, 이진분류에선 ‘binary’, 다중분류에선 ‘multiclass’ 사용
    • 기본값 = ‘regression’
  • learning_rate (eta) : 학습률(부스팅 이터레이션을 반복하면서 모델을 업데이트하는 데 사용되는 비율)
    • xgboost의 eta와 같은 의미
  • num_leaves:개별트리가가질수있는최대말단노드개수
    • 트리 복잡도를 결정하는 주요 파라미터
    • 값이 클수록 성능이 좋아질 수 있으나 과대적합 우려가 있음
    • 기본값=31
  • max_depth : 개별 트리의 최대 깊이
    • LightGBM은 말단 노드 중심으로 분할하므로 max_depth를 균형 중심 분할 모델(XGBoost)보다 크게 잡는 게 좋음
    • 과대적합 제어 파라미터
    • 트리 깊이가 깊을수록 모델이 복잡해지고 과대적합될 우려가 있음
    • 기본값 = -1 (0보다 작으면 깊이에 제한이 없음)
  • bagging_fraction (subsample) : 개별 트리를 훈련할 때 사용할 데이터 샘플링 비율
    • xgboost의 subsample 파라미터와 같은 의미
    • 배깅을 활성화하려면 bagging_freq 파라미터를 0이 아닌 값으로 설정해야 함
  • feature_fraction (colsample_bytree) : 개별 트리를 훈련할 때 사용하는 피처 샘플링 비율
    • xgboost의 colsample_bytree 파라미터와 같은 의미
  • lambda_l1 (reg_alpha) : L1 규제 조정 값
    • 값이 클수록 과대적합 방지 효과가 있음
    • 기본값=0
  • lambda_l2 (reg_lambda) : L2 규제 조정 값
    • 값이 클수록 과대적합 방지 효과가 있음
    • 기본값=0
  • min_child_samples : 말단 노드가 되기 위해 필요한 최소 데이터 개수
    • 값이 클수록 과대적합 방지 효과가 있음
    • 기본값=20
  • min_child_weight : 과대적합 방지를 위한 값
    • 0 이상 값으로 설정할 수 있음
    • 값이 클수록 과대적합 방지 효과가 있음
    • 기본값=1e-3
  • bagging_freq (subsample_freq) : 배깅 수행 빈도
    • 몇 번의 이터레이션마다 배깅을 수행할지 결정
    • 0 전달 시 배깅을 수행하지 않음
    • 1 전달 시 매이터레이션마다 트리가 새로운 샘플링 데이터로 학습
    • 기본값=0
  • force_row_wise : 메모리 용량이 충분하지 않을 때 메모리 효율을 높이는 파라미터
    • 메모리 용량이 충분하지 않을 때 True를 전달하면 메모리 효율이 좋아짐
    • 기본값 = False
  • random_state : 랜덤 시드값(코드를 반복 실행해도 같은 결과가 나오게 지정하는 값)
    • 기본값=None

LightGBM도 하이퍼파라미터가 많죠? XGBoost와 비슷한 파라미터도 많습니다.

이번에는 훈련 메서드인 lightgbm.train( )의 파라미터를 알아보죠. params에는 LightGBM1. 모델의 하이퍼파라미터를 전달합니다.

  • params : LightGBM 모델의 하이퍼파라미터 목록
    • 딕셔너리 타입으로 전달
  • train_set : 훈련 데이터셋
    • lightgbm.Dataset 타입으로 전달
  • num_boost_round : 부스팅 반복 횟수
    • xgboost.train( )의 num_boost_round와 같은 의미
    • 기본값=100
  • valid_sets : 모델 성능 평가용 검증 데이터셋
    • lightgbm.Dataset 타입으로 전달
    • 훈련을반복하면서훈련이잘되고있는지평가할때사용
    • 기본값=None
  • feval : 검증용 평가지표
    • 사용자정의함수형태로전달
    • valid_sets를 활용해 모델 성능을 검증할 때 사용할 사용자 정의 평가지표
    • 예측값과 실젯값을 파라미터로 전달받아, 평가지표명, 평가점수, 평가점수가 크면 좋은지 여부를 반환하는 함수여야 함
    • 기본값=None
  • categorical_feature : 범주형 데이터 파라미터
    • 이 파라미터에 전달된 데이터를 범주형 데이터로 인식함
    • 아무 값도 전달하지 않으면 category 타입인 데이터를 범주형 데이터로 인식함
  • early_stopping_rounds : 조기종료 조건
    • 정수형 타입으로 전달
    • 모델은 기본적으로 num_boost_round만큼 훈련을 반복함
    • 매 이터레이션마다 valid_sets로 모델 성능을 평가하는데, 모델 성능이 연속으로 좋아지지 않는다면 훈련을 중단함. 훈련을 중단하는 데 필요한 최소 횟수가 early_stopping_rounds임. 즉, early_stopping_rounds 동안 모델 성능이 좋아지지 않는다면 훈련을 중단함
    • 과대적합을 방지하는 효과가 있음
    • 대체로 learning_rate가 작으면 early_stopping_rounds를 크게 설정하고, learning_rate가 크면 early_stopping_rounds를 작게 설정함
    • 기본값=None
  • verbose_eval : 성능 수 로그 설정 값
    • xgboost.train( )의 verbose_eval과 같은 의미

앞 절에서도 말했듯이 처음부터 모든 파라미터를 숙지하려고 스트레스받지 마시고, 기본적인 파라미터에 익숙해지면 점차 늘려가는 방식으로 학습하세요.

????Note: XGBoost, LightGBM 외에도 다양한 부스팅 모델이 있습니다. 특히 CatBoost는 XGBoost나 LightGBM보다 느려서 잘 쓰이지는 않지만, 간혹 좋은 성능을 내는 경우도 있습니다.

????사이킷런 래퍼 모듈vs.파이썬 래퍼 모듈

사이킷런은 XGBoost와 LightGBM을 비롯해 여러 모델을 지원합니다. 다음 표에 사이킷런 래퍼 모듈과 파이썬 래퍼 모듈 사용법의 차이를 정리해뒀습니다.

▼ 사이킷런 래퍼 모듈vs.파이썬 래퍼 모듈 사용법 비교

 

4편에서는 하이퍼파라미터 최적화에 대해서 알아봅시다.

신백균
KAIST 산업및시스템공학과 졸업 후 한국생산성본부에서 직무교육 기획 및 운영을 담당하는 전문위원입니다. 세계 랭킹 0.18%의 캐글 노트북 엑스퍼트(Expert)이며, 월 평균 6만여 명이 방문하는 데이터 분석/머신러닝 관련 기술 블로그를 운영하고 있습니다. 참여자 1,200명 이상인 머신러닝 관련 오픈 채팅방의 운영진이기도 합니다.

Leave a Reply

©2020 GoldenRabbit. All rights reserved.
상호명 : 골든래빗 주식회사
(04051) 서울특별시 마포구 양화로 186, 5층 512호, 514호 (동교동, LC타워)
TEL : 0505-398-0505 / FAX : 0505-537-0505
대표이사 : 최현우
사업자등록번호 : 475-87-01581
통신판매업신고 : 2023-서울마포-2391호
master@goldenrabbit.co.kr
개인정보처리방침
배송/반품/환불/교환 안내