Note
์ฌ์ดํท๋ฐ์
model_selection๋ชจ๋์ ํ์ต ๋ฐ์ดํฐ์ ํ ์คํธ ๋ฐ์ดํฐ ์ธํธ๋ฅผ ๋ถ๋ฆฌํ๊ฑฐ๋ ๊ต์ฐจ ๊ฒ์ฆ ๋ถํ ๋ฐ ํ๊ฐ, ๊ทธ๋ฆฌ๊ณEstimator์ ํ์ดํผ ํ๋ผ๋ฏธํฐ๋ฅผ ํ๋ํ๊ธฐ ์ํ ๋ค์ํ ํจ์์ ํด๋์ค๋ฅผ ์ ๊ณต
1. ํ์ต/ํ
์คํธ ๋ฐ์ดํฐ ์ธํธ ๋ถ๋ฆฌ - train_test_split()
ํ์ต ๋ฐ์ดํฐ ์ธํธ๋ก๋ง ํ์ตํ๊ณ ์์ธกํ๋ฉด ๋ฌด์์ด ๋ฌธ์ ์ผ๊น?
- ๋ค์ ์์ ๋ ํ์ต๊ณผ ์์ธก์ ๋์ผํ ๋ฐ์ดํฐ ์ธํธ๋ก ์ํํ ๊ฒฐ๊ณผ
from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score
iris = load_iris()
dt_clf = DecisionTreeClassifier()
train_data = iris.data
train_label = iris.target
dt_clf.fit(train_data, train_label)
# ํ์ต ๋ฐ์ดํฐ ์
์ผ๋ก ์์ธก ์ํ
pred = dt_clf.predict(train_data)
print('์์ธก ์ ํ๋:',accuracy_score(train_label,pred))
>>> ์์ธก ์ ํ๋: 1.0- ์์ธก ์ ํ๋๊ฐ 1.0์ด๋ผ๋ ๋ป์ ์ ํ๋๊ฐ 100%
- ์ฆ, ๋ฌธ์ ์ ์ ๋ต์ ์๊ณ ์๋ ์ํ์์ ๊ฐ์ ๋ฌธ์ ๋ฅผ ํ ์คํธ ํ ๊ฒ!
- ๋ฐ๋ผ์, ์์ธก์ ์ํํ๋ ๋ฐ์ดํฐ ์ธํธ๋ ํ์ต์ ์ํํ ํ์ต์ฉ ๋ฐ์ดํฐ ์ธํธ๊ฐ ์๋ ์ ์ฉ์ ํ ์คํธ ๋ฐ์ดํฐ ์ธํธ์ฌ์ผ ํจ
์ฌ์ดํท๋ฐ์
train_test_split()
- ์๋ณธ ๋ฐ์ดํฐ ์ธํธ์์ ํ์ต ๋ฐ ํ ์คํธ ๋ฐ์ดํฐ ์ธํธ๋ฅผ ์ฝ๊ฒ ๋ถ๋ฆฌ ๊ฐ๋ฅ
train_test_split()๋ ์ฒซ ๋ฒ์งธ ํ๋ผ๋ฏธํฐ๋ก feature ๋ฐ์ดํฐ ์ธํธ, ๋ ๋ฒ์งธ ํ๋ผ๋ฏธํฐ๋ก label ๋ฐ์ดํฐ ์ธํธ๋ฅผ ์ ๋ ฅ๋ฐ๊ณ , ์ ํ์ ์ผ๋ก ๋ค์ ํ๋ผ๋ฏธํฐ๋ฅผ ์ ๋ ฅ ๋ฐ์
test_size: ์ ์ฒด ๋ฐ์ดํฐ์์ test ๋ฐ์ดํฐ ์ธํธ ํฌ๊ธฐ๋ฅผ ์ผ๋ง๋ก ์ํ๋งํ ๊ฒ์ธ๊ฐ๋ฅผ ๊ฒฐ์ (default : 0.25, ์ฆ 25%)train_size: ์ ์ฒด ๋ฐ์ดํฐ์์ train ๋ฐ์ดํฐ ์ธํธ ํฌ๊ธฐ๋ฅผ ์ผ๋ง๋ก ์ํ๋งํ ๊ฒ์ธ๊ฐ๋ฅผ ๊ฒฐ์ (test_sizeparameter๋ฅผ ํต์์ ์ผ๋ก ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์train_size๋ ์ ์ฌ์ฉ๋์ง ์์)shuffle: ๋ฐ์ดํฐ๋ฅผ ๋ถ๋ฆฌํ๊ธฐ ์ ์ ๋ฐ์ดํฐ๋ฅผ ๋ฏธ๋ฆฌ ์์์ง๋ฅผ ๊ฒฐ์ (default : True), ๋ฐ์ดํฐ๋ฅผ ๋ถ์ฐ์์ผ์ ์ข ๋ ํจ์จ์ ์ธ ํ์ต ๋ฐ ํ ์คํธ ๋ฐ์ดํฐ ์ธํธ๋ฅผ ๋ง๋๋ ๋ฐ ์ฌ์ฉrandom_state: ํธ์ถํ ๋๋ง๋ค ๋์ผํ ํ์ต/ํ ์คํธ์ฉ ๋ฐ์ดํฐ ์ธํธ๋ฅผ ์์ฑํ๊ธฐ ์ํด ์ฃผ์ด์ง๋ ๋์ ๊ฐ (train_test_split()๋ ํธ์ถ ์ ๋ฌด์์๋ก ๋ฐ์ดํฐ๋ฅผ ๋ถ๋ฆฌํ๋ฏ๋กrandom_state๋ฅผ ์ง์ ํ์ง ์์ผ๋ฉด ์ํํ ๋๋ง๋ค ๋ค๋ฅธ ํ์ต/ํ ์คํธ ์ฉ ๋ฐ์ดํฐ๋ฅผ ์์ฑ)train_test_split()์ ๋ฐํ๊ฐ์ tuple ํํ๋ก, ์์ฐจ์ ์ผ๋ก train-feature, test-feature, train-label, test-label ๋ฐ์ดํฐ ์ธํธ ๋ฐํ
- ๋ถ๊ฝ ๋ฐ์ดํฐ ์ธํธ๋ฅผ
train_test_split()์ ์ด์ฉํด test ๋ฐ์ดํฐ ์ธํธ๋ฅผ ์ ์ฒด์ 30%, train ๋ฐ์ดํฐ ์ธํธ๋ฅผ 70%๋ก ๋ถ๋ฆฌ
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
dt_clf = DecisionTreeClassifier( )
iris_data = load_iris()
X_train, X_test, y_train, y_test = train_test_split(iris_data.data,iris_data.target,
test_size=0.3, random_state=121)- train ๋ฐ์ดํฐ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก
DecisionTreeClassfier๋ฅผ ํ์ตํ๊ณ ์์ธก ์ ํ๋ ์ธก์
dt_clf.fit(X_train, y_train)
pred = dt_clf.predict(X_test)
print('์์ธก ์ ํ๋: {0:.4f}'.format(accuracy_score(y_test,pred)))
>>> ์์ธก ์ ํ๋: 0.9556๋ถ๊ฝ ๋ฐ์ดํฐ๋ 150๊ฐ์ ๋ฐ์ดํฐ๋ก ๋ฐ์ดํฐ์ ์์ด ํฌ์ง ์์ ์ ์ฒด์ 30% ์ ๋์ธ ํ ์คํธ ๋ฐ์ดํฐ๋ 45๊ฐ ์ ๋๋ฐ์ ๋์ง ์์ผ๋ฏ๋ก ์๊ณ ๋ฆฌ์ฆ์ ์์ธก ์ฑ๋ฅ์ ํ๋จํ๊ธฐ์๋ ๊ทธ๋ฆฌ ์ ์ ํ์ง ์์ โ ํ์ต์ ์ํ ๋ฐ์ดํฐ์ ์์ ์ผ์ ์์ค ์ด์์ผ๋ก ๋ณด์ฅํ๋ ๊ฒ๋ ์ค์ํ์ง๋ง, ํ์ต๋ ๋ชจ๋ธ์ ๋ํด ๋ค์ํ ๋ฐ์ดํฐ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์์ธก ์ฑ๋ฅ์ ํ๊ฐํด ๋ณด๋ ๊ฒ๋ ๋งค์ฐ ์ค์!
2. ๊ต์ฐจ ๊ฒ์ฆ (Cross-Validation, CV)
๊ณผ์ ํฉ (Overfitting)
๋ชจ๋ธ์ด ํ์ต ๋ฐ์ดํฐ์๋ง ๊ณผ๋ํ๊ฒ ์ต์ ํ๋์ด, ์ค์ ์์ธก์ ๋ค๋ฅธ ๋ฐ์ดํฐ๋ก ์ํํ ๊ฒฝ์ฐ์๋ ์์ธก ์ฑ๋ฅ์ด ๊ณผ๋ํ๊ฒ ๋จ์ด์ง๋ ๊ฒ
- ๊ณ ์ ๋ ํ์ต ๋ฐ์ดํฐ์ ํ ์คํธ ๋ฐ์ดํฐ๋ก ํ๊ฐ๋ฅผ ํ๋ค ๋ณด๋ฉด ํ ์คํธ ๋ฐ์ดํฐ์๋ง ์ต์ ์ ์ฑ๋ฅ์ ๋ฐํํ ์ ์๋๋ก ํธํฅ๋๊ฒ ๋ชจ๋ธ์ ์ ๋ํ๋ ๊ฒฝํฅ์ด ์๊ธธ ์ ์์
- ๊ฒฐ๊ตญ์ ํด๋น ํ ์คํธ ๋ฐ์ดํฐ์๋ง ๊ณผ์ ํฉ๋๋ ํ์ต ๋ชจ๋ธ์ด ๋ง๋ค์ด์ ธ ๋ค๋ฅธ ํ ์คํธ์ฉ ๋ฐ์ดํฐ๊ฐ ๋ค์ด์ฌ ๊ฒฝ์ฐ์๋ ์ฑ๋ฅ์ด ์ ํ๋จ โ ์ด๋ฌํ ๋ฌธ์ ์ ์ ๊ฐ์ ํ๊ธฐ ์ํด ๊ต์ฐจ ๊ฒ์ฆ์ ์ด์ฉํด ๋ ๋ค์ํ ํ์ต๊ณผ ํ๊ฐ๋ฅผ ์ํ!
๊ต์ฐจ ๊ฒ์ฆ (Cross-Validation, CV)
์ฃผ์ด์ง ๋ฐ์ดํฐ๋ฅผ ํ๋ จ ๋ฐ์ดํฐ์ ๊ฒ์ฆ ๋ฐ์ดํฐ๋ก ๋๋์ด ๋ชจ๋ธ์ ์ผ๋ฐํ ์ฑ๋ฅ์ ํ๊ฐํ๋ ๋ฐฉ๋ฒ
- ๋ฐ์ดํฐ ํธ์ค์ ๋ง๊ธฐ ์ํด์ ๋ณ๋์ ์ฌ๋ฌ ์ธํธ๋ก ๊ตฌ์ฑ๋ ํ์ต ๋ฐ์ดํฐ ์ธํธ์ ๊ฒ์ฆ ๋ฐ์ดํฐ ์ธํธ์์ ํ์ต๊ณผ ํ๊ฐ๋ฅผ ์ํํ๋ ๊ฒ
- ๊ฐ ์ธํธ์์ ์ํํ ํ๊ฐ ๊ฒฐ๊ณผ์ ๋ฐ๋ผ ํ์ดํผ ํ๋ผ๋ฏธํฐ ํ๋ ๋ฑ์ ๋ชจ๋ธ ์ต์ ํ๋ฅผ ๋์ฑ ์์ฝ๊ฒ ํ ์ ์์
- ๋๋ถ๋ถ์ ML ๋ชจ๋ธ์ ์ฑ๋ฅ ํ๊ฐ๋ ๊ต์ฐจ ๊ฒ์ฆ ๊ธฐ๋ฐ์ผ๋ก 1์ฐจ ํ๊ฐ๋ฅผ ํ ๋ค์ ์ต์ข ์ ์ผ๋ก ํ ์คํธ ๋ฐ์ดํฐ ์ธํธ์ ์ ์ฉํด ํ๊ฐํ๋ ํ๋ก์ธ์ค
a. k ํด๋ ๊ต์ฐจ ๊ฒ์ฆ
k ํด๋ ๊ต์ฐจ ๊ฒ์ฆ (K-Fold Cross-Validation)
k๊ฐ์ ๋ฐ์ดํฐ fold(์กฐ๊ฐ) ์ธํธ๋ฅผ ๋ง๋ค์ด์ k๋ฒ๋งํผ ๊ฐ fold ์ธํธ์ ํ์ต๊ณผ ๊ฒ์ฆ ํ๊ฐ๋ฅผ ๋ฐ๋ณต์ ์ผ๋ก ์ํํ๋ ๋ฐฉ๋ฒ
-
๋ค์ ๊ทธ๋ฆผ์ 5 fold ๊ต์ฐจ ๊ฒ์ฆ ์ํ (k=5)

