[The Based Models 2] Boosting
๐ Bagging vs Boosting
Bagging | Boosting | |
---|---|---|
๊ธฐ๋ณธ ๋ชจ๋ธ ๊ฐ ์ํฅ | ๊ธฐ๋ณธ ๋ชจ๋ธ๋ค ๊ฐ์ ์ํฅ์ ๋ฐ์ง ์๊ณ , ๊ฐ๋ณ์ ์ผ๋ก ๋ง๋ฆ | ์ด์ ๊ธฐ๋ณธ ๋ชจ๋ธ์ด ์์ธกํ์ง ๋ชปํ ๋ถ๋ถ์ ์ง์คํ๋ ๋ชจ๋ธ์ ๋ง๋ฆ |
๋ฐ์ดํฐ์ | ๊ธฐ์กด ๋ฐ์ดํฐ์ ์์ ์ค๋ณต ํ์ฉํ ๋ฌด์์ ์ถ์ถ(๋ถํธ์คํธ๋ฉ)์ผ๋ก ๋ง๋ฆ | ์ด์ ํ์ต์์ ์ค์ฐจ๊ฐ ์ฌํ๋ ๋ฐ์ดํฐ๋ค์ ๋ํ ๊ฐ์ค์น๋ฅผ ๋ถ์ฌํ ํ ๋๋คํ๊ฒ ์ ํํด์ ๋ง๋ฆ |
๋ถ์ฐ๊ณผ ํธํฅ | ๊ธฐ๋ณธ ๋ชจ๋ธ๋ค์ ์๋ก ๋ค๋ฅธ ์์์ผ๋ก ๋ฐ์ํ๋ ์ค์ฐจ๋ค์ด ์์๋๋ฉฐ ๋ถ์ฐ์ ์ค์ → ๊ณผ๋์ ํฉ ํด๊ฒฐ | Boosting ๊ณผ์ ์ ๋ฐ๋ณตํ๋ฉฐ ์ต์ข ๋ชจ๋ธ์ ๋ณต์ก๋๋ฅผ ์์น์ํค๋ฉด์ ํธํฅ์ ์ค์ → ๊ณผ์์ ํฉํด๊ฒฐ |
์ต์ข ๊ฒฐ๊ณผ | ๊ธฐ๋ณธ ๋ชจ๋ธ๋ค์ ํ๊ท (ํ๊ท๋ชจ๋ธ), ๋ค์๊ฒฐ(๋ถ๋ฅ๋ชจ๋ธ)๋ก ๊ฒฐ์ | ๊ธฐ๋ณธ ๋ชจ๋ธ๋ค์ ๊ฒฐ๊ณผ๋ฅผ ์ทจํฉํด ์์ธก ์ํ |
๋ํ ์๊ณ ๋ฆฌ์ฆ | Random Forest | AdaBoost, GBM, XGBoost, LightGBM |
cf) XGBoost์ ๋๋ฆฐ ์ ์ด LightGBM์ ์ฐ๋ฉด ํจ์ฌ ๋์์ง!
๋ํ์ ์ธ Boosting ์๊ณ ๋ฆฌ์ฆ๋ค์ธ AdaBoost, Gradient Boost์ ๋ํด ์์๋ณด์!
AdaBoost
๋ถ๋ฅ๋ฌธ์ ์ ์ ํฉ, Gradient boost๋ณด๋ค ์ด์์น ๋ฏผ๊ฐ, ์ฑ๋ฅ ๋จ์ด์ ธ ๋ณ๋ก ์ฌ์ฉ x..
์๋ชป ๋ถ๋ฅ๋ ๊ด์ธก์น์ ๊ฐ์ค์น ๋ถ์ฌํด ์ํ๋งํจ. (๊ฐ์ค ์ํ๋ง)
๐ Gradient Boost
ํ๊ท, ๋ถ๋ฅ ๋ฌธ์ ๋ชจ๋ ์ฌ์ฉ ๊ฐ๋ฅ
๊ฐ๋ ฅํ ์ฑ๋ฅ!
kaggle, ํ์ ์์ ์ธ๊ธฐ ๋์!
๊ตฌํํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ๋ง์ ์ฝ๊ฒ ๋ชจ๋ธ ๊ตฌ์ถ ๊ฐ๋ฅ
Gradient Boosting์ ํ๋ฆฐ ๋ฐ์ดํฐ์ ์ง์คํ๊ธฐ ์ํด, ์์ฐจ๋ฅผ ํ์ตํ๋ค.
- ์ด์ ํธ๋ฆฌ์์ ์๋ชป ๋ถ๋ฅ๋ ์ํ๋ค์ ๊ฐ์ค์น๋ฅผ ๋์ฌ ๋ค์ ํธ๋ฆฌ์์ ๋์ฑ ์ง์ค์ ์ผ๋ก ํ์ตํ๊ฒ ๋ฉ๋๋ค. ์ด๋ ๊ฐ์ค์น๋ฅผ ๋์ด๋ ๊ฒ์ ๋ฐ์ดํฐ ์ํ ์์ฒด๋ฅผ ๋ ๋ง์ด ์ถ์ถํ๋ ๊ฒ์ด ์๋๋ผ, ํด๋น ์ํ์ ์์ฌ ์ค์ฐจ(residual error)๋ฅผ ๊ณ์ฐํ์ฌ ์ด๋ฅผ ์ด์ฉํด ๊ฐ์ค์น๋ฅผ ์กฐ์ ํฉ๋๋ค.
์์ฐจ๊ฐ ํฐ ๊ด์ธก์น๋ฅผ ๋ ํ์ตํ๋๋ก ํ๋ ํจ๊ณผ๊ฐ ์์ผ๋ฉฐ, ์ด์ ๋ชจ๋ธ์ด ํ๋ฆฐ ๋งํผ์ ์ง์ ํ์ตํ๋ฉฐ ์ด์ ๋ชจ๋ธ์ ์์ฐจ์ ์ผ๋ก ๋ณด์ํจ.
๐ XGBoost
Gradient Boosting๋ณด๋ค ์ฑ๋ฅ, ๊ณ์ฐ์๋ ์ข๋ค!
XGBoost ๋ผ์ด๋ธ๋ฌ๋ฆฌ : 2014๋ ์ ๊ณต๊ฐ๋ Gradient Boosting Decision Tree ๊ตฌํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก, kaggle๋ฑ์์ ๊พธ์คํ ์ฌ๋๋ฐ์ ์จ ๋ชจ๋ธ์ด๋ค.
scikit-learn ensemble ๋ชจ๋์ GradientBoostingRegressor, GradientBoostingClassifier ํด๋์ค๋ Gradient Boosting Decision Tree ๊ธฐ๋ฐ ๋ชจ๋ธ์ด์ง๋ง, ์ฑ๋ฅ๊ณผ ๊ณ์ฐ ์๋๊ฐ XGBoost ๋ชจ๋ธ๋ณด๋ค ๋จ์ด์ ธ ์์ฃผ ์ฌ์ฉํ์ง๋ ์๋๋ค.
Gradient Boosting Decision Tree๋ Tree-Based ๋ชจ๋ธ์ ํน์ฑ์ ๊ทธ๋๋ ๋ฐ๋ฅธ๋ค.
- ํน์ฑ์ ์์นํํ ํ์๊ฐ ์๋ค. ( carboost๋ฑ์์๋ string type์ ํน์ฑ์ ๊ทธ๋๋ก ์ฒ๋ฆฌํ๊ธด ํจ.)
- ํน์ฑ์ scaling์ด๋ normalize๊ฐ ํ์์๋ค.
- one-hot encoding๋ณด๋ค ordinal encoding ์ ํธ๋จ.
- ํนํ cardinality๊ฐ ๋์ ํน์ฑ์ ๊ฒฝ์ฐ one-hot encdoing์ ํ์ต ์๊ฐ ๋ฐ ๋ฉ๋ชจ๋ฆฌ, ์ปดํจํ ์์์ด ๋ง์ด ์๋ชจ๋๋ฏ๋ก ์ฃผ์.
XGBoost์ ํ๋ผ๋ฏธํฐ
booster
- weak learner ๋ชจ๋ธ์ ์ค์ ํ ์ ์๋ ํ๋ผ๋ฏธํฐ
- gbtree : Decision Tree ๋ชจ๋ธ ์ฌ์ฉ
- dart : Decision Tree ๋ชจ๋ธ ์ฌ์ฉํ๋, DART ์๊ณ ๋ฆฌ์ฆ ์ฌ์ฉํด ๋ชจ๋ธ ์ ๊ทํ
- ๊ณผ์ ํฉ ๋ฐฉ์งํ๊ธฐ ์ํด, ์ด์ ์ ํ์ต๋ ํธ๋ฆฌ ์ค ๋ช ๊ฐ์ง๋ฅผ drop์ํค๋ ๊ธฐ๋ฒ
- https://xgboost.readthedocs.io/en/latest/tutorials/dart.html
objective
- ์ต์ํํ๊ณ ์ ํ๋ ๋ชฉ์ ํจ์ ์ค์
- (default) XGBClassifier : binary : logistic / XGBREgressor : reg : squarederror
- https://xgboost.readthedocs.io/en/latest/parameter.html#learning-task-parameters
eval_metric
- ๊ฒ์ฆ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ด ๋ฃ์ด์ค ๊ฒฝ์ฐ, ๊ฒ์ฆ ๋ฐฉ๋ฒ ์ค์ ํ ์ ์๋ค.
- (default) regression : rmse, classification : logloss
- eval_metric='error' : 1-accuracy์งํ ์ด์ฉํด ํ๊ฐ
XGBoost์ ์ฃผ์ ํ์ดํผํ๋ผ๋ฏธํฐ
XGBoost๋ ํ์ดํผํ๋ผ๋ฏธํฐ์ ๋ฐ๋ผ ์ฑ๋ฅ์ด ๋ง์ด ๋ฌ๋ผ์ง๋ ๋ชจ๋ธ์ด๋ฏ๋ก ๊ฐ๊ฐ ๋ชจ๋ ๊ณ ๋ คํด ์ฌ์ฉํด๋ณด์!!!
n_estimators
- weak learner๋ค์ ์ ๊ฒฐ์ (randomforest์ ๊ฒฝ์ฐ, decision tree์ ๊ฐ์๊ฐ ๋๊ฒ ์ง.)
learning_rate
- ๋จ๊ณ๋ณ๋ก weak learner๋ค ์ผ๋ง๋ ๋ฐ์ํ ์ง ๊ฒฐ์
- 0~1 ๋ฒ์
- ๊ฐ์ด ๋๋ฌด ํฌ๋ฉด overfitting ๋ฐ์ ์ฌ์.
- ๊ฐ์ด ๋๋ฌด ์์ผ๋ฉด ํ์ต์ด ๋๋ ค์ง.
- ์ผ๋ฐ์ ์ผ๋ก 0.05~0.3 ์ ๋์ ๋ฒ์์์ ํ์ ์งํ
max_depth
- ๊ฐ weak learner ํธ๋ฆฌ๋ค์ ์ต๋ ๊น์ด ๊ฒฐ์
- ๋ชจ๋ธ์ ์ฑ๋ฅ์ ๊ฐ์ฅ ํฐ ์ํฅ์ ์ฃผ๋ ๋ณ์!!!
- ๊ฐ์ด ๋๋ฌด ํฌ๋ฉด, overfitting ๋ฐ์ ์ฌ์ฐ๋ฉฐ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋ ๋์ด๋จ.
- ์ผ๋ฐ์ ์ผ๋ก 5-12 ์ ๋์ ๋ฒ์์์ ํ์ ์งํ
min_child_weight
- leaf ๋ ธ๋์ ํฌํจ๋๋ ๊ด์ธก์น์ ์ ๊ฒฐ์
- ๊ฐ์ด ์ปค์ง์๋ก, weak learner๋ค์ ๋ณต์ก๋ ๊ฐ์
- ์ผ๋ฐ์ ์ผ๋ก, overfitting ์, 1,2,4,8…๊ณผ ๊ฐ์ด 2๋ฐฐ์ฉ ์ฑ๋ฅ์ ๋๋ ค ํ์ธ
subsample
- ๊ฐ weak learner๋ค์ ํ์ตํ ๋ ๊ณผ์ ํฉ์ ๋ง๊ณ , ์ผ๋ฐํ ์ฑ๋ฅ์ ์ฌ๋ฆฌ๊ธฐ ์ํด, ์ ์ฒด ๋ฐ์ดํฐ ์ค ์ผ๋ถ๋ฅผ ์ํ๋งํ์ฌ ํ์ตํจ.
- subsample ํ๋ผ๋ฏธํฐ๊ฐ ๋ฐ์ดํฐ๋ฅผ ์ํ๋งํ ๋น์จ ๊ฒฐ์ ํจ.
- ์ผ๋ฐ์ ์ผ๋ก 0.8์ ๋๋ก ์ค์ ํ๋ฉฐ, ๋ฐ์ดํฐ์ ํฌ๊ธฐ์ ๋ฐ๋ผ ๋ฌ๋ผ์ง ์ ์๋ค.
colsample_bytree
- column์ ์ํ๋งํ ๋น์จ
- ์ผ๋ฐ์ ์ผ๋ก 0.8์ ๋๋ก ์ค์ ํ๋ฉฐ, ํน์ฑ์ ๊ฐ์์ ๋ฐ๋ผ ๋ฌ๋ผ์ง ์ ์๋ค. ํน์ฑ์ด ์ฒ ๊ฐ ์ด์์ผ๋ก ๋งค์ฐ ๋ง์ ๊ฒฝ์ฐ 0.1๋ฑ์ ๋งค์ฐ ์์ ๊ฐ ์ค์ ํ๊ธฐ๋ ํจ.
scale_pos_weight
- ๋ถ๊ท ํ target ํ๋!!
- sum(negative cases) / sum(positive cases) ๊ฐ์ ๋ฃ์ด์ฃผ๋ฉด, scikit-learn์ 'class_weight= balanced' ์ต์ ๊ณผ ๋์ผํ๊ฒ ๋จ.
์ผ๋ฐ์ ์ผ๋ก
max_depth
,learning rate
๊ฐ ๊ฐ์ฅ ์ค์ํ hyperparameter์ด๋ฉฐ, ๊ณผ์ ํฉ์ ๋ฐฉ์งํ๊ธฐ ์ํด ์ถ๊ฐ์ ์ผ๋ก ์กฐ์ ํด์ค.
https://xgboost.readthedocs.io/en/latest/parameter.html#learning-task-parameters
XGBoost Parameters — xgboost 2.0.0-dev documentation
update: Starts from an existing model and only updates its trees. In each boosting iteration, a tree from the initial model is taken, a specified sequence of updaters is run for that tree, and a modified tree is added to the new model. The new model would
xgboost.readthedocs.io
Early Stopping
- ์ง์ ํด์ค n_estimators ๋งํผ ํ์ต์ ๋ฐ๋ณตํ์ง ์๋๋ผ๋, ์ผ์ ํ์์์ ๋ ์ด์ ์ฑ๋ฅ์ด ํฅ์๋์ง ์์ผ๋ฉด ์ค๋จ์ํค๋ ๋ฐฉ๋ฒ
- ๋ค๋ฅธ ํ์ดํผํ๋ผ๋ฏธํฐ ํ๋ํ ๋, ์ด์ ๋ง์ถ์ด n_estimators๊ฐ์ ๋ณ๊ฒฝํด์ฃผ์ง ์์๋ ๋์ ํธ๋ฆฌํ๋ค.
- XGBoost ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์
early_stopping_rounds
์ค์ ํด ๊ธฐ๋ฅ ์ฌ์ฉ - early stopping์ ๊ฒฐ์ ํ๋ ๊ธฐ์ค ๋ฐ์ดํฐ์
์ธ
eval_set
์ ์ ๊ณตํด์ฃผ์ด์ผํจ. - ์ฌ๋ฌ ๊ฐ์ eval_set์ด ์ ๊ณต๋ ๊ฒฝ์ฐ ๋ง์ง๋ง dataset์ด ๊ธฐ์ค ๋ฐ์ดํฐ์ ์ด ๋จ.
model = XGBClassifier(objective='binary:logistic',
eval_metric='error',
n_estimators=3244224,
n_jobs=-1,
max_depth=7,
learning_rate=0.1,
cale_pos_weight= train[target].value_counts(normalize=True)[0]/ train[target].value_counts(normalize=True)[1],
reg_lambda=1}
watchlist = [(x_train, y_train{, (x_val, y_val)]
modell.fit(x_train, y_train,
eval_set=watchlist,
early_stopping_rounds=50) # 50 rounds๋์ ์ฑ๋ฅ ๊ฐ์ ์ด ์์ผ๋ฉด ํ์ต ์ค์ง.
Kaggle - H1N1๋ ๊ฐ ๋ฐฑ์ ๋ฐ์
# 80/20 ๋น์จ๋ก train / test ๋ฐ์ดํฐ ๋ถ๋ฆฌ
train, val = train_test_split(train, test_size=0.2, random_state=42, stratify=train[target])
# Feature Engineering
def engineer(df):
# drop high cardinality columns
selected_cols = df.select_dtypes(include=["number", "object"])
labels = selected_cols.nunique()
selected_features = labels[labels <= 30].index.tolist()
df = df[selected_features]
# new feature
behaviorals = [col for col in df.columns if 'behavioral' in col]
df['behaviorals'] = df[behaviorals].sum(axis=1)
# drop feature
dels = [col for col in df.columns if ('employment' in col or 'seas' in col)]
df.drop(columns=dels, inplace=True)
return df
train = engineer(train.copy())
val = engineer(val.copy())
test = engineer(test.copy())
train.shape, val.shape, test.shape
>> ((33723, 32), (8431, 32), (28104, 31))
# feature, label ๋ถ๋ฆฌ
x_train, y_train = train.drop(target, axis=1), train[target]
x_val, y_val = val.drop(target, axis=1), val[target]
x_test = test
from category_encoders import OrdinalEncoder
from sklearn.impute import SimpleImputer
from xgboost import XGBClassifier
encoder = OrdinalEncoder()
x_train = encoder.fit_transform(x_train)
x_val = encoder.transform(x_val)
x_test = encoder.transform(x_test)
model = XGBClassifier(
objective='binary:logistic',
eval_metric='error',
n_estimators=100,
random_state=42,
n_jobs=-1,
max_depth=7,
learning_rate=0.1,
scale_pos_weight=3,
sub_sample=0.8,
colsample_bytre=0.8,
min_child_weight=16, # ๊ฐ์ง์น๊ธฐ์ ์ฌ์ฉ๋๋ ๊ฐ์ค์น์ ์ต์๊ฐ ์ง์ , overfitting์, 1,2,4,8..ํํ๋ก ๋๋ ค๊ฐ๊ธฐ
reg_lambda=1) # L1, L2๊ท์ ๊ฐ๋ ์กฐ์ - ๊ฐํด์๋ก, ๊ฐ์ค์น๊ฐ ์์์ ธ ๊ณผ์ ํฉ ๋ฐฉ์ง
eval_set = [(x_train, y_train), (x_val, y_val)]
model.fit(x_train, y_train,
eval_set=eval_set,
early_stopping_rounds=50)
model.score(x_train, y_train)
model.score(x_val, y_val)
>>
train score :0.7967
val score : 0.7771
randomforest๋ชจ๋ธ๋ณด๋ค, overfitting ๊ฐ๋ฅ์ฑ ๋ฎ์์ก๋ค.
kaggle์ ์ ์ถ ์, XGBClassifier์ f1-score : 0.61997
๋ค์๋ฒ์๋ ๋ค๋ฅธ ๋ชจ๋ธ์ ํตํด ๋ score๋ฅผ ์ฌ๋ ค๋ณด์!!
More study
ํธ๋ฆฌ ์๊ฐํ
# ์๊ฐํ ๋ชจ๋ ๋ถ๋ฌ์ค๊ธฐ
from xgboost import plot_tree
# ์๊ฐํ
plot_tree(model, # ๋ชจ๋ธ์ด๋ฆ
num_trees=0, # ํ์ํ ํธ๋ฆฌ ๋ฒํธ
rankdir='TB') # ํ์ ๋ฐฉํฅ: LR' or 'TB'
plt.gcf().set_size_inches(13, 13);
lightBGM
import lightgbm as lgb
# LightGBM ๋ชจ๋ธ ์ค์ ํ๊ธฐ
model = lgb.LGBMClassifier(
objective='binary:logistic',
metric='error',
n_estimators=100,
random_state=42,
num_leaves=31, # ์ ๋
ธ๋ ๊ฐ์ : ๋ ์ด์ ๋ถํ ํ ์ ์๋ ์ต์ข
์ ์ธ ์์ญ์ญ
learning_rate=0.1,
max_depth=5,
reg_lambda=1,
scale_pos_weight=3,
subsample=0.8,
colsample_bytree=0.8,
min_child_weight=16
)
wathchlist = [(X_train_encoded, y_train), (X_val_encoded, y_val)]
# LightGBM ๋ชจ๋ธ ํ์ตํ๊ธฐ
model.fit(X_train_encoded, y_train, eval_set=watch_list, early_stopping_rounds=50)
XGB๋ณด๋ค, lightGBM ๋ชจ๋ธ์ด ํ์คํ ๋ ๋น ๋ฅด๋ค..!
ํ์ง๋ง, ๋ด๊ฐ ํ ๋ฐ์ดํฐ์ ์์๋ XGB ๋ชจ๋ธ์ด ์ฑ๋ฅ์ด ๋ ์ข์๋ค.
[Reference]
Gradient Boosting์ด ๊ตฌํ๋ Python Library
- scikit-learn Gradient Tree Boosting — ์๋์ ์ผ๋ก ์๋๊ฐ ๋๋ฆด ์ ์์ต๋๋ค.
- Anaconda: already installed
- Google Colab: already installed
- xgboost — ๊ฒฐ์ธก๊ฐ์ ์์ฉํ๋ฉฐ, monotonic constraints๋ฅผ ๊ฐ์ ํ ์ ์์ต๋๋ค.
- Anaconda, Mac/Linux: conda install -c conda-forge xgboost
- Windows: conda install -c anaconda py-xgboost
- Google Colab: already installed
- LightGBM — ๊ฒฐ์ธก๊ฐ์ ์์ฉํ๋ฉฐ, monotonic constraints๋ฅผ ๊ฐ์ ํ ์ ์์ต๋๋ค.
- Anaconda: conda install -c conda-forge lightgbm
- Google Colab: already installed
- CatBoost — ๊ฒฐ์ธก๊ฐ์ ์์ฉํ๋ฉฐ, categorical features๋ฅผ ์ ์ฒ๋ฆฌ ์์ด ์ฌ์ฉํ ์ ์์ต๋๋ค.
- Anaconda: conda install -c conda-forge catboost
- Google Colab: pip install catboost
๋ฐฐ๊น ๋ณต์ต
๋ถ์คํ
- AdaBoost
- Gradient Boosting
- Bagging vs Boosting
- Single estimator versus bagging: bias-variance decomposition
- Understanding AdaBoost
- Friedman, Jerome H. "Greedy function approximation: a gradient boosting machine." Annals of statistics (2001): 1189-1232.
- Gradient Boosting Diagram
- Monotonic Constraint
- DART
- XGBoost Parameters
- Avoid Overfitting By Early Stopping With XGBoost In Python
- ๋ฐ์ดํฐ๊ฐ ๋ฐ์ด๋ ธ๋ AI ๋์ดํฐ, ์บ๊ธ ์์ ๋ญํน ์ง์ ์ ์ํ ํ์ด๊ธฐ (๊ฐ๋์ํค ๋ค์ด์ค์ผ, ์ฌ์นดํ ๋ฅ์ง, ํธ์ฌ์นด ๊ฒ์ด์ค์ผ, ํ๋ผ๋ง์ฐ ์ ์ง ์ /๋๋์ผWJ )