LightGBM으로 캐글 마스터? 실전 예제와 함께 파헤치기

핫한 머신러닝 프레임워크인 LightGBM을 빼놓을 수 없죠.

이 글을 통해 여러분에게 LightGBM의 뛰어난 성능과 특징에 대해 한 발짝 다가섰으면 좋겠습니다. 실제 데이터를 활용한 예제를 통해 이 프레임워크를 어떻게 활용할 수 있는지 알아보시죠.

LightGBM-실습-활용

LightGBM이란?

LightGBM(Light Gradient Boosting Machine)은 Microsoft에서 개발한 오픈 소스 머신러닝 프레임워크인데요. 특히 대규모 데이터 세트와 복잡한 모델에 대해 매우 효율적입니다.

저 개인적인 경험도 많은 데이터에 대해 랭덤포레스트나 XGboost에 비해 빨리 결과가 나와 신기했던 적이 있습니다. 그 원리에 대해 알면 조금은 이해하실거예요.

이 프레임워크는 decision tree 알고리즘 기반 입니다. tree 모델을 개선한 gradient boosting 기법을 사용하고 있는데요. LightGBM은 XGBoost나 Gradient Boosting Regressor(GBR)와 같은 맥락에서 많이 이야기 합니다. 

하지만 다른 gradient boosting 프레임워크와 비교해 몇 가지 독특한 특징을 가지고 있습니다. 그 특징에 대해 하나씩 살펴보시죠. 

 

LightGBM의 주요 특징

1. Exclusive Feature Bundling (EFB)

LightGBM은 고차원 sparse 데이터에 대한 치수 축소를 자동으로 처리하는데요. 이 기능은 분석가들이 일일히 수작업 없이 데이터의 고차원성을 효율적으로 관리할 수 있도록 해줍니다.

2. Gradient-Based One-Side Sampling (GOSS)

GOSS는 큰 그래디언트를 가진 인스턴스를 유지하는 데 사용할 수 있는 선택적 매개변수입니다. 이러한 인스턴스는 모델의 예측이 크게 어긋난 데이터 포인트를 나타내며, 모델 개선에 중요한 역할을 합니다.

3. Leaf-wise Tree Growth

일반적으로 GBR과 XGBoost는 레벨 단위로 트리를 성장시키는데요. 반면, LightGBM은 손실 함수 감소가 가장 큰 리프를 선택적으로 분할하여 보다 효율적이고 깊이가 있는 트리를 생성합니다.

 

Kaggle 데이터셋을 이용한 실험

이제 실전으로 넘어가 보겠습니다. LightGBM의 실습하기 위해 Ames Housing 데이터셋을 이용하여 두 가지 부스팅 전략인 GBDT와 GOSS의 성능을 비교해 보았습니다.

Ames Housing Dataset

참고로 Ames Housing Dataset은 미국 아이오와주 에임스 시의 주택 판매 정보를 담고 있는 데이터셋입니다. 이 데이터셋의 주요 특징은 다음과 같습니다.

구분 설명
데이터셋 개요
  • 2006년부터 2010년까지 에임스 시에서 판매된 개별 주택 정보를 포함합니다.
  • 총 2,930개의 주택 데이터와 82개의 변수로 구성되어 있습니다.
  • 주택 가격 예측을 위한 회귀 분석에 주로 사용됩니다
주요 변수
  • 주택 특성: 침실 수, 차고, 벽난로, 수영장, 현관 등
  • 위치 정보: 동네, 위도, 경도
  • 부지 정보: 용도 지역, 모양, 크기 등
  • 상태 및 품질 평가
  • 판매 가격 (예측 대상 변수)

자~ 이제 각 기법의 차이점과 장점이 무엇인지 확인해 보시죠.

먼저 데이터 전처리를 통해 카테고리형 변수들을 처리하는 것으로 시작하겠습니다. 이 부분은 LightGBM의 강점 중 하나로, 카테고리형 데이터를 원활하게 처리하여 예측 정확성과 모델의 효율성을 높일 수 있는 기능입니다.

import pandas as pd
import lightgbm as lgb
from sklearn.model_selection import cross_val_score

def load_and_preprocess_data(file_path):
    """데이터를 로드하고 전처리하는 함수"""
    data = pd.read_csv(file_path)
    X = data.drop('SalePrice', axis=1)
    y = data['SalePrice']
    
    # 카테고리형 열을 'category' 데이터 타입으로 변환
    categorical_cols = X.select_dtypes(include=['object']).columns
    X[categorical_cols] = X[categorical_cols].astype('category')
    
    return X, y