- 5๊ฐ์ fold๋ ๋ฐ์ดํฐ ์ธํธ๋ฅผ ํ์ต๊ณผ ๊ฒ์ฆ์ ์ํ ๋ฐ์ดํฐ ์ธํธ๋ก ๋ณ๊ฒฝํ๋ฉด์ 5๋ฒ ํ๊ฐ๋ฅผ ์ํํ ๋ค, ์ด 5๊ฐ์ ํ๊ฐ๋ฅผ ํ๊ท ํ ๊ฒฐ๊ณผ๋ฅผ ๊ฐ์ง๊ณ ์์ธก ์ฑ๋ฅ์ ํ๊ฐ
- ์ด๋ ๊ฒ ํ์ต ๋ฐ์ดํฐ ์ธํธ์ ๊ฒ์ฆ ๋ฐ์ดํฐ ์ธํธ๋ฅผ ์ ์ง์ ์ผ๋ก ๋ณ๊ฒฝํ๋ฉด์ ๋ง์ง๋ง 5๋ฒ์งธ(k๋ฒ์งธ)๊น์ง ํ์ต๊ณผ ๊ฒ์ฆ์ ์ํํ๋ ๊ฒ์ด ๋ฐ๋ก k fold ๊ต์ฐจ ๊ฒ์ฆ
-
์ฌ์ดํท๋ฐ์์๋ k fold ๊ต์ฐจ ๊ฒ์ฆ ํ๋ก์ธ์ค๋ฅผ ๊ตฌํํ๊ธฐ ์ํด
KFold์StratifiedKFold๋ฅผ ์ ๊ณต
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score
from sklearn.model_selection import KFold
import numpy as np
iris = load_iris()
features = iris.data
label = iris.target
dt_clf = DecisionTreeClassifier(random_state=156)
# 5๊ฐ์ ํด๋ ์ธํธ๋ก ๋ถ๋ฆฌํ๋ KFold ๊ฐ์ฒด์ ํด๋ ์ธํธ๋ณ ์ ํ๋๋ฅผ ๋ด์ ๋ฆฌ์คํธ ๊ฐ์ฒด ์์ฑ.
kfold = KFold(n_splits=5)
cv_accuracy = []
print('๋ถ๊ฝ ๋ฐ์ดํฐ ์ธํธ ํฌ๊ธฐ:',features.shape[0])
>>> ๋ถ๊ฝ ๋ฐ์ดํฐ ์ธํธ ํฌ๊ธฐ: 150KFold(n_splits=5)๋กKFold๊ฐ์ฒด๋ฅผ ์์ฑํ์ผ๋, ์ด์ ์์ฑ๋KFold๊ฐ์ฒด์split()์ ํธ์ถํด ์ ์ฒด ๋ถ๊ฝ ๋ฐ์ดํฐ๋ฅผ 5๊ฐ์ fold ๋ฐ์ดํฐ ์ธํธ๋ก ๋ถ๋ฆฌ
n_iter = 0
# KFold๊ฐ์ฒด์ split( ) ํธ์ถํ๋ฉด ํด๋ ๋ณ ํ์ต์ฉ, ๊ฒ์ฆ์ฉ ํ
์คํธ์ ๋ก์ฐ ์ธ๋ฑ์ค๋ฅผ array๋ก ๋ฐํ ย
for train_index, test_index ย in kfold.split(features):
ย ย # kfold.split( )์ผ๋ก ๋ฐํ๋ ์ธ๋ฑ์ค๋ฅผ ์ด์ฉํ์ฌ ํ์ต์ฉ, ๊ฒ์ฆ์ฉ ํ
์คํธ ๋ฐ์ดํฐ ์ถ์ถ
ย ย X_train, X_test = features[train_index], features[test_index]
ย ย y_train, y_test = label[train_index], label[test_index]
ย ย #ํ์ต ๋ฐ ์์ธก
ย ย dt_clf.fit(X_train , y_train) ย ย
ย ย pred = dt_clf.predict(X_test)
ย ย n_iter += 1
ย ย # ๋ฐ๋ณต ์ ๋ง๋ค ์ ํ๋ ์ธก์
ย ย accuracy = np.round(accuracy_score(y_test,pred), 4)
ย ย train_size = X_train.shape[0]
ย ย test_size = X_test.shape[0]
ย ย print('\n#{0} ๊ต์ฐจ ๊ฒ์ฆ ์ ํ๋ :{1}, ํ์ต ๋ฐ์ดํฐ ํฌ๊ธฐ: {2}, ๊ฒ์ฆ ๋ฐ์ดํฐ ํฌ๊ธฐ: {3}'
ย ย ย ย ย .format(n_iter, accuracy, train_size, test_size))
ย ย print('#{0} ๊ฒ์ฆ ์ธํธ ์ธ๋ฑ์ค:{1}'.format(n_iter,test_index))
ย ย cv_accuracy.append(accuracy)
# ๊ฐ๋ณ iteration๋ณ ์ ํ๋๋ฅผ ํฉํ์ฌ ํ๊ท ์ ํ๋ ๊ณ์ฐ
print('\n## ํ๊ท ๊ฒ์ฆ ์ ํ๋:', np.mean(cv_accuracy))
- 5๋ฒ ๊ต์ฐจ ๊ฒ์ฆ ๊ฒฐ๊ณผ ํ๊ท ๊ฒ์ฆ ์ ํ๋๋ 0.9์ด๊ณ , ๊ต์ฐจ ๊ฒ์ฆ ์๋ง๋ค ๊ฒ์ฆ ์ธํธ์ ์ธ๋ฑ์ค๊ฐ ๋ฌ๋ผ์ง์ ์ ์ ์์!
b. Stratified K Fold ํด๋์ค
Stratified K Fold
๋ถ๊ท ํํ(imbalanced) ๋ถํฌ๋๋ฅผ ๊ฐ์ง label(๊ฒฐ์ ํด๋์ค) ๋ฐ์ดํฐ ์งํฉ์ ์ํ K fold ๋ฐฉ์
- ๋ถ๊ท ํํ ๋ถํฌ๋๋ฅผ ๊ฐ์ง label ๋ฐ์ดํฐ ์งํฉ์ ํน์ label ๊ฐ์ด ํน์ดํ๊ฒ ๋ง๊ฑฐ๋ ๋งค์ฐ ์ ์ด์ ๊ฐ์ ๋ถํฌ๊ฐ ํ์ชฝ์ผ๋ก ์น์ฐ์น๋ ๊ฒ์ ์๋ฏธ
K Fold๊ฐ label ๋ฐ์ดํฐ ์งํฉ์ด ์๋ณธ ๋ฐ์ดํฐ ์งํฉ์ label ๋ถํฌ๋ฅผ ํ์ต ๋ฐ ํ ์คํธ ์ธํธ์ ์ ๋๋ก ๋ถ๋ฐฐํ์ง ๋ชปํ๋ ๊ฒฝ์ฐ์ ๋ฌธ์ ๋ฅผ ํด๊ฒฐ!
- ์ด๋ฅผ ์ํด ์๋ณธ ๋ฐ์ดํฐ์ label ๋ถํฌ๋ฅผ ๋จผ์ ๊ณ ๋ คํ ๋ค ์ด ๋ถํฌ์ ๋์ผํ๊ฒ ํ์ต๊ณผ ๊ฒ์ฆ ๋ฐ์ดํฐ ์ธํธ๋ฅผ ๋ถ๋ฐฐ
๋์ถ ์ฌ๊ธฐ ๋ฐ์ดํฐ๋ฅผ ์์ธกํ๋ค๊ณ ๊ฐ์ !
- ์ด ๋ฐ์ดํฐ ์ธํธ๋ 1์ต ๊ฑด์ด๊ณ , ์์ญ ๊ฐ์ feature์ ๋์ถ ์ฌ๊ธฐ ์ฌ๋ถ๋ฅผ ๋ปํ๋ label(์ฌ๊ธฐ:1, ์ ์:0)๋ก ๊ตฌ์ฑ๋์ด ์์
- ๊ทธ๋ฐ๋ฐ ๋๋ถ๋ถ์ ๋ฐ์ดํฐ๋ ์ ์ ๋์ถ์ผ ๊ฒ!
- ๋์ถ ์ฌ๊ธฐ๊ฐ ์ฝ 1000๊ฑด์ด ์๋ค๊ณ ํ๋ค๋ฉด ์ ์ฒด์ 0.0001%์ ์์ฃผ ์์ ํ๋ฅ ๋ก ๋์ถ ์ฌ๊ธฐ label์ด ์กด์ฌ
- ์ด๋ ๊ฒ ๋๋ค๋ฉด K Fold๋ก ๋๋คํ๊ฒ ํ์ต ๋ฐ ํ ์คํธ ์ธํธ์ ์ธ๋ฑ์ค๋ฅผ ๊ณ ๋ฅด๋๋ผ๊ณ label ๊ฐ์ธ 0๊ณผ 1์ ๋น์จ์ ์ ๋๋ก ๋ฐ์ํ์ง ๋ชปํ๋ ๊ฒฝ์ฐ๊ฐ ์ฝ๊ฒ ๋ฐ์!
- ๋ฐ๋ผ์ ์๋ณธ ๋ฐ์ดํฐ์ ์ ์ฌํ ๋์ถ ์ฌ๊ธฐ ๋ ์ด๋ธ ๊ฐ์ ๋ถํฌ๋ฅผ ํ์ต/ํ ์คํธ ์ธํธ์๋ ์ ์งํ๋ ๊ฒ ๋งค์ฐ ์ค์!
Note
๋จผ์ K Fold๊ฐ ์ด๋ค ๋ฌธ์ ๋ฅผ ๊ฐ์ง๊ณ ์๋์ง ํ์ธํด ๋ณด๊ณ ์ด๋ฅผ ์ฌ์ดํท๋ฐ์
StratifiedKFoldํด๋์ค๋ฅผ ์ด์ฉํด ๊ฐ์ !
- ๋ถ๊ฝ ๋ฐ์ดํฐ ์ธํธ๋ฅผ ๊ฐ๋จํ๊ฒ DataFrame์ผ๋ก ์์ฑํ๊ณ label ๊ฐ์ ๋ถํฌ๋ ํ์ธ
import pandas as pd
iris = load_iris()
iris_df = pd.DataFrame(data=iris.data, columns=iris.feature_names)
iris_df['label']=iris.target
iris_df['label'].value_counts()
- ๊ฐ ๊ต์ฐจ ๊ฒ์ฆ ์๋ง๋ค ์์ฑ๋๋ ํ์ต/๊ฒ์ฆ label ๋ฐ์ดํฐ ๊ฐ์ ๋ถํฌ๋ ํ์ธ
kfold = KFold(n_splits=3)
# kfold.split(X)๋ ํด๋ ์ธํธ๋ฅผ 3๋ฒ ๋ฐ๋ณตํ ๋๋ง๋ค ๋ฌ๋ผ์ง๋ ํ์ต/ํ
์คํธ ์ฉ ๋ฐ์ดํฐ ๋ก์ฐ ์ธ๋ฑ์ค ๋ฒํธ ๋ฐํ.
n_iter =0
for train_index, test_index ย in kfold.split(iris_df):
ย ย n_iter += 1
ย ย label_train= iris_df['label'].iloc[train_index]
ย ย label_test= iris_df['label'].iloc[test_index]
ย ย print('## ๊ต์ฐจ ๊ฒ์ฆ: {0}'.format(n_iter))
ย ย print('ํ์ต ๋ ์ด๋ธ ๋ฐ์ดํฐ ๋ถํฌ:\n', label_train.value_counts())
ย ย print('๊ฒ์ฆ ๋ ์ด๋ธ ๋ฐ์ดํฐ ๋ถํฌ:\n', label_test.value_counts())
- ๊ต์ฐจ ๊ฒ์ฆ ์๋ง๋ค 3๊ฐ์ fold ์ธํธ๋ก ๋ง๋ค์ด์ง๋ ํ์ต label๊ณผ ๊ฒ์ฆ label์ด ์์ ํ ๋ค๋ฅธ ๊ฐ์ผ๋ก ์ถ์ถ๋จ
- ์ด๋ฐ ์ ํ์ผ๋ก ๊ต์ฐจ ๊ฒ์ฆ ๋ฐ์ดํฐ ์ธํธ๋ฅผ ๋ถํ ํ๋ฉด ๊ฒ์ฆ ์์ธก ์ ํ๋๋ 0์ด ๋ ์๋ฐ์ ์์
- ๋์ผํ ๋ฐ์ดํฐ ๋ถํ ์
StratifiedKFold๋ก ์ํํ๊ณ ํ์ต/๊ฒ์ฆ label ๋ฐ์ดํฐ์ ๋ถํฌ๋ ํ์ธ
StratifiedKFold๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ KFold๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ๊ณผ ๊ฑฐ์ ๋น์ทํ์ง๋ง, ๋จ ํ๋ ํฐ ์ฐจ์ด๋StratifiedKFold๋ label ๋ฐ์ดํฐ ๋ถํฌ๋์ ๋ฐ๋ผ ํ์ต/๊ฒ์ฆ ๋ฐ์ดํฐ๋ฅผ ๋๋๊ธฐ ๋๋ฌธ์split()๋ฉ์๋์ ์ธ์๋ก feature ๋ฐ์ดํฐ ์ธํธ๋ฟ๋ง ์๋๋ผ label ๋ฐ์ดํฐ ์ธํธ๋ ๋ฐ๋์ ํ์!
from sklearn.model_selection import StratifiedKFold
skf = StratifiedKFold(n_splits=3)
n_iter=0
for train_index, test_index in skf.split(iris_df, iris_df['label']):
ย ย n_iter += 1
ย ย label_train= iris_df['label'].iloc[train_index]
ย ย label_test= iris_df['label'].iloc[test_index]
ย ย print('## ๊ต์ฐจ ๊ฒ์ฆ: {0}'.format(n_iter))
ย ย print('ํ์ต ๋ ์ด๋ธ ๋ฐ์ดํฐ ๋ถํฌ:\n', label_train.value_counts())
ย ย print('๊ฒ์ฆ ๋ ์ด๋ธ ๋ฐ์ดํฐ ๋ถํฌ:\n', label_test.value_counts())
- ์ถ๋ ฅ ๊ฒฐ๊ณผ๋ฅผ ๋ณด๋ฉด ํ์ต label๊ณผ ๊ฒ์ฆ label ๋ฐ์ดํฐ ๊ฐ์ ๋ถํฌ๋๊ฐ ๊ฑฐ์ ๋์ผํ๊ฒ ํ ๋น๋์์ ์ ์ ์์
- ์ด๋ ๊ฒ ๋ถํ ์ด ๋์ด์ผ label ๊ฐ 0, 1, 2๋ฅผ ๋ชจ๋ ํ์ตํ ์ ์๊ณ , ์ด์ ๊ธฐ๋ฐํด ๊ฒ์ฆ์ ์ํํ ์ ์์
StratifiedKFold๋ฅผ ์ด์ฉํด ๋ถ๊ฝ ๋ฐ์ดํฐ ๊ต์ฐจ ๊ฒ์ฆ
dt_clf = DecisionTreeClassifier(random_state=156)
skfold = StratifiedKFold(n_splits=3)
n_iter=0
cv_accuracy=[]
# StratifiedKFold์ split( ) ํธ์ถ์ ๋ฐ๋์ ๋ ์ด๋ธ ๋ฐ์ดํฐ ์
๋ ์ถ๊ฐ ์
๋ ฅ ํ์ ย
for train_index, test_index ย in skfold.split(features, label):
ย ย # split( )์ผ๋ก ๋ฐํ๋ ์ธ๋ฑ์ค๋ฅผ ์ด์ฉํ์ฌ ํ์ต์ฉ, ๊ฒ์ฆ์ฉ ํ
์คํธ ๋ฐ์ดํฐ ์ถ์ถ
ย ย X_train, X_test = features[train_index], features[test_index]
ย ย y_train, y_test = label[train_index], label[test_index]
ย ย #ํ์ต ๋ฐ ์์ธก
ย ย dt_clf.fit(X_train, y_train) ย ย
ย ย pred = dt_clf.predict(X_test)
ย ย # ๋ฐ๋ณต ์ ๋ง๋ค ์ ํ๋ ์ธก์
ย ย n_iter += 1
ย ย accuracy = np.round(accuracy_score(y_test,pred), 4)
ย ย train_size = X_train.shape[0]
ย ย test_size = X_test.shape[0]
ย ย print('\n#{0} ๊ต์ฐจ ๊ฒ์ฆ ์ ํ๋ :{1}, ํ์ต ๋ฐ์ดํฐ ํฌ๊ธฐ: {2}, ๊ฒ์ฆ ๋ฐ์ดํฐ ํฌ๊ธฐ: {3}'
ย ย ย ย ย .format(n_iter, accuracy, train_size, test_size))
ย ย print('#{0} ๊ฒ์ฆ ์ธํธ ์ธ๋ฑ์ค:{1}'.format(n_iter,test_index))
ย ย cv_accuracy.append(accuracy)
# ๊ต์ฐจ ๊ฒ์ฆ๋ณ ์ ํ๋ ๋ฐ ํ๊ท ์ ํ๋ ๊ณ์ฐ
print('\n## ๊ต์ฐจ ๊ฒ์ฆ๋ณ ์ ํ๋:', np.round(cv_accuracy, 4))
print('## ํ๊ท ๊ฒ์ฆ ์ ํ๋:', np.round(np.mean(cv_accuracy), 4))
Note
Stratified K Fold์ ๊ฒฝ์ฐ ์๋ณธ ๋ฐ์ดํฐ์ label ๋ถํฌ๋ ํน์ฑ์ ๋ฐ์ํ ํ์ต ๋ฐ ๊ฒ์ฆ ๋ฐ์ดํฐ ์ธํธ๋ฅผ ๋ง๋ค ์ ์์ผ๋ฏ๋ก ์๊ณก๋ label ๋ฐ์ดํฐ ์ธํธ์์๋ ๋ฐ๋์Stratified K Fold๋ฅผ ์ด์ฉํด ๊ต์ฐจ ๊ฒ์ฆํด์ผ ํจ!
c. ๊ต์ฐจ ๊ฒ์ฆ์ ๋ณด๋ค ๊ฐํธํ๊ฒ - cross_val_score()
- ์ฌ์ดํท๋ฐ์ ๊ต์ฐจ ๊ฒ์ฆ์ ์ข ๋ ํธ๋ฆฌํ๊ฒ ์ํํ ์ ์๊ฒ ํด์ฃผ๋ API ์ ๊ณต
KFold๋ก ๋ฐ์ดํฐ๋ฅผ ํ์ตํ๊ณ ์์ธก ํ๋ ์ฝ๋ ์์-
- fold ์ธํธ๋ฅผ ์ค์
-
- for ๋ฃจํ์์ ๋ฐ๋ณต์ผ๋ก ํ์ต ๋ฐ ํ ์คํธ ๋ฐ์ดํฐ์ ์ธ๋ฑ์ค๋ฅผ ์ถ์ถ
-
- ๋ฐ๋ณต์ ์ผ๋ก ํ์ต๊ณผ ์์ธก์ ์ํํ๊ณ ์์ธก ์ฑ๋ฅ ๋ฐํ
-
cross_val_score()๋ ์ด๋ฐ ์ผ๋ จ์ ๊ณผ์ ์ ํ๊บผ๋ฒ์ ์ํํด์ฃผ๋ API
cross_val_score()
cross_val_score(estimator, X, y=None, scoring=None, cv=None, n_jobs=1, verbose=0, fit_params=None, pre_dispatch='2*n_jobs')
- ์ฃผ์ parameter : estimator, X, y, scoring, cv
estimator:Classifierํด๋์ค orRegressorํด๋์ค๋ฅผ ์๋ฏธX: feature ๋ฐ์ดํฐ ์ธํธy: label ๋ฐ์ดํฐ ์ธํธscoring: ์์ธก ์ฑ๋ฅ ํ๊ฐ ์งํcv: ๊ต์ฐจ ๊ฒ์ฆ fold ์
KFold๊ฐ์ฒด๋StratifiedKFold๊ฐ์ฒด๋ฅผ ์ ๋ ฅํ ์๋ ์์- ๋ฐํ ๊ฐ์
scoringํ๋ผ๋ฏธํฐ๋ก ์ง์ ๋ ์ฑ๋ฅ ์งํ ์ธก์ ๊ฐ์ ๋ฐฐ์ด ํํ๋ก ๋ฐํ- ์ฆ,
classifier๊ฐ ์ ๋ ฅ๋๋ฉดStratified K fold๋ฐฉ์์ผ๋ก label ๊ฐ์ ๋ถํฌ์ ๋ฐ๋ผ ํ์ต/ํ ์คํธ ์ธํธ ๋ถํ (ํ๊ท์ธ ๊ฒฝ์ฐ๋Stratified K fold๋ฐฉ์์ผ๋ก ๋ถํ ํ ์ ์์ผ๋ฏ๋กK fold๋ฐฉ์์ผ๋ก ๋ถํ )
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import cross_val_score , cross_validate
from sklearn.datasets import load_iris
iris_data = load_iris()
dt_clf = DecisionTreeClassifier(random_state=156)
data = iris_data.data
label = iris_data.target
# ์ฑ๋ฅ ์งํ๋ ์ ํ๋(accuracy) , ๊ต์ฐจ ๊ฒ์ฆ ์ธํธ๋ 3๊ฐ
scores = cross_val_score(dt_clf , data , label , scoring='accuracy',cv=3)
print('๊ต์ฐจ ๊ฒ์ฆ๋ณ ์ ํ๋:',np.round(scores, 4))
print('ํ๊ท ๊ฒ์ฆ ์ ํ๋:', np.round(np.mean(scores), 4))
>>> ๊ต์ฐจ ๊ฒ์ฆ๋ณ ์ ํ๋: [0.98 0.94 0.98]
ํ๊ท ๊ฒ์ฆ ์ ํ๋: 0.9667cross_val_score()API๋ ๋ด๋ถ์์ Estimator๋ฅผ ํ์ต(fit), ์์ธก(predict), ํ๊ฐ(evaluation)์์ผ์ฃผ๋ฏ๋ก ๊ฐ๋จํ๊ฒ ๊ต์ฐจ ๊ฒ์ฆ์ ์ํํ ์ ์์!- cv ํ๋ผ๋ฏธํฐ์ ์ ์๊ฐ(fold ์)๋ฅผ ์
๋ ฅํ๋ฉด ๋ด๋ถ์ ์ผ๋ก
StratifiedKFold๋ฅผ ์ด์ฉ - ๋น์ทํ API๋ก
cross_validate()์กด์ฌ- ์ฌ๋ฌ ๊ฐ์ ํ๊ฐ ์งํ ๋ฐํ ๊ฐ๋ฅ
- ํ์ต ๋ฐ์ดํฐ์ ๋ํ ์ฑ๋ฅ ํ๊ฐ ์งํ์ ์ํ ์๊ฐ๋ ๊ฐ์ด ์ ๊ณต
3. GridSearchCV - ๊ต์ฐจ ๊ฒ์ฆ๊ณผ ์ต์ ํ์ดํผ ํ๋ผ๋ฏธํฐ ํ๋์ ํ ๋ฒ์
Note
ํ์ดํผ ํ๋ผ๋ฏธํฐ (Hyperparameter)
- ๋ชจ๋ธ์ ํ์ตํ๊ธฐ ์ ์ ์ฌ์ฉ์๊ฐ ์ง์ ์ค์ ํ๋ ๊ฐ์ผ๋ก, ์ด ๊ฐ์ ์กฐ์ ํด ์๊ณ ๋ฆฌ์ฆ์ ์์ธก ์ฑ๋ฅ ๊ฐ์
GridSearchCV
- ์ฌ์ดํท๋ฐ์์ ์ ๊ณตํ๋ ํ์ดํผ ํ๋ผ๋ฏธํฐ ์ต์ ํ API
Classifier๋Regressor์ ๊ฐ์ ์๊ณ ๋ฆฌ์ฆ์ ์ฌ์ฉ๋๋ ํ์ดํผ ํ๋ผ๋ฏธํฐ๋ฅผ ์์ฐจ์ ์ผ๋ก ์ ๋ ฅํ๋ฉด์ ํธ๋ฆฌํ๊ฒ ์ต์ ์ ํ๋ผ๋ฏธํฐ๋ฅผ ๋์ถํ ์ ์๋ ๋ฐฉ์ ์ ๊ณต- Grid๋ ๊ฒฉ์๋ผ๋ ๋ป์ผ๋ก, ์ด์ดํ๊ฒ ํ๋ผ๋ฏธํฐ๋ฅผ ์ ๋ ฅํ๋ฉด์ ํ ์คํธ๋ฅผ ํ๋ ๋ฐฉ์
- ๊ฒฐ์ ํธ๋ฆฌ ์๊ณ ๋ฆฌ์ฆ์ ์ฌ๋ฌ ํ์ดํผ ํ๋ผ๋ฏธํฐ๋ฅผ ์์ฐจ์ ์ผ๋ก ๋ณ๊ฒฝํ๋ฉด์ ์ต๊ณ ์ฑ๋ฅ์ ๊ฐ์ง๋ ํ๋ผ๋ฏธํฐ ์กฐํฉ์ ์ฐพ๊ณ ์ ํ๋ค๋ฉด
- ๋ค์๊ณผ ๊ฐ์ด ํ๋ผ๋ฏธํฐ์ ์งํฉ์ ๋ง๋ค๊ณ ์ด๋ฅผ ์์ฐจ์ ์ผ๋ก ์ ์ฉํ๋ฉด์ ์ต์ ํ ์ํ ๊ฐ๋ฅ
grid_parameters = {'max_depth': [1, 2, 3],
'min_samples_split': [2, 3]}GridSearchCV๋ ๊ต์ฐจ ๊ฒ์ฆ์ ๊ธฐ๋ฐ์ผ๋ก ์ด ํ์ดํผ ํ๋ผ๋ฏธํฐ์ ์ต์ ๊ฐ์ ์ฐพ๊ฒ ํด์ค!-
- ๋ฐ์ดํฐ ์ธํธ๋ฅผ cross-validation์ ์ํ ํ์ต/ํ ์คํธ ์ธํธ๋ก ์๋์ผ๋ก ๋ถํ
-
- ํ์ดํผ ํ๋ผ๋ฏธํฐ grid์ ๊ธฐ์ ๋ ๋ชจ๋ ํ๋ผ๋ฏธํฐ๋ฅผ ์์ฐจ์ ์ผ๋ก ์ ์ฉํด ์ต์ ์ ํ๋ผ๋ฏธํฐ๋ฅผ ์ฐพ์ ์ ์๊ฒ ํด์ค
-
- ๋จ, ๋์์ ์์ฐจ์ ์ผ๋ก ํ๋ผ๋ฏธํฐ๋ฅผ ํ
์คํธํ๋ฏ๋ก ์ํ์๊ฐ์ด ์๋์ ์ผ๋ก ์ค๋ ๊ฑธ๋ฆฌ๋ ๋จ์ ์กด์ฌ!
- ์์ ๊ฒฝ์ฐ CV๊ฐ 3ํ๋ผ๋ฉด CV 3ํ x 6๊ฐ ํ๋ผ๋ฏธํฐ ์กฐํฉ = 18ํ์ ํ์ต/ํ๊ฐ ์ด๋ฃจ์ด์ง
GridSearchCVํด๋์ค
estimator: classifier, regressor, pipeline์ด ์ฌ์ฉ๋ ์ ์์param_grid: key + ๋ฆฌ์คํธ ๊ฐ์ ๊ฐ๋ ๋์ ๋๋ฆฌ๊ฐ ์ฃผ์ด์ง (estimator์ ํ๋์ ์ํด ํ๋ผ๋ฏธํฐ๋ช ๊ณผ ์ฌ์ฉ๋ ์ฌ๋ฌ ํ๋ผ๋ฏธํฐ ๊ฐ ์ง์ )scoring: ์์ธก ์ฑ๋ฅ์ ์ธก์ ํ ํ๊ฐ ๋ฐฉ๋ฒ ์ง์ , ๋ณดํต์ ์ฌ์ดํท๋ฐ์ ์ฑ๋ฅ ํ๊ฐ ์งํ๋ฅผ ์ง์ ํ๋ ๋ฌธ์์ด(ex:โaccuracyโ)๋ก ์ง์ ํ๋ ๋ณ๋์ ์ฑ๋ฅ ํ๊ฐ ์งํ ํจ์๋ ์ง์ ํ ์ ์์cv: ๊ต์ฐจ ๊ฒ์ฆ์ ์ํด ๋ถํ ๋๋ ํ์ต/ํ ์คํธ ์ธํธ์ ๊ฐ์ ์ง์ refit: default=True์ด๋ฉฐ True๋ก ์์ฑ ์ ๊ฐ์ฅ ์ต์ ์ ํ์ดํผ ํ๋ผ๋ฏธํฐ๋ฅผ ์ฐพ์ ๋ค ์ ๋ ฅ๋estimator๊ฐ์ฒด๋ฅผ ํด๋น ํ์ดํผ ํ๋ผ๋ฏธํฐ๋ก ์ฌํ์ต
<์์ > ๊ฒฐ์ ํธ๋ฆฌ ์๊ณ ๋ฆฌ์ฆ์ ์ฌ๋ฌ ๊ฐ์ง ์ต์ ํ ํ๋ผ๋ฏธํฐ๋ฅผ ์์ฐจ์ ์ผ๋ก ์ ์ฉํด ๋ถ๊ฝ ๋ฐ์ดํฐ๋ฅผ ์์ธก ๋ถ์ํ๋ ๋ฐ
GridSearchCV์ด์ฉ
from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import GridSearchCV
# ๋ฐ์ดํฐ๋ฅผ ๋ก๋ฉํ๊ณ ํ์ต๋ฐ์ดํ์ ํ
์คํธ ๋ฐ์ดํฐ ๋ถ๋ฆฌ
iris = load_iris()
X_train, X_test, y_train, y_test = train_test_split(iris_data.data, iris_data.target,
ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย test_size=0.2, random_state=121)
dtree = DecisionTreeClassifier()
### parameter ๋ค์ dictionary ํํ๋ก ์ค์
parameters = {'max_depth':[1,2,3], 'min_samples_split':[2,3]}train_test_split()์ ์ด์ฉํด ํ์ต ๋ฐ์ดํฐ์ ํ ์คํธ ๋ฐ์ดํฐ๋ฅผ ๋จผ์ ๋ถ๋ฆฌ- ํ ์คํธํ ํ์ดํผ ํ๋ผ๋ฏธํฐ๋ค์ dictionary ํํ๋ก ์ค์
import pandas as pd
# param_grid์ ํ์ดํผ ํ๋ผ๋ฏธํฐ๋ค์ 3๊ฐ์ train, test set fold ๋ก ๋๋์ด์ ํ
์คํธ ์ํ ์ค์ . ย
### refit=True ๊ฐ default ์. True์ด๋ฉด ๊ฐ์ฅ ์ข์ ํ๋ผ๋ฏธํฐ ์ค์ ์ผ๋ก ์ฌ ํ์ต ์ํด. ย
grid_dtree = GridSearchCV(dtree, param_grid=parameters, cv=3, refit=True)
# ๋ถ๊ฝ Train ๋ฐ์ดํฐ๋ก param_grid์ ํ์ดํผ ํ๋ผ๋ฏธํฐ๋ค์ ์์ฐจ์ ์ผ๋ก ํ์ต/ํ๊ฐ .
grid_dtree.fit(X_train, y_train)
# GridSearchCV ๊ฒฐ๊ณผ ์ถ์ถํ์ฌ DataFrame์ผ๋ก ๋ณํ
scores_df = pd.DataFrame(grid_dtree.cv_results_)
scores_df[['params', 'mean_test_score', 'rank_test_score',
ย ย ย ย ย ย 'split0_test_score', 'split1_test_score', 'split2_test_score']]- ํ์ต ๋ฐ์ดํฐ ์ธํธ๋ฅผ
GridSearchCV๊ฐ์ฒด์fit()๋ฉ์๋์ ์ธ์๋ก ์ ๋ ฅ - ํ์ต ๋ฐ์ดํฐ๋ฅผ
cv์ ๊ธฐ์ ๋ ํด๋ฉ ์ธํธ๋ก ๋ถํ ํดparam_grid์ ๊ธฐ์ ๋ ํ์ดํผ ํ๋ผ๋ฏธํฐ๋ฅผ ์์ฐจ์ ์ผ๋ก ๋ณ๊ฒฝํ๋ฉด์ ํ์ต/ํ๊ฐ๋ฅผ ์ํํ๊ณ ๊ทธ ๊ฒฐ๊ณผ๋ฅผcv_results_์์ฑ์ ๊ธฐ๋ก
<๊ฒฐ๊ณผ>
params์ปฌ๋ผ์๋ ์ํํ ๋๋ง๋ค ์ ์ฉ๋ ๊ฐ๋ณ ํ์ดํผ ํ๋ผ๋ฏธํฐ๊ฐ์ ๋ํ๋rank_test_score๋ ํ์ดํผ ํ๋ผ๋ฏธํฐ๋ณ๋กd ์ฑ๋ฅ์ด ์ข์ score ์์๋ฅผ ๋ํ๋ (1์ด ๊ฐ์ฅ ๋ฐ์ด๋ ์์์ด๋ฉฐ ์ด๋์ ํ๋ผ๋ฏธํฐ๊ฐ ์ต์ ์ ํ์ดํผ ํ๋ผ๋ฏธํฐ)mean_test_score๋ ๊ฐ๋ณ ํ์ดํผ ํ๋ผ๋ฏธํฐ๋ณ๋ก CV์ ํด๋ฉ ํ ์คํธ ์ธํธ์ ๋ํด ์ด ์ํํ ํ๊ฐ ํ๊ท ๊ฐ
print('GridSearchCV ์ต์ ํ๋ผ๋ฏธํฐ:', grid_dtree.best_params_)
print('GridSearchCV ์ต๊ณ ์ ํ๋: {0:.4f}'.format(grid_dtree.best_score_))
GridSearchCV๊ฐ์ฒด์fit()์ ์ํํ๋ฉด ์ต๊ณ ์ฑ๋ฅ์ ๋ํ๋ธ ํ์ดํผ ํ๋ผ๋ฏธํฐ์ ๊ฐ๊ณผ ๊ทธ๋์ ํ๊ฐ ๊ฒฐ๊ณผ ๊ฐ์ด ๊ฐ๊ฐbest_params_,best_score_์์ฑ์ ๊ธฐ๋ก
# GridSearchCV์ refit์ผ๋ก ์ด๋ฏธ ํ์ต์ด ๋ estimator ๋ฐํ
estimator = grid_dtree.best_estimator_
# GridSearchCV์ best_estimator_๋ ์ด๋ฏธ ์ต์ ํ์ดํผ ํ๋ผ๋ฏธํฐ๋ก ํ์ต์ด ๋จ
pred = estimator.predict(X_test)
print('ํ
์คํธ ๋ฐ์ดํฐ ์ธํธ ์ ํ๋: {0:.4f}'.format(accuracy_score(y_test,pred)))
>>> ํ
์คํธ ๋ฐ์ดํฐ ์ธํธ ์ ํ๋: 0.9667refit=True์ด๋ฉดGridSearchCV๊ฐ ์ต์ ์ฑ๋ฅ์ ๋ํ๋ด๋ ํ์ดํผ ํ๋ผ๋ฏธํฐ๋กEstimator๋ฅผ ๋ค์ ํ์ตํดbest_estimator_๋ก ์ ์ฅrefit=False์ธ ๊ฒฝ์ฐ ์ต์ ์ ๋ชจ๋ธ(best_estimator_)์ ์๋์ผ๋ก ๋ค์ ํ์ตํ์ง ์์!- ์ฆ,
best_estimator_์์ฑ์ด ์กด์ฌํ์ง ์์ผ๋ฉฐ, ์ค์ง ๊ต์ฐจ ๊ฒ์ฆ ๊ฒฐ๊ณผ(cv_results_)๋ง ์ ๊ณต๋จ
- ์ด๋ฏธ ํ์ต๋
best_estimator_๋ฅผ ์ด์ฉํด ํ ์คํธ ๋ฐ์ดํฐ ์ธํธ๋ก ์ ํ๋๋ฅผ ์ธก์ ํ ๊ฒฐ๊ณผ ์ฝ 96.67%์ ๊ฒฐ๊ณผ ๋์ถ
Tip
ํ์ต ๋ฐ์ดํฐ๋ฅผ
GridSearchCV๋ฅผ ์ด์ฉํด ์ต์ ํ์ดํผ ํ๋ผ๋ฏธํฐ ํ๋์ ์ํํ ๋ค์ ๋ณ๋์ ํ ์คํธ ์ธํธ์์ ์ด๋ฅผ ํ๊ฐํ๋ ๊ฒ์ด ์ผ๋ฐ์ ์ธ ๋จธ์ ๋ฌ๋ ๋ชจ๋ธ ์ ์ฉ ๋ฐฉ๋ฒ

