241021 TIL #520 AI Tech #54 Stacking 구현

김춘복·2024년 10월 21일
0

TIL : Today I Learned

목록 보기
522/575

Today I Learned

오늘은 stacking을 직접 구현해보았다.


Stacking

  • 세팅
import xgboost as xgb
import lightgbm as lgb
from sklearn.ensemble import RandomForestRegressor
from sklearn.model_selection import train_test_split, KFold
from sklearn.metrics import mean_absolute_error
from sklearn.linear_model import LinearRegression

# 학습에 사용할 특징 열
feature_columns = [col for col in temp_train_df.columns if col not in ['deposit', '_type', 'index']]

# 학습 및 테스트 데이터 준비
X = temp_train_df[feature_columns]
y = temp_train_df['deposit']
X_test = test_df[feature_columns]

# 학습 데이터를 검증용으로 분할
X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2, random_state=42)

xgboost

# XGBoost를 위한 DMatrix 생성
dtrain = xgb.DMatrix(X_train, label=y_train)
dval = xgb.DMatrix(X_val, label=y_val)
dtest = xgb.DMatrix(X_test)

# XGBoost 파라미터 설정
xgb_params = {
    'objective': 'reg:absoluteerror',
    'eval_metric': 'mae',
    'max_depth': 6,
    'eta': 0.05,
    'subsample': 0.8,
    'colsample_bytree': 0.8,
    'seed': 42
}

# 모델 학습
xgb_model = xgb.train(
    xgb_params,
    dtrain,
    num_boost_round=500,
    early_stopping_rounds=50,
    evals=[(dtrain, 'train'), (dval, 'eval')],
    verbose_eval=25
)

# 검증 및 테스트 세트에 대한 예측
xgb_val_pred = xgb_model.predict(dval)
xgb_test_pred = xgb_model.predict(dtest)

lightgbm

# LightGBM 모델 초기화
lgb_params = {
    'objective': 'regression',
    'metric': 'mae',
    'boosting_type': 'gbdt',
    'num_leaves': 31,
    'learning_rate': 0.05,
    'feature_fraction': 0.9,
    'bagging_fraction': 0.8,
    'bagging_freq': 5,
    'seed': 42
}

# 콜백 함수 정의
def print_evaluation(period=10):
    def callback(env):
        if (env.iteration + 1) % period == 0:
            train_mae = env.evaluation_result_list[0][2]
            val_mae = env.evaluation_result_list[1][2]
            print(f"[{env.iteration + 1}] Train MAE: {train_mae:.4f}, Val MAE: {val_mae:.4f}")
    return callback

# 모델 학습
lgb_train = lgb.Dataset(X_train, label=y_train)
lgb_val = lgb.Dataset(X_val, label=y_val, reference=lgb_train)

lgb_model = lgb.train(
    lgb_params,
    lgb_train,
    num_boost_round=500,
    valid_sets=[lgb_train, lgb_val],
    callbacks=[print_evaluation(period=100)]
)

# 검증 및 테스트 세트에 대한 예측
lgb_val_pred = lgb_model.predict(X_val, num_iteration=lgb_model.best_iteration)
lgb_test_pred = lgb_model.predict(X_test, num_iteration=lgb_model.best_iteration)

random forest

한 피처에 대한 의존도가 너무 커서 하이퍼파라미터 조정 필요

# 랜덤 포레스트 모델 초기화
rf_model = RandomForestRegressor(
    n_estimators=100,
    max_depth=10,
    random_state=42,
    n_jobs=-1
)

# 모델 학습
rf_model.fit(X_train, y_train)

# 학습 세트에 대한 예측
rf_train_pred = rf_model.predict(X_train)

# 검증 세트에 대한 예측
rf_val_pred = rf_model.predict(X_val)

# 테스트 세트에 대한 예측
rf_test_pred = rf_model.predict(X_test)


# 학습 세트의 MAE 계산
train_mae = mean_absolute_error(y_train, rf_train_pred)
print(f"Train MAE: {train_mae:.4f}")

# 검증 세트의 MAE 계산
val_mae = mean_absolute_error(y_val, rf_val_pred)
print(f"Validation MAE: {val_mae:.4f}")

Gradient Boosting Regressor

from sklearn.ensemble import GradientBoostingRegressor