def evaluate_model(model, X, y, cv=5):
    """모델을 평가하고 평균 R² 점수를 반환하는 함수"""
    scores = cross_val_score(model, X, y, cv=cv)
    return scores.mean()

def main():
    # 데이터 로드 및 전처리
    X, y = load_and_preprocess_data('Ames.csv')
    
    # 모델 정의
    models = {
        "Default Light GBM (GBDT)": lgb.LGBMRegressor(),
        "Light GBM (GOSS)": lgb.LGBMRegressor(boosting_type='goss')
    }
    
    # 결과 저장을 위한 딕셔너리
    results = {}
    
    # 각 모델 평가
    for name, model in models.items():
        score = evaluate_model(model, X, y)
        results[name] = score
    
    # 결과 출력
    for name, score in results.items():
        print(f"{name}의 평균 R² 점수: {score:.4f}")

if __name__ == "__main__":
    main()

위 실험에서 Ames Housing 데이터셋을 사용하여 GBDT 모델은 평균 R² 점수가 0.9145였으며, GOSS 모델은 0.9109의 점수를 기록하였습니다.

이는 데이터셋의 특성과 GOSS의 데이터 포인트 중요도에 따라 모델의 성능 차이가 발생할 수 있음을 나타냅니다.

리프 단위 트리 성장 전략의 미세 조정

이제 LightGBM의 또 다른 특징인 리프 단위 트리 성장에 대해 알아볼까요? Leaf-wise 접근법은 손실 감소를 최적화하여 트리를 성장시킵니다.

이 전략은 모델의 성능을 향상시킬 수 있지만, 과적합의 위험을 가지고 있습니다. 이번 실험에서는 ‘num_leaves’ 매개변수를 다양하게 설정하여 최적의 복잡도를 찾으려 합니다.

import pandas as pd
import lightgbm as lgb
from sklearn.model_selection import cross_val_score
 
# Load the Ames Housing Dataset
data = pd.read_csv('Ames.csv')
X = data.drop('SalePrice', axis=1)
y = data['SalePrice']
 
# Convert categorical columns to 'category' dtype
categorical_cols = X.select_dtypes(include=['object']).columns
X[categorical_cols] = X[categorical_cols].apply(lambda x: x.astype('category'))
 
# Define a range of leaf sizes to test
leaf_sizes = [5, 10, 15, 31, 50, 100]
 
# Results storage
results = {}
 
# Experiment with different leaf sizes for GBDT
results['GBDT'] = {}
print("Testing different 'num_leaves' for GBDT:")
for leaf_size in leaf_sizes:
    model = lgb.LGBMRegressor(boosting_type='gbdt', num_leaves=leaf_size)
    scores = cross_val_score(model, X, y, cv=5, scoring='r2')
    results['GBDT'][leaf_size] = scores.mean()
    print(f"num_leaves = {leaf_size}: Average R² score = {scores.mean():.4f}")
 
# Experiment with different leaf sizes for GOSS
results['GOSS'] = {}
print("\nTesting different 'num_leaves' for GOSS:")
for leaf_size in leaf_sizes:
    model = lgb.LGBMRegressor(boosting_type='goss', num_leaves=leaf_size)
    scores = cross_val_score(model, X, y, cv=5, scoring='r2')
    results['GOSS'][leaf_size] = scores.mean()
    print(f"num_leaves = {leaf_size}: Average R² score = {scores.mean():.4f}")

결과적으로, num_leaves의 설정값이 10일 때 두 모델 모두 최적의 R² 점수를 기록했으며, 이는 더 많은 복잡도가 모델의 일반화 능력을 저하시킬 수 있음을 의미합니다.

 

마무리

LightGBM은 데이터 특성과 요구사항에 따라 다양한 부스팅 전략을 활용할 수 있는 강력한 프레임워크입니다. 특히, 대규모 데이터와 복잡한 패턴을 다루는 데 있어 효율적이고 유연한 성능을 발휘합니다.

이를 통해 모델 성능의 향상 뿐아니라 데이터의 인사이트를 도출하는 데에도 큰 도움을 줄 수 있습니다. 앞으로 머신러닝 프로젝트에 LightGBM을 활용하시길 추천드립니다. 

Leave a Comment