๐ Hyperparmeter Tuning
์๊ณ ๋ฆฌ์ฆ์ ์ฌ์ฉํ์ฌ ๋ชจ๋ธ๋ง ํ ๋ ์ต์ ํํ๊ธฐ ์ํด ์กฐ์ ํด๋ณด์.
ํ๋์ ์ ๋ต์ ์์ !!!
Tuning์ ๊ธฐ๋ณธ ์์
- ํ๋ ๋์ ๋ชจ๋ธ
- ๋ฒ์
- ์กฐํฉ ์ ํ ๋ฐฉ๋ฒ ex) random ์ ํ, exhaustive(๋ชจ๋ ์กฐํฉ์๋)
- ๊ฒ์ฆ ๋ฐฉ๋ฒ ex) cross validation , validation set ์ ๊ณต ๋ฑ
- scoring metric (๋ช ํํ ์ ์ํ์ง ์์ผ๋ฉด, ์๋ํ์ง ์์ ํ์ดํผํ๋ฆฌ๋ฏธํฐ ์กฐํฉ์ด ์ ํ๋ ์ ์๋ค.) : metric ๊ฐ์ด ๊ฐ์ฅ ์ฐ์ํ hyperparameter ์กฐํฉ ์ ํ!
์ง์ ํ๋
๋ค๋ฅธ ํด๋ค ์ฌ์ฉํ๊ธฐ ์ , ํ์ดํผํ๋ผ๋ฏธํฐ ๋ฒ์ ๋ฑ์ ๋ํด ๋๋ต์ ์ผ๋ก ๊ฐ์ ์ก๊ธฐ ์ํด ํ์์ ์ธ ๊ณผ์
์ถ์ฒ ๋ฐฉ๋ฒ
- hyperparameter๋ค์ default๊ฐ์ผ๋ก ๋๊ณ , 3๊ฐ ์ด๋ด์ ์ค์ํ hyperparmeter๋ฅผ ๋ฐ๊ฟ๊ฐ๋ฉฐ ์ฑ๋ฅ ๋ณํ ํ์ธ
- ๋๋ค์์ hyperparam๋ค์ด ๋ชจ๋ธ์ ๋ณต์ก์ฑ๊ณผ ๊ด๋ จ๋ ๊ฒ์ด๋ค. ๊ณผ์ ํฉ / ๊ณผ์์ ํฉ์ ์ฌ๋ถ๋ฅผ ํ์ธํ๊ณ , ๋ชจ๋ธ์ ๋ณต์ก์ฑ์ ์กฐ์ ํ๋ค.
Exhaustive Grid Search
ํ๋ผ๋ฏธํฐ ๊ฐ ๋ฒ์๋ฅผ ๋ชจ๋ ์ฌ์ฉํ๋ grid serach ๋ชจ๋ธ ์ ์ธ ํ ํ์ต, ๊ฐ์ฅ ์ข์ ์ฑ๋ฅ์ ๋ณด์ธ ํ๋ผ๋ฏธํฐ ๊ฐ์ผ๋ก ์๋ ํ์ต.
์๊ฐ์ ์ค๋๊ฑธ๋ ค๋ ๋ง์์ ํธํ์ง..
from sklearn.model_selection import GridSearchCV
from category_encoders import OrdinalEncoder
from xgboost import XGBClassifier
from sklearn.pipeline import make_pipeline
# pipeline ๊ตฌ์ฑ
pipe = make_pipeline(OrdinalEncoder(),
SimpleImputer(strategy='median'),
XGBClassifier(objective='binary:logistic',
eval_metric='error',
n_estimators=200,
learning_rate=0.1,
use_label_encoder=False,
n_jobs=-1))
# ๋งค๊ฐ๋ณ์ ๊ผญ ๋ฒ์๋ฅผ dict ํํ๋ก ์ ์ธ!!
params = {'xgbclassifier__max_depth':[2,4,6],
'xgbclassifier__min_child_weight':[2,4,6],
'xgbclassifier__colsample__bytree':[0.6,0.8,1.0]}
grid_search = GridSearchCV(pipe,
param_grid=parms,
scoring='roc_auc', # ํ๊ฐ์งํ(default:accuracy)
cv=3, # k-fold cv (default:cv=5)
verbose=3) # ํ์ต๊ณผ์ ํ์ ์ ๋
grid_search.fit(x_train, y_train)
grid_search.best_params_ # ์ต์ ์ ํ์ดํผํ๋ผ๋ฏธํฐ
>> {'xgbclassifier__colsample_bytree': 0.6, 'xgbclassifier__max_depth': 4, 'xgbclassifier__min_child_weight': 4}
grid_search.best_score_ # ์ต์ AUC
>> 0.8204
# ์ํ์, grid_search๋ ์ต์ ์ ํ์ดํผํ๋ผ๋ฏธํฐ๋ก ์๋ ํ์ต์ด ์๋ฃ๋ ๋ชจ๋ธ์ด๋ค.
# ํน์ฑ ์ค์๋ ํ์ธ์, grid_search.best_estimator_ ์ด์ฉ
tmp = pd.DataFrame()
tmp['feature'] = list(x_train)
tmp['importance'] = grid_search.best_estimator_[1].feature_importances_
tmp.sort_values(by='importance', inplace=True)
plt.barh(y=tmp['feature'], width=tmp['importance']);
Randomized Search
ํ๋ผ๋ฏธํฐ ๊ฐ ๋ฒ์์์ ๋ช ๊ฐ ์ ํํ ์ง ์ ํ์ฌ random search ๋ชจ๋ธ ์ ์ธ ํ ํ์ต, ๊ฐ์ฅ ์ข์ ์ฑ๋ฅ์ ๋ณด์ธ ํ๋ผ๋ฏธํฐ ๊ฐ์ผ๋ก ์๋ ํ์ต.
๋นจ๋ฆฌ ํ ์ ์์ง๋ง, ์ด์ ๋งก๊ธฐ๋ ๋๋..
cross validation ๋ฐฉ๋ฒ์ผ๋ก ํ์ ์งํ
ํ์ดํผํ๋ผ๋ฏธํฐ ๋ฒ์๋ก ๊ฐ์ ์ง์ ํด์ค ์๋ ์๊ณ , scipy.stats
์ ๋ถํฌ๋ก๋ ์ง์ ๊ฐ๋ฅ
์ค์ ํด์ฃผ๋ ํ์ดํผํ๋ผ๋ฏธํฐ์ ๋ฒ์๋ ๋์ง๋ง, fitting์ ์ค์ ํด ์ค n_iter๋งํผ๋ง ์งํ๋จ.
# ์ด๋ฒ์, pipeline ์ฌ์ฉ์ํ๊ณ ํด๋ณด์
from scipy.stats.distributions import uniform
from sklearn.model_selection import RandomizedSearchCV
# ํ๋ผ๋ฏธํฐ ๋์
๋๋ฆฌ ์ ์ธ
param = {'strategy':['median','mean'],
'max_depth':[2,4,6],
'min_child_weight':[2,4,8],
'colsample_bytree':uniform(loc=0.5, scale=0.5)} # 0.5-1์ฌ์ด์ uniform ๋ถํฌ๋ก ๋ฒ์ ์ง์
# ๊ธฐ๋ณธ ๋ชจ๋ธ ์ ์ธ
dst_model = DesicionTreeClassifier()
# random search ์ ์ธ
model = RandomizedSearchCV(dst_model,
param,
cv=3,
n_iter=20, # 20๊ฐ ๋ฝ์๋
scoring='accuracy')
# default๊ฐ์ด๋ผ๋ ์จ์ฃผ๋ ๊ฒ ์ข๋ค. ํ๋์ ์๊ธฐ ์ํด์.
# ๋ถ๋ฅ์ accuracy, ํ๊ท์ r2 ์์ง ๋ง๊ธฐ!
model.fit(x_train, y_train)
# ์ํ ์ ๋ณด
model.cv_results_
# ์ต์ ํ๋ผ๋ฏธํฐ
model.best_params_
# ์ต๊ณ ์ฑ๋ฅ
model.best_scores_
random์ผ๋ก ํ๋๋ฐ 6 ๋์์ผ๋ฉด, 6 ์ฃผ์๊ฐ๋ง ์ด์ฉํด grid search ์ํ
์์ํ๋ฉด, ๊ทธ ๊ทผ์ฒ๊ฐ์ grid search ํด์ค ์ ์๋ ๋ฐฉ๋ฒ๋ ์จ๋จน์ด๋ณด์!
Bayesian Search
์ด์ ์ ํ์ํ ์กฐํฉ๋ค์ ์ฑ๋ฅ์ ๊ธฐ๋ฐ์ผ๋ก ์ฑ๋ฅ์ด ์ ๋์ค๋ ์กฐํฉ๋ค์ ์ค์ฌ์ผ๋ก ํ๋ฅ ์ ์ผ๋ก ํ์
sklearn์์๋ ์ด ๊ธฐ๋ฅ ์ ๊ณตํ์ง ์์ผ๋ฉฐ, hyperpot
๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ ์ ๊ณตํ๋ stochastic expresssions๋ก ์ง์ ํด์ค์ผํจ.
์์ฃผ ์ฌ์ฉํ๋ expression๋ค
- hp.choice(label, options) : ๋ฆฌ์คํธ๋ ํํ ํํ์ ์ ํ์ง ์ค ํ๋ ์ ํ
- hp.randint(label, upper) : [0,upper]๋ฒ์ ๋ด์ ์ ์๊ฐ ๋๋ค ์ ํ
- hp.uniform(label, low, high) : [low, high]๋ฒ์ ๋ด์ ์ค์๊ฐ ๋๋ค ์ ํ
- hp.quniform(label, low, high, q) : [low,high]์ฌ์ด ๊ท ๋ฑ ๋ถํฌ์์ q๊ฐ๊ฒฉ์ ์ผ์ ์์ ๋ค๋ก๋ถํฐ ๋๋ค ์ ํ
- hp.normal(label, mu, sigma) : ํ๊ท mu, ํ์คํธ์ฐจ sigma๋ฅผ ๊ฐ๋ ์ ๊ท๋ถํฌ๋ก๋ถํฐ ์ค์๊ฐ ๋๋ค ์ ํ
- ์์ธํ ๋ด์ฉ์ ์ฌ๊ธฐ๋ฅผ ์ฐธ๊ณ
from hyperopt import hp, fmin, tpe, Trials, STATUS_OK
from sklearn.model_selection import cross_val_score
params = {'simpleimputer__strategy': hp.choice('strategy', ['median','mean']),
'xgbclassifier__max_depth': hp.quniform('max_depth', 2, 10, 2),
'xgbclassifier__min_child_weight': hp.quniform('min_child_weight',2,10,2),
'xgbclassifier__colsample_bytree': hp.uniform('colsample_bytree', 0.5,1.0)}
# hyperopt ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ฌ์ฉ ์ ํ์ต ๋ฐ ๊ฒ์ฆ ํจ์ ์ง์ ์์ฑํด์ค์ผํจ.
def get_pipe(params):
# max_depth๋ ์ ์ํ์ผ๋ก ๋ณํ
parmas['xgbclassifier__max_depth'] = int(parmas['xgbclassifier__max_depth']
pipe = make_pipeline(OrdinalEncoder(),
SimpleImputer(strategy='median'),
XGBClassifier(objective='binary:logistic',
eval_metric='error',
n_estimators=200,
learning_rate=0.1,
use_label_encoder=True,
n_jobs=-1)
pipe = pipe.set_parms(**params)
return pipe
# ๋ชฉ์ ํจ์
def fit_and_eval(params):
pipe = get_pipe(params) # ์ฃผ์ด์ง params๋ก ํ์ดํ๋ผ์ธ์ ๋ง๋ค์ด ๊ฐ์ ธ์จ๋ค.
# ์ฑ๋ฅ ๊ฒ์ฆ
score = cross_val_score(pipe, x_train, y_train, cv=3, scoring='roc_auc')
avg_cv_score = np.mean(score)
# roc_auc๋ ํด์๋ก ์ข์ metric์ด๋ฏ๋ก, hpyeropt.fmin์ด roc_auc๋ฅผ ์ต๋ํํ๋๋ก ํ๊ธฐ์ํด
# - ๋ถํธ๋ฅผ ๋ถ์ฌ ๋ฐํํจ.
return {'loss': -avg_cv_score, 'status':STATUS_OK}
# ํ์ต ์ ๋ณด ์ ์ฅ
trials = (Trials())
# ํ์ตํ๊ธฐ
best_parmas = fmin(fn=fit_and_eval, # ๋ชฉ์ ํจ์
trials=trials, # ์๋ํ ์
๋ ฅ ๋ฐ ์
๋ ฅ ๊ฒฐ๊ณผ ์ ์ฅ
space=params, # ๊ฒ์ ๊ณต๊ฐ
ago=tpe.suggest, # ๋ฒ ์ด์ง์ ์ต์ ํ ์ ์ฉ ์๊ณ ๋ฆฌ์ฆ
max_evals=10, # ์๋ํ์
rstate=np.random.default_rng(2023)) # ์๋ํ ๋๋ง๋ค ๋์ผํ ๊ฒฐ๊ณผ๋ฅผ ๋ก
trials.trials # ๋ชจ๋ trial ์ ๋ณด์ ๋ํด ์ง์ ์ ๊ทผ ๊ฐ๋ฅ
# Trials() ๊ฐ์ฒด๋ฅผ fmin์ ํจ๊ป ๋ฃ์ด ์คํํ๋ฉด,
# ์คํ๋๋ ๋งค fit์ ํ์ต ์ ๋ณด ๋ฐ ํ์ต ๊ฒฐ๊ณผ๊ฐ ํด๋น ๊ฐ์ฒด์ ๋ชจ๋ ์ ์ฅ๋จ
trials.best_trial['misc']['vals'] # ์ต์ ํ๋ผ๋ฏธํฐ
>> {'colsample_bytree': [0.6709747268729134], 'max_depth': [4.0],
'min_child_weight': [8.0], 'strategy': [1]}
-trials.best_trial['result']['loss']) # ์ต์ AUC
>> 0.8491
์ด ๊ณผ์ ์ ๋ฐ๋ณตํ์ฌ, ์ต์ ์ ํ์ดํผํ๋ผ๋ฏธํฐ๋ฅผ ํ์ธํ๋ค!
best_max_depth = int(best_params['max_depth']
best_min_child_weight = int(best_params['min_child_weight']
best_colsample_bytree = int(best_params['colsapmle_bytree']
# ์ต์ข
์ ๋ชจ๋ธ ์ ์ธ
best_search = make_pipeline(OrdinalEncoder(),
XGBClassifier(max_depth=best_max_depth,
min_child_weight=best_min_child_weight,
colsample_bytree=best_colsample_bytree))
# ํ์ตํ๊ธฐ
best_search.fit(x_train, y_train)
# ํ์ต, ๊ฒ์ฆ ์ฑ๋ฅ ๋น๊ต
y_pred_train = best_search.predict(x_train)
print("ํ์ต f1-score", f1_score(y_train, y_pred_train))
print("๊ฒ์ฆ f1-score", -trials.best_trial['result']['loss'])
>> ํ์ต F1: 0.6106811145510836
๊ฒ์ฆ F1: 0.5818764879623988
hyperopt ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ฌ์ฉ ์ ํ์ต ๋ฐ ๊ฒ์ฆ ํจ์๋ฅผ ์ง์ ์์ฑํด์ฃผ์ด์ผํจ.
loss๋ฅผ ๊ฐ์ฅ ์๊ฒ ๋ง๋ค์ด์ฃผ๋ ํ์ดํผํ๋ผ๋ฏธํฐ ์กฐํฉ ์ ํ, ํด์๋ก ์ข์ metric์ ๊ฒฝ์ฐ -๋ถํธ๋ฅผ ๋ถ์ฌ ๋ฐํํด์ฃผ์ด์ผํจ.
loss : -auc (hyperopt)
score : -mse (sklearn)
๋ชฉ์ ํจ์๊ฐ ์ต์๊ฐ ๋๋๋ก ํด์ผํจ. f1๊ฐ์ ํด์๋ก ์ข์ ๊ฒ์ด๋, score ์ -๋ฅผ ๋ถ์ฌ์ ๋ฆฌํดํด์ฃผ์ด, f1๊ฐ์ ํค์ฐ๊ณ ์๊ณ ๋ชฉ์ ํจ์๊ฐ์ ์์์ง๊ฒ ํ๋ค.
fmin : find minimum : ์ฐ๋ฆฌ๊ฐ ๋ง๋ ๋ชฉ์ ํจ์์ ์ต์๊ฐ์ด ๋ ๋๊น์ง ์ฐพ์๋ผ!
sckit learn์ random state๋ก ์ง์ ํด์ฃผ๋ฉด ๋๋๋ฐ, ์ด๊ฒ์ rstate๋ก ๋ฐ๋ก ์ง์ ํด์ค์ผํจ.
๐ ํน์ฑ ์ ํ
๋ฐ์ดํฐ๊ฐ ์ถฉ๋ถํ์ง ์์ ์ํฉ์์๋ ๋ถํ์ํ ํน์ฑ์ด ๊ณผ์ ํฉ์ ์์ธ์ด ๋ ์ ์์
์ค์ํ์ง ์์ column dropํ๋ฉฐ ํน์ฑ ์ ํํด๋ณด์!
ํน์ฑ ์ค์๋ ๊ธฐ๋ฐ ํน์ฑ ์ ํ
์ ํํ๊ท ๊ธฐ๋ฐ ๋ชจ๋ธ์ ๊ฒฝ์ฐ coefficient๋ฅผ ํตํด ,
ํธ๋ฆฌ ๊ธฐ๋ฐ ๋ชจ๋ธ์ ๊ฒฝ์ฐ feature_importance๋ฅผ ํตํด ํน์ฑ์ ์ค์๋ ์์น๊ฐ ์ป์.
→ ์ด๋ฅผ ๊ธฐ๋ฐ์ผ๋ก, ํน์ ๊ฐ ์๋์ ์ค์๋๋ฅผ ๊ฐ๋ ํน์ฑ๋ค drop์ํฌ ์ ์๋ค.
train_sub, val = train_test_split(train, test_size=0.2, stratify=train[target], random_state=42)
X_train, y_train = train_sub.drop(columns=target), train_sub[target]
X_val, y_val = val.drop(columns=target), val[target]
pipe = make_pipeline(
OrdinalEncoder(),
SimpleImputer(strategy="mean"),
XGBClassifier(
objective="binary:logistic",
eval_metric="auc",
n_estimators=200,
random_state=42,
n_jobs=-1,
max_depth=6,
min_child_weight=6,
colsample_bytree=0.7,
learning_rate=0.1,
use_label_encoder=False,
),
)
pipe.fit(X_train, y_train)
print("๊ฒ์ฆ AUC: ", pipe.score(X_val, y_val))
>> ๊ฒ์ฆ AUC: 0.8255248487723876
feature_importances = list(
zip(X_train.columns, pipe.named_steps["xgbclassifier"].feature_importances_)
)
feature_importances = sorted(feature_importances, key=lambda x: x[1], reverse=True)
plt.figure(figsize=(10, 10), dpi=120)
plt.barh(*list(zip(*feature_importances[::-1])))
plt.axvline(0.015, color="red", linewidth=0.5)
ํน์ฑ ์ค์๋๊ฐ 0.015๋ฏธ๋ง์ธ ํน์ฑ๋ค dropํ ์ฌํ์ต
features_selected = list(filter(lambda x: x[1] >= 0.015, feature_importances))
print(features_selected)
selected_feature_names = list(map(lambda x: x[0], features_selected))
X_train_selected = X_train[selected_feature_names]
X_val_selected = X_val[selected_feature_names]
pipe = make_pipeline(
OrdinalEncoder(),
SimpleImputer(strategy="mean"),
XGBClassifier(
objective="binary:logistic",
eval_metric="auc",
n_estimators=200,
random_state=42,
n_jobs=-1,
max_depth=6,
min_child_weight=6,
colsample_bytree=0.7,
learning_rate=0.1,
use_label_encoder=False,
),
)
pipe.fit(X_train_selected, y_train)
print("๊ฒ์ฆ AUC: ", pipe.score(X_val_selected, y_val))
print("ํน์ฑ ์:")
print("\tBefore: ", X_train.shape[1])
print("\tAfter: ", X_train_selected.shape[1])
>>
๊ฒ์ฆ AUC: 0.8255248487723876
ํน์ฑ ์:
Before: 32
After: 10
→ feature ๊ฐ์๊ฐ ์ ์ด์ ธ๋, score์ ๋น์ทํ ๊ฒ ํ์ธ ๊ฐ๋ฅ!
์ฐจ์๊ฐ์์ ์ด์ ธ์ ์คํ๋ ค ์ข์!
ํต๊ณ๋ ๊ธฐ๋ฐ ํน์ฑ ์ ํ
๊ฐ ํน์ฑ๋ค๊ณผ ํ๊ฒ๊ฐ ๊ฐ์ ํต๊ณ๋์ผ๋ก๋ถํฐ ๊ฐ ํน์ฑ์ ์ํฅ๋ ฅ ์ถ์ธกํด ๋ฎ์ ์ํฅ๋ ฅ ๊ฐ๋ ํน์ฑ๋ค ์ ๊ฑฐ
- ํผ์ด์จ ์๊ด๊ณ์
- ์ฐ์ํ ํน์ฑ, ์ฐ์ํ ํ๊ฒ์ ๊ฒฝ์ฐ
np.corrcoef
๋จ์ : ๋ ํน์ฑ ๊ฐ์ ์ ํ ๊ด๊ณ์ฑ๋ง ํ์ธ ๊ฐ๋ฅ
- ์คํผ์ด๋ง ์๊ด๊ณ์
- ๋ ํน์ฑ์ ์ ํ์ฑ์ด ์๋ ๋จ์กฐ์ฑ ๋ณด์ฌ์ค. ์ฆ, ํ ํน์ฑ์ด ์ปค์ง ๋ ๋ค๋ฅธ ํน์ฑ์ด ํจ๊ป ์ปค์ง๋์ง๋ฅผ ์์นํํด์ค.
- ๊ฐ ํน์ฑ์ ๊ฐ๋ค์ ๊ทธ ๊ฐ์ ์ ์ฒด์์์ ์์๋ก ๋์นํ ๋ค์, ํผ์ด์จ ์๊ด๊ณ์๋ฅผ ๊ตฌํ๋ ๊ฒ๊ณผ ๋์ผ
scipy.stats.spearmanr
# ๋ ํน์ฑ์ด ๋น์ ํ ๊ด๊ณ์ด์ง๋ง, ๋จ์กฐ ๊ด๊ณ์ผ ๋ ์ดํด๋ณด์
# y=x^3
x = np.random.normal(0,5,1000)
y = x**3+np.random.normal(0,1,1000)
plt.plot(x,y,'.')
print("Pearson Corrcoef:", np.corrcoef(x, y)[0, 1])
print("Spearman Corrcoef:", spearmanr(x, y))
>> Pearson Corrcoef: 0.7745216717448516
Spearman Corrcoef: SignificanceResult(statistic=0.9968557448557448, pvalue=0.0)
ํผ์ด์จ / ์คํผ์ด๋ง ์๊ด๊ณ์ ํต๊ณ๋์ ์ด์ฉํด, ํ๊ฒ๊ฐ๊ณผ ํต๊ณ๋์ด ์์ k๋ด์ ๋๋ ํน์ฑ๋ค๋ง ์ ํํ๊ฑฐ๋, ์ ์ ํ threshold๋ฅผ ์ง์ ํ์ฌ ํด๋น ๊ฐ ์ด์์ ํต๊ณ๋์ ๊ฐ๋ ํน์ฑ๋ค๋ง ํ์ต์ ์ด์ฉ ๊ฐ๋ฅ
sklearn.feature_selection.SelectKBest
๋ฌธ์ ์ ์ ํ(๋ถ๋ฅ/ํ๊ท)์ ๋ฐ๋ผ ๋ค์ํ ํต๊ณ๋์ ๊ธฐ๋ฐ์ผ๋ก ํน์ฑ ์ ํํ ์ ์๊ฒํจ.
score_func
์ ๋ฐ๊ฟ์ค์ผ๋ก์จ ์๋ก ๋ค๋ฅธ ํต๊ณ๋์ผ๋ก๋ถํฐ ํน์ฑ ์ ํ ๊ฐ๋ฅ
๋ํ์ ์ธ ๋ช ๊ฐ์ง ํต๊ณ๋ ์ต์ (score_func)
๋ถ๋ฅ/ํ๊ท ๋ฌธ์ ์ ๋ฐ๋ผ ์ ์ ํ ์ต์ ์ ํํด์ผํจ.
๋ถ๋ฅ ํ๊ฒ์ ์ํ ์ต์ ๋ค
f_classif
mutual_info_classif
chi2
ํ๊ท ํ๊ฒ์ ์ํ ์ต์ ๋ค
f_regression
mutual_info_regression
from category_encoders import OneHotEncoder
enc = OrdinalEncoder()
imp = SimpleImputer()
X_train_encoded = enc.fit_transform(X_train)
X_train_imputed = imp.fit_transform(X_train_encoded)
X_val_encoded = enc.transform(X_val)
X_val_imputed = imp.transform(X_val_encoded)
from sklearn.feature_selection import SelectKBest, mutual_info_classif
selector = SelectKBest(score_func=mutual_info_classif, k=6)
X_train_selected = selector.fit_transform(X_train_imputed, y_train)
X_val_selected = selector.transform(X_val_imputed)
# ์ ํ๋ ํน์ฑ
X_train_encoded.columns[selector.get_support()].tolist()
>> ['h1n1_knowledge', 'doctor_recc_h1n1', 'health_insurance', 'health_worker', 'opinion_h1n1_vacc_effective', 'opinion_h1n1_risk']
model = XGBClassifier(
objective="binary:logistic",
eval_metric="auc",
n_estimators=200,
random_state=42,
n_jobs=-1,
max_depth=6,
min_child_weight=6,
colsample_bytree=0.7,
learning_rate=0.1,
use_label_encoder=False,
)
model.fit(X_train_selected, y_train)
print("๊ฒ์ฆ AUC: ", model.score(X_val_selected, y_val))
print("ํน์ฑ ์:")
print("\tBefore: ", X_train.shape[1])
print("\tAfter: ", X_train_selected.shape[1])
>> ๊ฒ์ฆ AUC: 0.8268295575851026
ํน์ฑ ์:
Before: 32
After: 6
feature ๊ฐ์๊ฐ 6์ผ๋ก ์ค์๊ณ , ์ฑ๋ฅ์ ์์ฃผ์กฐ๊ธ ๋์์ก๋ค! good!
More Study
- pipeline์ธ๋ / ์์ธ๋์ ๋ฐ๋ผ ์ฝ๋ ๊ตฌ๋ถ. (pipeline ์ฐ๋ฉด ํ๋ผ๋ฏธํฐ ๋์ ๋๋ฆฌ ์ ์ธ ์, ์์ ๋ชจ๋ธ์ด๋ฆ๋ ๊ฐ์ด ์จ์ค์ผํจ)
- ํน์ฑ ์ค์๋ ํ์ธ ์, grid_search.best_estimator_ (์ด๊ฑด ๋ด๋ถ๋ฅผ ๋ด์ผ๋๋๊ป ๋ถ๋ฌ์ค๊ธฐ)→ ์ต์ ์ ํ๋ผ๋ฏธํฐ๊ฐ ์ฐ์ธ ๋ชจ๋ธ์ ๊ฐ์ ธ์์ผ feature imporatances ํ์ธ ๊ฐ๋ฅ
grid search๊ฐ ๊ฐ์ฅ ์ฑ๋ฅ์ด ์ข์ง๋ง, ๋๋ฌด ๋๋ฆฌ๋ค...
์๊ฐ์ด ์๋ค๋ฉด , random search!!๋ ๋ฒ ์ด์ง์ ์ฐ๊ธฐ
๋ฒ ์ด์ง์์ ๋น์ฐํ grid๋ณด๋จ ์ข์ง ์์ง๋ง, ์ฑ๋ฅ์ด ๋ง ์ข์ง ์์ง๋ง, ๋น ๋ฅด๋ค.
๋ฒ ์ด์ง์์ ๊ทธ๋ฆฌ ๋ง์ด ์ฐ์ด์ง ์๋๋ค๊ณ ํ๋ค
์ธ์ฝ๋ฉ, ์ค์ผ์ผ๋ง์ train / test ๋ถ๋ฆฌ ํ ํ์ ํด์ผํจ!!
why?
ํ ์คํธ์ฉ ๋ฐ์ดํฐ๋ ์ฐ๋ฆฌ๊ฐ ๋ฏธ๋๋ฐ์ดํฐ์ด๋ค. ์ฐ๋ฆฌ์๊ฒ ์๋ค๊ณ ๋ด์ผํ๋ค.
ํ ์คํธ ๋ฐ์ดํฐ๋ ํ์ฌ ๋ฐ์ดํฐ์ ์ํฅ์ ์ฃผ๋ฉด ์๋๋ค.
์ธ์ฝ๋ฉ,์ค์ผ์ผ๋ง์ ๊ท์น์ ๋ง๋ ๋ ํจํด์ ํ๊ฐ์ฉ ๋ฐ์ดํฐ๋ค์ด ๊ฐ์ด ๊ท์นํจํด์ ๋ง๋ค๊ฒ ๋๋ฉด ์๋๋ค.
์ธ์ฝ๋, ์ค์ผ์ผ๋ง ์ ๊ทธ ๋ชจ๋ธ์ ๋จผ์ ํ๋ จ๋ฐ์ดํฐ๋ก ํ์ตํ ํ, ๊ทธ๊ฑฐ๋ฅผ ๊ธฐ์ค์ผ๋ก ํ ์คํธ๋ฐ์ดํฐ๋ ํ์ต์ํด.
ํ์ดํผํ๋ผ๋ฏธํฐ ํ๋์ ์ฌ์ฉํ๋ cv๋ ๋ฌด์์ ์๋ฏธํ๋?
์ด๊ฒ๋ cross validation์ผ๋ก, ํ๋ ๊ณผ์ ์์ ์ฐพ์ ์กฐํฉ์ ํ๋์ ๋ฐ์ดํฐ์ ์ ๋ํด์๋ง ์ฑ๋ฅ์ ํ๊ฐํด๋ณธ๋ค๋ฉด ์ด ์ฑ๋ฅ์ ์ ๋ขฐํ๊ธฐ ์ด๋ ต๋ค.
- Ex 1) max_depth = 7 -> ํ๋์ ๋ฐ์ดํฐ์ ์ฌ์ฉ -> ์ ํ๋ 0.9 -> ์ ํ๋๊ฐ ์์ฒญ ๋๋ค!๊ทผ๋ฐ ์ด ๊ฒฐ๊ณผ๋ฅผ ๋ฏฟ์ ์ ์์๊น?
- Ex 2) max_depth = 7 ->
cv=3
-> 3๊ฐ์ ๋ฐ์ดํฐ์ ์ ๊ฒ์ฆ์ผ๋ก ์ฌ์ฉ -> ์ ํ๋ ๊ฐ๊ฐ 0.9, 0.7, 0.8 -> ํ๊ท ์ ํ๋ 0.8 -> ์ ํ๋๊ฐ ์ค์ํ๊ณ , ์ฌ๋ฌ ๋ฒ ๊ฒ์ฆํด์ ์ ๋ขฐํ ์ ์๊ฒ ๋ค!
→ ํ๋ ๊ณผ์ ์์ ์ฐพ์ ์กฐํฉ์ CV๋ก ์ฌ๋ฌ ๋ฒ ๊ฒ์ฆํด ๋ด์ผ๋ก์จ ํด๋น ์กฐํฉ์ด ์ด๋ ์ ๋์ ์ผ๋ฐํ ์ฑ๋ฅ์ ๋ด๋์ง ํ๊ฐํด๋ณผ ์ ์๋ค.
ํ์ดํผํ๋ผ๋ฏธํฐ ํ๋์ ์ฌ์ฉํ๋ scoring์๋ ์ด๋ค ํ๊ฐ์งํ๋ฅผ ์ฌ์ฉํด์ผ ํ ๊น?
- ํ๊ณ ์ ํ๋ ๋ถ๋ฅ ๋ฌธ์ ์์ F1-score๋ฅผ ํ๊ฐ์งํ๋ก ์ฌ์ฉํ๊ณ ์๋๋ฐ ํ๋ ๊ณผ์ ์์
scoring=accuracy
๋ก ์ค์ ํ๋ฉด ์ด๋ป๊ฒ ๋ ๊น?- ์ฐ๋ฆฌ๋ ํ๋์ ํตํด F1-score๊ฐ ๊ฐ์ฅ ๋์ ๋ชจ๋ธ๊ณผ ํ์ดํผํ๋ผ๋ฏธํฐ ์กฐํฉ์ ์ป๊ณ ์ถ์ ๊ฒ์ธ๋ฐ ํ๋ ํ ๋์ถ๋ ๊ฒฐ๊ณผ๋ ์ ํ๋๊ฐ ๊ฐ์ฅ ๋์ ์กฐํฉ์ผ ๊ฒ์ด๋ค.
- ๋ฐ๋ผ์ ํ๋์ ์ฌ์ฉํ๋
scoring
์ต์ ์๋ ์ฐ๋ฆฌ๊ฐ ํ๊ณ ์๋ ๋ฌธ์ ์์ ์ฌ์ฉ๋๋ ๊ฐ์ฅ ์ ํฉํ ํ๊ฐ์งํ๋ฅผ ์ฌ์ฉํด์ฃผ์ด์ผ ํ๋ค.
ํ์ง๋ง, ํ๋ผ๋ฏธํฐ์ ์ธ๋ฐํ ์กฐ์ ์ผ๋ก ์ต์ ํ๋ ์ฑ๋ฅ์ ์ป์์์ง๋ผ๋ ์ด์ํ๊ฒฝ์์๋ ์ฑ๋ฅ์ด ๊ผญ ๋ณด์ฅ๋๋ ๊ฒ์ ์๋๋ค..
๋ฐ๋ผ์..! ๋ชจ๋ธ๋ง ๋ชฉํ๋ก๋,
์๋ฒฝํ์ ์ ํ ์์ธก๋ ฅ์ ์ํด ์ ์ ํ ๋ณต์ก๋์ ๋ชจ๋ธ์ ์์ฑํ๋ ๊ฒ์ด๋ค!!!
[references]
'Machine Learning' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Applied Predictive Modeling 2] Interpretable ML(2) (0) | 2023.04.17 |
---|---|
[Applied Predictive Modeling 1] Interpretable ML (0) | 2023.04.17 |
[The Based Models 3] Preprocessing (0) | 2023.04.15 |
[The Based Models 2] Boosting (0) | 2023.04.14 |
[The Based Models 1] Tree Based Model (0) | 2023.04.14 |