# Gradient Boosting 회귀 모델 초기화
gb_model = GradientBoostingRegressor(n_estimators=100, learning_rate=0.1, random_state=42)

# 모델 학습
gb_model.fit(X_train, y_train)

# 검증 및 테스트 세트에 대한 예측
gb_val_pred = gb_model.predict(X_val)
gb_test_pred = gb_model.predict(X_test)

# 학습 세트의 MAE 계산
gb_train_pred = gb_model.predict(X_train)
train_mae = mean_absolute_error(y_train, gb_train_pred)
print(f"Train MAE: {train_mae:.4f}")

# 검증 세트의 MAE 계산
val_mae = mean_absolute_error(y_val, gb_val_pred)
print(f"Validation MAE: {val_mae:.4f}")

ElasticNet Regressor

MAE가 다른 모델에 비해 1000 이상 높게 나와서 재고 필요

from sklearn.linear_model import ElasticNet

# ElasticNet 회귀 모델 초기화
elastic_model = ElasticNet(alpha=0.1, l1_ratio=0.7, random_state=42, max_iter=10000)

# 모델 학습
elastic_model.fit(X_train, y_train)

# 검증 및 테스트 세트에 대한 예측
elastic_val_pred = elastic_model.predict(X_val)
elastic_test_pred = elastic_model.predict(X_test)

# 학습 세트의 MAE 계산
elastic_train_pred = elastic_model.predict(X_train)
train_mae = mean_absolute_error(y_train, elastic_train_pred)
print(f"Train MAE: {train_mae:.4f}")

# 검증 세트의 MAE 계산
val_mae = mean_absolute_error(y_val, elastic_val_pred)
print(f"Validation MAE: {val_mae:.4f}")

Stacking(Light GBM)

from lightgbm import LGBMRegressor
from sklearn.metrics import mean_absolute_error
from sklearn.model_selection import cross_val_predict, KFold
from sklearn.model_selection import RandomizedSearchCV
import numpy as np

# 검증 세트의 예측을 메타 모델의 입력으로 결합
meta_X = np.column_stack((xgb_val_pred, lgb_val_pred, rf_val_pred, gb_val_pred))
meta_y = y_val

# 테스트 세트의 예측을 메타 모델의 입력으로 결합
meta_X_test = np.column_stack((xgb_test_pred, lgb_test_pred, rf_test_pred, gb_test_pred))

# LGBMRegressor 메타 모델의 하이퍼파라미터 탐색 공간 정의
param_dist = {
    'learning_rate': [0.01, 0.05, 0.1],
    'max_depth': [3, 5, 7, 9],
    'num_leaves': [31, 63, 127],
    'min_child_samples': [5, 10, 20, 30],
    'min_split_gain' : [0.2, 0.3, 0.5],
}

# LGBMRegressor 메타 모델 초기화
base_model = LGBMRegressor(random_state=42, force_row_wise=True)

# RandomizedSearchCV를 사용한 하이퍼파라미터 튜닝
kf = KFold(n_splits=5, shuffle=True, random_state=42)
random_search = RandomizedSearchCV(base_model, param_distributions=param_dist, 
                                   n_iter=50, cv=kf, scoring='neg_mean_absolute_error', 
                                   random_state=42, n_jobs=-1)

# 하이퍼파라미터 튜닝 수행
random_search.fit(meta_X, meta_y)

# 최적의 모델 선택
best_model = random_search.best_estimator_

# 교차 검증을 사용한 메타 모델의 성능 평가
cv_predictions = cross_val_predict(best_model, meta_X, meta_y, cv=kf)
cv_mae = mean_absolute_error(meta_y, cv_predictions)
print(f"Meta Model Cross-Validation MAE: {cv_mae:.4f}")

# 전체 데이터로 최종 모델 학습
best_model.fit(meta_X, meta_y)

# 최종 예측 수행
final_pred = best_model.predict(meta_X_test)

# 특성 중요도 출력
feature_importance = best_model.feature_importances_
feature_names = ['XGBoost', 'LightGBM', 'RandomForest', 'GradientBoosting', 'ElasticNet Regressor']
for name, importance in zip(feature_names, feature_importance):
    print(f"{name} importance: {importance:.4f}")
profile
Backend Dev / Data Engineer

0개의 댓글