์์ํ๋ฉฐ: ํ์ค์ ์ธ ๋ชจ๋ธ๋ง์ ๋์ ํ๋ค
์ด๋ฒ์๋ ์ํ ๋ง์ผํ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ง๊ณ ๊ณ ๊ฐ์ด ์ ๊ธฐ ์๊ธ์ ๊ฐ์ ํ ์ง ์์ธกํ๋ ํ๋ก์ ํธ๋ฅผ ์งํํ๋ค. ๋ฐ์ดํฐ ์ ์ฒ๋ฆฌ๋ถํฐ ์ฌ๋ฌ ๋ชจ๋ธ์ ๋น๊ตํ๊ณ , ํ์ดํผํ๋ผ๋ฏธํฐ ํ๋, ๊ทธ๋ฆฌ๊ณ AutoML ๋๊ตฌ์ธ PyCaret๊น์ง ์ฌ์ฉํด๋ณธ, ๊ทธ์ผ๋ง๋ก ๋จธ์ ๋ฌ๋ ๋ถ๋ฅ์ ์ข ํฉ์ ๋ฌผ์ธํธ ๊ฐ์ ๊ฒฝํ์ด์๋ค.
๐ก โ์ง์ง ์ค์ํ ๊ฑด, ์ค์ ์๊ธ ๊ณ ๊ฐ์ ๋์น์ง ์๋ ๊ฒ!โ
์ด๋ฒ ํ๋ก์ ํธ์ ํต์ฌ ๋ชฉํ๋ ๋ฐ๋ก ์ฌํ์จ(Recall) ์ ๋์ด๋ ๊ฒ์ด์๋ค. ๋ชจ๋ธ์ ์ ํ๋๋ง ๋์ด๋ ๊ฑด ์๋ฏธ๊ฐ ์์๋ค. ์ง์ง ๊ณ ๊ฐ์ ํ๋๋ผ๋ ๋ ์ฐพ์๋ด๋ ๋ชจ๋ธ์ ๋ง๋๋ ์ฌ์ , ์ง๊ธ ์์ํ๋ค.
๐ฅ 1๋จ๊ณ: ๋ฐ์ดํฐ์์ ์ฒซ ๋ง๋จ
UCI ์ ์ฅ์์ ์ํ ๋ง์ผํ
๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ๋ค. ๊ณ ๊ฐ์ ๋์ด, ์ง์
, ๋์ถ ์ฌ๋ถ ๊ฐ์ ์ ๋ณด๋ก ์๊ธ ๊ฐ์
์ฌ๋ถ(y
)๋ฅผ ์์ธกํ๋ ๋ฌธ์ ์๋ค. ๋ฐ์ดํฐ๋ฅผ ์ดํด๋ณด๋ no
์ yes
๋น์จ์ด ์ฝ 8:1๋ก, ๋ฐ์ดํฐ ๋ถ๊ท ํ์ด ์ฌ๊ฐํ๋ค. ์ด๊ฑด ์ ํ๋๋ง ๋ฏฟ๊ณ ๊ฐ๋ค๊ฐ ํฐ์ผ๋๋ค๋ ์ ํธ์๋ค. ๐จ
๊ทธ๋ฆฌ๊ณ ์ค์ํ ๋ฐ๊ฒฌ! duration
(ํตํ ์๊ฐ)์ด๋ผ๋ ํผ์ฒ๊ฐ ์์๋๋ฐ, ์ด๊ฑด ์์ธก ์์ ์์๋ ์ ์ ์๋, ๊ฒฐ๊ณผ์ ๊ฐ๊น์ด ์ ๋ณด์๋ค. ์ด๋ฐ ์ฌํ ์ ๋ณด๋ฅผ ์ฌ์ฉํ๋ฉด ๋ชจ๋ธ์ด ๊ณผ๋์ ํฉ๋๊ธฐ ์ฌ์์ ๊ณผ๊ฐํ ์ ์ธํ๋ค. ํ์ค์ ์ธ ๋ชจ๋ธ๋ง์ ์ฒซ๊ฑธ์์ด์๋ค๊ณ ์๊ฐํ๋ค.
โจ 2๋จ๊ณ: ๋ฐ์ดํฐ ์ฑํ์์ (์ ์ฒ๋ฆฌ)
๋ชจ๋ธ์ด ๋ฐ์ดํฐ๋ฅผ ์ ์ํํ ์ ์๋๋ก ๊น๋ํ๊ฒ ๋ค๋ฌ์ด์ฃผ๋ ๊ณผ์ ์ด ํ์์๋ค.
- ์์นํ ๋ฐ์ดํฐ: ํผ์ฒ๋ง๋ค ๊ฐ์ ๋ฒ์๊ฐ ์ ๊ฐ๊ฐ์ด๋ผ StandardScaler๋ฅผ ์ฌ์ฉํด์ ํ๊ท 0, ๋ถ์ฐ 1๋ก ๋ง์ถฐ์คฌ๋ค. ์ด์์น์ ๋ ๋ฏผ๊ฐํด์ ๊ฐ์ฅ ๋ฌด๋ํ๊ณ ์์ ์ ์ธ ์ ํ์ด์๋ค.
-
๋ฒ์ฃผํ ๋ฐ์ดํฐ: ๋ฌธ์์ด์ ๋ชจ๋ธ์ด ์ดํด ๋ชป ํ๋๊น ์ซ์๋ก ๋ฐ๊ฟ์ผ ํ๋ค. ๊ฐ ์นดํ
๊ณ ๋ฆฌ๋ฅผ ์๋ก์ด ํผ์ฒ๋ก ๋ง๋๋ OneHotEncoder๋ฅผ ์ฌ์ฉํ๋ค.
drop='first'
์ต์ ์ผ๋ก ๋ค์ค๊ณต์ ์ฑ ๋ฌธ์ ๋ ํผํ๊ณ ํผ์ฒ ์๋ ์ค์ด๋ ๊ฟํ๋ ์์ง ์์๋ค.
# ์์นํ ๋ฐ์ดํฐ ์ค์ผ์ผ๋ง
scaler = StandardScaler()
X_train[num_cols] = scaler.fit_transform(X_train[num_cols])
X_test[num_cols] = scaler.transform(X_test[num_cols])
# ๋ฒ์ฃผํ ๋ฐ์ดํฐ ์ธ์ฝ๋ฉ
encoder = OneHotEncoder(drop='first')
# ... ์ธ์ฝ๋ฉ ๊ณผ์ ์๋ต ...
โ๏ธ 3๋จ๊ณ: ๋ชจ๋ธ ์ผํ! ์ต๊ณ ์ ๋ถ๋ฅ๊ธฐ๋?
์์ฌ๊ฒฐ์ ๋๋ฌด, ๋๋ค ํฌ๋ ์คํธ, KNN, ๋ก์ง์คํฑ ํ๊ท, ์ด๋ ๊ฒ 4๊ฐ์ง ๊ธฐ๋ณธ ๋ชจ๋ธ์ ๋ง๋ค์ด์ ์ฑ๋ฅ์ ๋น๊ตํด๋ดค๋ค. ์ด๋ฒ ๋ฌธ์ ์์๋ ์ฌํ์จ(Recall) ์ด ๊ฐ์ฅ ์ค์ํ ์งํ์๊ธฐ ๋๋ฌธ์, ์ด ์ ์๋ฅผ ์ค์ ์ ์ผ๋ก ๋ดค๋ค.
๊ฒฐ๊ณผ๋? ์ ๋ฐ์ ์ธ ์ฑ๋ฅ(์ ํ๋, AUC)์ ๋๋ค ํฌ๋ ์คํธ๊ฐ ๊ฐ์ฅ ์ข์์ง๋ง, ์ ์ ์ค์ํ ์ฌํ์จ์ ๋ค๋ฅธ ๋ชจ๋ธ๊ณผ ๋น์ทํ๊ฑฐ๋ ์คํ๋ ค ๋ฎ๊ธฐ๋ ํ๋ค. ๋ชจ๋ธ๋ง๋ค ์ฅ๋จ์ ์ด ์๋ค๋ ๊ฑธ ๋ค์ ํ๋ฒ ๋๊ผ๋ค.
๐ ๏ธ 4๋จ๊ณ: ๋ชจ๋ธ ์ฑ๋ฅ ์ฅ์ด์ง๊ธฐ (ํ์ดํผํ๋ผ๋ฏธํฐ ํ๋)
๊ฐ์ฅ ์ ๋ ฅํ๋ ๋๋ค ํฌ๋ ์คํธ๋ฅผ RandomizedSearchCV
๋ก ์ต์ ํํด๋ดค๋ค. ๋ชจ๋ ์กฐํฉ์ ๋ค ํด๋ณด๋ GridSearchCV
๋ณด๋ค ํจ์ฌ ํจ์จ์ ์ด๊ธฐ ๋๋ฌธ์ด๋ค.
# RandomizedSearchCV๋ก ์ต์ ํ๋ผ๋ฏธํฐ ํ์
param_grid = {'n_estimators': [100, 300, 500], 'max_depth': [50, 80, 100], ...}
rfc = RandomForestClassifier(random_state=42)
rm_model = RandomizedSearchCV(rfc, param_distributions=param_grid, cv=5, scoring='recall', n_iter=5)
rm_model.fit(X_train, y_train)
๊ทธ๋ฐ๋ฐโฆ ํ๋ ํ ์ฌํ์จ์ด ์คํ๋ ค ๋จ์ด์ก๋ค. ๐ญ ๋ฌด์กฐ๊ฑด ํ๋์ด ๋ฅ์ฌ๋ ์๋๋ผ๋ ๋ผ์ํ ๊ตํ์ ์ป์๋ค. ๊ธฐ๋ณธ ๋ชจ๋ธ์ด ์ด๋ฏธ ๊ด์ฐฎ์๊ฑฐ๋, ๋ด๊ฐ ์ค์ ํ ํ๋ผ๋ฏธํฐ ๋ฒ์๊ฐ ์ต์ ์ด ์๋์์ ์๋ ์๊ฒ ๋ค๋ ์๊ฐ์ด ๋ค์๋ค.
๐ค 5๋จ๊ณ: AutoML ์นํธํค, PyCaret ๋ง๋ณด๊ธฐ
๋ช ์ค์ ์ฝ๋๋ก ์ด ๋ชจ๋ ๊ณผ์ ์ ์๋ํํ๋ PyCaret์ ์จ๋ดค๋๋ฐ, ์ด๊ฑด ์ ๋ง ์ ์ธ๊ณ์๋ค!
from pycaret.classification import *
s = setup(df_bank_ready2, target = 'y', session_id = 123)
best = compare_models()
tuned_best_model = tune_model(best)
๋ฐ์ดํฐ ์ ์ฒ๋ฆฌ๋ถํฐ ๋ชจ๋ธ ๋น๊ต, ํ๋๊น์ง ์์์ ๋ค ํด์ฃผ๋ ์์ฐ์ฑ์ด ํญ๋ฐํ๋ค. ํ๋ก์ ํธ ์ด๊ธฐ์ ๋น ๋ฅด๊ฒ ๋ฒ ์ด์ค๋ผ์ธ ๋ชจ๋ธ์ ๋ง๋ค ๋ ์์ผ๋ก ๋ฌด์กฐ๊ฑด ์ฌ์ฉํ ๊ฒ ๊ฐ๋ค.
โจ ์ค๋์ ํ๊ณ
์ด๋ฒ ํ๋ก์ ํธ๋ ๋จธ์ ๋ฌ๋ ๋ถ๋ฅ ๋ฌธ์ ์ A to Z๋ฅผ ๊ฒฝํํด๋ณธ ์์คํ ์๊ฐ์ด์๋ค. ๋ฐ์ดํฐ ๋ถ๊ท ํ์ ์ค์์ฑ์ ๋ชธ์ผ๋ก ๋๊ผ๊ณ , ์ํฉ์ ๋ง๋ ์ ์ฒ๋ฆฌ์ ํ๊ฐ ์งํ(ํนํ ์ฌํ์จ!) ์ ํ์ด ์ผ๋ง๋ ์ค์ํ์ง ๊นจ๋ฌ์๋ค.
์ฌ๋ฌ ๋ชจ๋ธ์ ์ง์ ๋ง๋ค๊ณ ๋น๊ตํ๋ฉฐ ๊ฐ ์๊ณ ๋ฆฌ์ฆ์ ์ฅ๋จ์ ์ ํ์ ํ๊ณ , ํ์ดํผํ๋ผ๋ฏธํฐ ํ๋์ด ํญ์ ์ ๋ต์ ์๋๋ผ๋ ํ์ค์ ์ธ ๊ตํ๋ ์ป์๋ค. ๋ง์ง๋ง์ผ๋ก PyCaret ๊ฐ์ AutoML ๋๊ตฌ์ ๊ฐ๋ ฅํจ์ ๋ง๋ณด๋ฉด์, ์์ผ๋ก๋ ๋ ๋น ๋ฅด๊ณ ํจ์จ์ ์ผ๋ก ๋ชจ๋ธ๋ง์ ์์ํ ์ ์๊ฒ ๋ค๋ ์์ ๊ฐ์ด ์๊ฒผ๋ค.