์ด๋ฒ ์ธ์ ์์๋ ๋ ๊ฐ์ง ๊ณก์ ์ ์ด์ฉํด ์๊ณ ๋ฆฌ์ฆ์ ๋๋ฒ๊น ํ์ฌ ๋ณด๋ค ๋์ ๋ชจ๋ธ์ ๋ง๋๋ ๋ฐฉ๋ฒ ํ๋์, ๊ทธ๋ฆฌ๋ ์์น๋ฅผ ์ด์ฉํด ํ์ดํผํ๋ผ๋ฏธํฐ๋ฅผ ํ๋ํ๋ ๋ฐฉ๋ฒ ๋ ๊ฐ์ง๋ฅผ ์ดํด๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค. ์ง๋ ์ธ์ ๊ณผ ์ด๋์ ๋ ์ด์ด์ง๋ ์ฃผ์ ์ด๋, 16์ ๋ณด๊ณ ์ค์ ๋ ์ข์ต๋๋ค!
A. ํ์ต ๊ณก์ ๊ณผ ๊ฒ์ฆ ๊ณก์ ์ ์ฌ์ฉํ ์๊ณ ๋ฆฌ์ฆ ๋๋ฒ๊น
1. ํ์ต ๊ณก์ ์ผ๋ก ํธํฅ๊ณผ ๋ถ์ฐ ๋ฌธ์ ๋ถ์
ํ์ต ๊ณก์ , ์ฆ ๊ทธ๋ํ๋ฅผ ์ด์ฉํ๋ฉด ๋ชจ๋ธ์ ํ๋ จ ์ ํ๋์ ๊ฒ์ฆ ์ ํ๋๋ฅผ ๋ชจ๋ธ์ ๋์ ๋ถ์ฐ์ ๋ฌธ์ ๊ฐ ์๋์ง, ํธํฅ์ ๋ฌธ์ ๊ฐ ์๋์ง๋ฅผ ์ฝ๊ฒ ํ์ธํ๊ณ ๊ณ ์น ์ ์์ต๋๋ค. ๋ฐ์ดํฐ๋ฅผ ๋ ๋ชจ์ผ๋ ๊ฒ์ ์ฌ์ค ๋ถ๊ฐ๋ฅํ ๊ฒฝ์ฐ๊ฐ ๊ฝค ์๊ธฐ ๋๋ฌธ์, ๊ผญ ๋ฐ์ดํฐ๋ฅผ ๋ ๋ชจ์์ผํ๋์ง๋ฅผ ํ๋จํ ์ ์๊ฒ ํด์ฃผ์ฃ .
์ผ์ชฝ ์ ๊ทธ๋ํ๋ ํธํฅ์ด ๋์ ๋ชจ๋ธ์ ๋๋ค. ์ด ๋ชจ๋ธ์ ํ๋ จ๊ณผ ๊ต์ฐจ๊ฒ์ฆ์ ์ ํ๋๊ฐ ๋ค ๋ฎ์ผ๋ฏ๋ก, ์ธ๋ํผํ ๋์์์ ์ ์ ์์ต๋๋ค. ์ด ๊ฒฝ์ฐ์๋ ๋ชจ๋ธ์ ํ๋ผ๋ฏธํฐ ๊ฐ์๋ฅผ ๋๋ฆฌ๋ ๊ฒ์ด ์ข์ต๋๋ค. ํน์ฑ์ ๋ ์์งํ๊ฑฐ๋ SVM, ๋ก์ง์คํฑ ํ๊ท ๋ถ๋ฅ๊ธฐ์ ๊ท์ ๊ฐ๋๋ฅผ ์ค์ผ ์ ์์ฃ .
์ค๋ฅธ์ชฝ ์ ๊ทธ๋ํ๋ ๋ถ์ฐ์ด ๋์ ๋ชจ๋ธ์ ๋๋ค. ํ๋ จ ์ ํ๋์ ๊ต์ฐจ ๊ฒ์ฆ ์ ํ๋ ์ฌ์ด์ ์ฐจ์ด๊ฐ ์์์ ํ์ธํ ์ ์์ฃ ? ์ด ๊ฒฝ์ฐ๋ ๊ณผ๋์ ํฉ, ์ค๋ฒํผํ ์ ๋๋ค. ์ด ๊ฒฝ์ฐ์๋ ๋ ๋ง์ ํ๋ จ ๋ฐ์ดํฐ๋ฅผ ๋ชจ์ผ๊ฑฐ๋ ๊ท์ ๋ฅผ ๊ฐํํจ์ผ๋ก์จ ํด๊ฒฐํ ์ ์์ต๋๋ค. ๊ท์ ๊ฐ ์๋ ๋ชจ๋ธ์์๋ ํน์ฑ ์ ํ์ด๋ ์ถ์ถ์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
์ด์ ์ฌ์ดํท๋ฐ์ ํ์ต ๊ณก์ ํจ์๋ฅผ ์ฌ์ฉํด๋ณผ๊น์?
import matplotlib.pyplot as plt
from sklearn.model_selection import learning_curve
pipe_lr = make_pipeline(StandardScaler(),
LogisticRegression(solver='liblinear',
penalty='l2',
random_state=1))
train_sizes, train_scores, test_scores =\
learning_curve(estimator=pipe_lr,
X=X_train,
y=y_train,
train_sizes=np.linspace(0.1, 1.0, 10),
cv=10,
n_jobs=1)
train_mean = np.mean(train_scores, axis=1)
train_std = np.std(train_scores, axis=1)
test_mean = np.mean(test_scores, axis=1)
test_std = np.std(test_scores, axis=1)
plt.plot(train_sizes, train_mean,
color='blue', marker='o',
markersize=5, label='training accuracy')
plt.fill_between(train_sizes,
train_mean + train_std,
train_mean - train_std,
alpha=0.15, color='blue')
plt.plot(train_sizes, test_mean,
color='green', linestyle='--',
marker='s', markersize=5,
label='validation accuracy')
plt.fill_between(train_sizes,
test_mean + test_std,
test_mean - test_std,
alpha=0.15, color='green')
plt.grid()
plt.xlabel('Number of training samples')
plt.ylabel('Accuracy')
plt.legend(loc='lower right')
plt.ylim([0.8, 1.03])
plt.tight_layout()
plt.show()
learning_curveํจ์์ train_sizes ๋งค๊ฐ๋ณ์๋ฅผ ์ด์ฉํ๋ฉด ํ์ต๊ณก์ ์์ฑ์ ํ์ํ ํ๋ จ ์ํ์ ๊ฐ์์ ๋น์จ์ ์ง์ ํ ์ ์์ต๋๋ค. ์ฌ๊ธฐ์๋ ์ผ์ ๊ฐ๊ฒฉ์ผ๋ก ํ๋ จ ์ธํธ์ ๋น์จ 10๊ฐ๋ฅผ ์ค์ ํด์ฃผ์์ต๋๋ค.
learning_curveํจ์๋ ๊ณ์ธต๋ณ k-๊ฒน ๊ต์ฐจ ๊ฒ์ฆ์ ํตํด ๊ต์ฐจ ๊ฒ์ฆ ์ ํ๋๋ฅผ ๊ณ์ฐํด์ค๋๋ค. ์ฌ๊ธฐ์ k=10์ ๋๋ค.
์ด ๊ทธ๋ํ์์ ๋ณผ ์ ์๋ฏ 250๊ฐ ์ด์์ ์ํ์ ์ฌ์ฉํ ๋ ๋ชจ๋ธ์ด ์ ์๋ํ๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค. ์ด๊ฒ๋ณด๋ค ์ ์ผ๋ฉด ๋ ๋ง์ด ์ค๋ฒํผํ ๋๋ค๋ ์ฆ๊ฑฐ์ด์ฃ .
2. ๊ฒ์ฆ ๊ณก์ ์ผ๋ก ๊ณผ๋์ ํฉ๊ณผ ๊ณผ์์ ํฉ ์กฐ์ฌ
๊ฒ์ฆ ๊ณก์ ์ ๋ชจ๋ธ ์ฑ๋ฅ์ ๋์ผ ์ ์๋ ๋๊ตฌ์ ๋๋ค. ๋ชจ๋ธ ํ๋ผ๋ฏธํฐ ๊ฐ์ ํจ์๋ก ๊ทธ๋ ค์ฃผ์ฃ . ๋ก์ง์คํฑ ํ๊ท์ ๊ฒฝ์ฐ์๋ ๊ท์ ๋ฅผ ๋ํ๋ด๋ ๋งค๊ฐ๋ณ์ C๊ฐ ๋ฉ๋๋ค. ์ฌ์ดํท๋ฐ์ผ๋ก ๊ทธ๋ฆฌ๋ ๋ฐฉ๋ฒ์ ์์๋ณผ๊น์?
param_range = [0.001, 0.01, 0.1, 1.0, 10.0, 100.0]
train_scores, test_scores = validation_curve(
estimator=pipe_lr,
X=X_train,
y=y_train,
param_name='logisticregression__C',
param_range=param_range,
cv=10)
train_mean = np.mean(train_scores, axis=1)
train_std = np.std(train_scores, axis=1)
test_mean = np.mean(test_scores, axis=1)
test_std = np.std(test_scores, axis=1)
plt.plot(param_range, train_mean,
color='blue', marker='o',
markersize=5, label='training accuracy')
plt.fill_between(param_range, train_mean + train_std,
train_mean - train_std, alpha=0.15,
color='blue')
plt.plot(param_range, test_mean,
color='green', linestyle='--',
marker='s', markersize=5,
label='validation accuracy')
plt.fill_between(param_range,
test_mean + test_std,
test_mean - test_std,
alpha=0.15, color='green')
plt.grid()
plt.xscale('log')
plt.legend(loc='lower right')
plt.xlabel('Parameter C')
plt.ylabel('Accuracy')
plt.ylim([0.8, 1.00])
plt.tight_layout()
plt.show()
learning_curve ํจ์์ ๋น์ทํ๊ฒ validation_curve ํจ์๋ ๊ธฐ๋ณธ ์ธํ ์ด ๊ณ์ธต๋ณ k-๊ฒน ๊ต์ฐจ ๊ฒ์ฆ์ ํตํด ๋ชจ๋ธ์ ์ฑ๋ฅ์ ์ถ์ ํ๋๋ก ๋์ด์์ต๋๋ค. ์ด ํจ์์์ ํ๊ฐํ๊ธธ ์ํ๋ ๋ณ์๋ฅผ ์ง์ ์ ํด์ค๋๋ค. ์ด ๊ฒฝ์ฐ์๋ ๋ก์ง์คํฑ ํ๊ท์ C์ด์ฃ .
param_range์์๋ ์ด๋ฆ์ฒ๋ผ ๊ฐ ๋ฒ์๋ฅผ ์ง์ ํด์ค๋๋ค. ํ์ต๊ณก์ ์์๋ ์ด์ ์ฒ๋ผ ํ๋ จ ์ ํ๋์ ๊ต์ฐจ ๊ฒ์ฆ ์ ํ๋, ํ์ค ํธ์ฐจ๋ฅผ ๋ํ๋ด์ฃผ์์ต๋๋ค.
C์ ๋ฐ๋ผ ์ ํ๋ ์ฐจ์ด๊ฐ ๋ฏธ๋ฌํ์ง๋ง ๊ท์ ๊ฐ๋๋ฅผ ๋์ฌ C๋ฅผ ์ค์ด๋ฉด ์กฐ๊ธ ๊ณผ์์ ํฉ๋๊ณ , ๊ท์ ๊ฐ๋๋ฅผ ๋ฎ์ถฐ C๋ฅผ ๋๋ฆฌ๋ฉด ์กฐ๊ธ ๊ณผ๋์ ํฉ๋จ์ ํ์ธํ ์ ์์ต๋๋ค.
B. ๊ทธ๋ฆฌ๋ ์์น๋ฅผ ์ฌ์ฉํ ๋จธ์ ๋ฌ๋ ๋ชจ๋ธ ์ธ๋ถ ํ๋
1. ๊ทธ๋ฆฌ๋ ์์น๋ฅผ ์ฌ์ฉํ ํ์ดํผ ํ๋ผ๋ฏธํฐ ํ๋
๊ทธ๋ฆฌ๋ ์์น๋ ์ธ๊ธฐ์๋ ํ์ดํผ ํ๋ผ๋ฏธํฐ ์ต์ ํ ๋ฐฉ๋ฒ์ ๋๋ค. ๊ทธ๋ฆฌ๋ ์์น๊ฐ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ์ฌ๋ฌ๊ฐ์ง ํ์ดํผ ํ๋ผ๋ฏธํฐ ๊ฐ์ ์ ๋ถ ์กฐ์ฌํ๊ณ , ์ด ๊ฐ์ ๋ชจ๋ ์กฐํฉ์ ๋ฐ๋ผ ์ฑ๋ฅ์ ํ๊ฐํด์ ์ต์ ์ ์กฐํฉ์ ์ฐพ์ต๋๋ค. ์ฝ๋๋ก ๋ณด์ค๊น์?
from sklearn.model_selection import GridSearchCV
from sklearn.svm import SVC
pipe_svc = make_pipeline(StandardScaler(),
SVC(random_state=1))
param_range = [0.0001, 0.001, 0.01, 0.1, 1.0, 10.0, 100.0, 1000.0]
param_grid = [{'svc__C': param_range,
'svc__kernel': ['linear']},
{'svc__C': param_range,
'svc__gamma': param_range,
'svc__kernel': ['rbf']}]
gs = GridSearchCV(estimator=pipe_svc,
param_grid=param_grid,
scoring='accuracy',
cv=10,
n_jobs=-1)
gs = gs.fit(X_train, y_train)
print(gs.best_score_)
print(gs.best_params_)
์ด ์ฝ๋์์๋ GridSearchCV ํด๋์ค์ ๊ฐ์ฒด๋ฅผ ๋ง๋ค๊ณ SVM์ ์ํด ํ์ดํ๋ผ์ธ์ ํ๋ จํ๊ณ ํ๋ํด์ค๋๋ค. ๊ทธ๋ฆฌ๊ณ param_grid์ ํ๋ํ๋ ค๋ ๋งค๊ฐ๋ณ์๋ฅผ ์ง์ ํด์ค๋๋ค. RBF ์ปค๋ SVM์์๋ svc__C์ svc__gamma ๋งค๊ฐ๋ณ์๋ฅผ ํ๋ํด์ค๋๋ค.
๊ทธ๋ฆฌ๋ ์์น๋ฅผ ์ํํ ํ ์ต๊ณ ์ ์๋ best_score_ ์์ฑ์์ ์ป์ ์ ์์ผ๋ฉฐ, ์ด ๋ชจ๋ธ์ ๋งค๊ฐ๋ณ์๋ best_params_ ์์ฑ์์ ํ์ธ ๊ฐ๋ฅํฉ๋๋ค.
๋ง์ง๋ง์ผ๋ก ํ ์คํธ ์ธํธ๋ฅผ ์ฌ์ฉํด ์ฑ๋ฅ์ ์ถ์ ํด์ค๋๋ค. ์ด ๋ชจ๋ธ์ best_estimator_์์ ์ป์ ์ ์์ต๋๋ค.
clf = gs.best_estimator_
clf.fit(X_train, y_train)
print('ํ
์คํธ ์ ํ๋: %.3f' % clf.score(X_test, y_test))
2. ์ค์ฒฉ ๊ต์ฐจ ๊ฒ์ฆ์ ์ฌ์ฉํ ์๊ณ ๋ฆฌ์ฆ ์ ํ
๊ทธ๋ฆฌ๋ ์์น์ k-๊ฒน ๊ต์ฐจ ๊ฒ์ฆ์ ํจ๊ป ์ฌ์ฉํ๋ฉด ๋จธ์ ๋ฌ๋ ๋ชจ๋ธ์ ์ฑ๋ฅ์ ์ธ๋ถ์ ์ผ๋ก ์กฐ์ ํ๊ธฐ ์ฝ์ต๋๋ค. ๊ทธ๋ฌ๋ ๊ฐ์ ๊ฒ์ด ์๋ ์ฌ๋ฌ ์ข ๋ฅ์ ์๊ณ ๋ฆฌ์ฆ์ ๋น๊ตํ๋ ค๋ฉด ์ค์ฒฉ ๊ต์ฐจ ๊ฒ์ฆ(nested cross-validation)์ ์ถ์ฒํฉ๋๋ค.
์ค์ฒฉ ๊ต์ฐจ ๊ฒ์ฆ์ k-๊ฒน ๊ต์ฐจ ๊ฒ์ฆ ๋ฃจํ์ ๋ฐ๊นฅ์ชฝ ๋ถ๋ถ์ด ํ๋ จ๊ณผ ๋ฐ์ดํฐ ํด๋๋ก ๋ฐ์ดํฐ๋ฅผ ๋๋๊ณ , ์์ชฝ ๋ฃจํ์์ k-๊ฒน ๊ต์ฐจ ๊ฒ์ฆ์ ์ํํด ๋ชจ๋ธ์ ์ ํํฉ๋๋ค. ๋ชจ๋ธ์ ์ ํํ๋ฉด ํ ์คํธ ํด๋๋ก ํ๊ฐํด์ค๋๋ค. ์ผ๋จ ๊ทธ๋ฆผ์ ๋ณผ๊น์?
์ด ๊ทธ๋ฆผ์ ๊ฒฝ์ฐ์๋ ๋ฐ๊นฅ ๋ฃจํ์๋ ๋ค์ฏ ๊ฐ ํด๋๋ฅผ, ์์ชฝ ๋ฃจํ์๋ ๋ ๊ฐ ํด๋๋ฅผ ์ฌ์ฉํ๋ ๊ฐ๋ ์ ๋ณด์ฌ์ค๋๋ค. ์ด ๋ฐฉ์์ ๋์ฉ๋ ๋ฐ์ดํฐ์ ์์ ์ ์ฉํ๋ฉฐ, ์ด ๊ฒฝ์ฐ์๋ 5x2 ๊ต์ฐจ ๊ฒ์ฆ์ด๋ผ๊ณ ๋ ํฉ๋๋ค.
์ฌ์ดํท๋ฐ์์๋ ์๋์ ๊ฐ์ต๋๋ค.
gs = GridSearchCV(estimator=pipe_svc,
param_grid=param_grid,
scoring='accuracy',
cv=2)
scores = cross_val_score(gs, X_train, y_train,
scoring='accuracy', cv=5)
print('CV ์ ํ๋: %.3f +/- %.3f' % (np.mean(scores),
np.std(scores)))
๋ฐํ๋ ํ๊ท ๊ต์ฐจ ๊ฒ์ฆ ์ ์๋ ๋ชจ๋ธ์ ํ๋ํ์ ๋ ์๋ก์ด ๋ฐ์ดํฐ์์ ๊ธฐ๋ํ ์ ์๋ ์ ํ๋๋ผ๊ณ ํ ์ ์์ต๋๋ค.
์ค์ฒฉ ๊ต์ฐจ ๊ฒ์ฆ์ ์๋ก, ์๊ณ ๋ฆฌ์ฆ์ ๋น๊ต๋ฅผ ์ํด ์ฌ์ฉํ๋ฉด SVM๊ณผ ๋จ์ผ ๊ฒฐ์ ํธ๋ฆฌ ๋ถ๋ฅ๊ธฐ๋ฅผ ๋น๊ตํ ์ ์์ต๋๋ค.
from sklearn.tree import DecisionTreeClassifier
gs = GridSearchCV(estimator=DecisionTreeClassifier(random_state=0),
param_grid=[{'max_depth': [1, 2, 3, 4, 5, 6, 7, None]}],
scoring='accuracy',
cv=2)
scores = cross_val_score(gs, X_train, y_train,
scoring='accuracy', cv=5)
print('CV ์ ํ๋: %.3f +/- %.3f' % (np.mean(scores),
np.std(scores)))
๊ฒฐ๊ณผ์์ ํ์ธ ๊ฐ๋ฅ ํ๋ฏ์ด SVM ๋ชจ๋ธ์ ๊ฒ์ฆ ์ฑ๋ฅ์ ๊ฒฐ์ ํธ๋ฆฌ์ ์ฑ๋ฅ๋ณด๋ค ๋ ๋ฐ์ด๋ฉ๋๋ค. ์ด๋ ๋ฏ ์ค์ฒฉ ๊ต์ฐจ ๊ฒ์ฆ์ ํตํด ๋ ๋์ ์๊ณ ๋ฆฌ์ฆ์ ์ ํํ ์ ์์ต๋๋ค!
์, ์ฌ๊ธฐ๊น์ง ๋ชจ๋ธ์ ๋ ์ข๊ฒ ๋ง๋ค๊ธฐ ์ํด์ ์ด๋ค ๋ถ๋ถ์ ๋ฐ๊พธ๊ณ ์ถ๊ฐํด์ผํ๋์ง, ๋ ์ด๋ค ์๊ณ ๋ฆฌ์ฆ์ด ๋ ์ ํฉํ์ง๋ฅผ ์ฝ๊ฒ ํ์ธํ ์ ์๋๋ก ๋์์ฃผ๋ ๋๊ตฌ๋ค์ ์ดํด๋ณด์์ต๋๋ค. ์ธ์ 16๋ถํฐ 18๊น์ง๋ ์ญ ๋ชจ๋ธ์ ํ๊ฐํ๊ฑฐ๋ ํ์ดํผํ๋ผ๋ฏธํฐ๋ฅผ ํ๋ํ๋ ๋ฐฉ๋ฒ์ ์ค๋ช ํด์ฃผ๊ณ ์์ผ๋ ์๋ก ๋ค๋ฅธ ๋ฐฉ๋ฒ์ ์๊ฐํ๊ณ ์์ผ๋ ์ฐ๋ฌ์ ์ฝ์ ํ์๋ ์์ต๋๋ค! ํ์ง๋ง ๊ฐ์ด ์์๋๋ฉด ์ข๊ฒ ์ฃ ?
๋ค์ ์ธ์ ์์๋ ์ฑ๋ฅ ํ๊ฐ์ ๋ค์ํ ์งํ๋ค๊ณผ, ํด๋์ค์ ์๋ ์ํ์ด ๋ถ๊ท ํํ ๊ฒฝ์ฐ์ ์ด๋ป๊ฒ ๋ฐ์ดํฐ๋ฅผ ๋ค๋ฃจ์ด์ผํ๋์ง์ ๋ํด์ ์ด์ผ๊ธฐํ๋๋ก ํ๊ฒ ์ต๋๋ค. ์๊ณ ํ์ จ์ต๋๋ค!