# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 2
#     language: python
#     name: python2
# ---

# + [markdown] school_cell_uuid="1b23c3307c5c4698b86a0c930c85433c"
# # 모형 하이퍼 파라미터 튜닝

# + [markdown] school_cell_uuid="a37f8ea91a44484498e6daf6a38b760e"
# 머신 러닝 모형이 완성된 후에는 성능을 향상시키기 위한 하이퍼 파라미터 최적화 등의 모형 최적화 과정을 통해 예측 성능을 향상시킨다.

# + [markdown] school_cell_uuid="373f26192e304fe384bd20a41c9f854e"
# ## Scikit-Learn 의 모형 하이퍼 파라미터 튜닝 도구

# + [markdown] school_cell_uuid="e3911c3d1450449293d632b230ca4352"
# Scikit-Learn에서는 다음과 같은 모형 최적화 도구를 지원한다.
#
# * [`validation_curve`](http://scikit-learn.org/stable/modules/generated/sklearn.learning_curve.validation_curve.html)
#   * 단일 하이퍼 파라미터 최적화
# * [`GridSearchCV`](http://scikit-learn.org/stable/modules/generated/sklearn.grid_search.GridSearchCV.html)
#   * 그리드를 사용한 복수 하이퍼 파라미터 최적화
# * [`ParameterGrid`](http://scikit-learn.org/stable/modules/generated/sklearn.grid_search.ParameterGrid.html)  
#  * 복수 파라미터 최적화용 그리드
#

# + [markdown] school_cell_uuid="d1aaa13a1e5f44bf944456592ee0cf54"
# ## `validation_curve` 사용 예 

# + [markdown] school_cell_uuid="a21cfa574b054d6caed1fbfe38fd1280"
# `validation_curve` 함수는 최적화할 파라미터 이름과 범위, 그리고 성능 기준을 `param_name`, `param_range`, `scoring` 인수로 받아 파라미터 범위의 모든 경우에 대해 성능 기준을 계산한다.

# + school_cell_uuid="00aab77c1b8c4f9db19a3c968c50b05a"
from sklearn.datasets import load_digits
from sklearn.svm import SVC
from sklearn.learning_curve import validation_curve

digits = load_digits()
X, y = digits.data, digits.target

param_range = np.logspace(-6, -1, 10)

# + school_cell_uuid="84643397187446979f4c4c810fd4f03f"
# %%time
train_scores, test_scores = \
    validation_curve(SVC(), X, y, 
                     param_name="gamma", param_range=param_range,
                     cv=10, scoring="accuracy", n_jobs=1)

# + school_cell_uuid="3dd91079782c4125a1d7b92ee5761fb4"
train_scores_mean = np.mean(train_scores, axis=1)
train_scores_std = np.std(train_scores, axis=1)
test_scores_mean = np.mean(test_scores, axis=1)
test_scores_std = np.std(test_scores, axis=1)

plt.title("Validation Curve with SVM")
plt.xlabel("$\gamma$")
plt.ylabel("Score")
plt.ylim(0.0, 1.1)
plt.semilogx(param_range, train_scores_mean, label="Training score", color="r")
plt.fill_between(param_range, train_scores_mean - train_scores_std,
                 train_scores_mean + train_scores_std, alpha=0.2, color="r")
plt.semilogx(param_range, test_scores_mean, label="Cross-validation score", color="g")
plt.fill_between(param_range, test_scores_mean - test_scores_std,
                 test_scores_mean + test_scores_std, alpha=0.2, color="g")
plt.legend(loc="best")
plt.show()

# + [markdown] school_cell_uuid="700b3f8cb09b4dfd8e8adfcf332baa4e"
# ## `GridSearchCV` 사용예

# + [markdown] school_cell_uuid="8c933c8e35424d7aabfbe7120117771b"
# `GridSearchCV`  클래스는 `validation_curve` 함수와 달리 모형 래퍼(Wrapper) 성격의 클래스이다.  클래스 객체에 `fit` 메서드를 호출하면 grid search를 사용하여 자동으로 복수개의 내부 모형을 생성하고 이를 모두 실행시켜서 최적 파라미터를 찾아준다. 생성된 복수개와 내부 모형과 실행 결과는 다음 속성에 저장된다.
#
# * `grid_scores_ `
#  * param_grid 의 모든 파리미터 조합에 대한 성능 결과. 각각의 원소는 다음 요소로 이루어진 튜플이다.
#   * parameters: 사용된 파라미터
#   * mean_validation_score: 교차 검증(cross-validation) 결과의 평균값
#   * cv_validation_scores: 모든 교차 검증(cross-validation) 결과
# * `best_score_` 
#  * 최고 점수 
# * `best_params_`
#  * 최고 점수를 낸 파라미터
# * `best_estimator_`
#  * 최고 점수를 낸 파라미터를 가진 모형

# + school_cell_uuid="2b2dde7edf34472c816d7e463aaec718"
from sklearn.grid_search import GridSearchCV
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC

pipe_svc = Pipeline([('scl', StandardScaler()), ('clf', SVC(random_state=1))])

param_range = [0.0001, 0.001, 0.01, 0.1, 1.0, 10.0, 100.0, 1000.0]
param_grid = [
    {'clf__C': param_range, 'clf__kernel': ['linear']},
    {'clf__C': param_range, 'clf__gamma': param_range, 'clf__kernel': ['rbf']}]

gs = GridSearchCV(estimator=pipe_svc, param_grid=param_grid, scoring='accuracy', cv=10, n_jobs=1)
# %time gs = gs.fit(X, y)

# + school_cell_uuid="a962063a593d436aa4f662b0844100ef"
print(gs.best_score_)
print(gs.best_params_)

# + school_cell_uuid="bb402a52eb0c46528e3877485bcc4fee"
gs.grid_scores_

# + [markdown] school_cell_uuid="b2d7c60bbb2640d2950667c5aa7652d0"
# ## `ParameterGrid` 사용예

# + [markdown] school_cell_uuid="e309a8580715444a9136eed33e850c54"
# 때로는 scikit-learn 이 제공하는 GridSearchCV 이외의 방법으로 그리드 탐색을 해야하는 경우도 있다. 이 경우 파라미터를 조합하여 탐색 그리드를 생성해 주는 명령어가 `ParameterGrid` 이다. `ParameterGrid` 는 탐색을 위한 iterator 역할을 한다.

# + school_cell_uuid="e19d25d2ec2c4cfba41b54c417278d58"
from sklearn.grid_search import ParameterGrid

# + school_cell_uuid="a0cbec4b337f488bb1aa7c572fe70d43"
param_grid = {'a': [1, 2], 'b': [True, False]}
list(ParameterGrid(param_grid))

# + school_cell_uuid="29c941318d43480dab325091261398fe"
param_grid = [{'kernel': ['linear']}, {'kernel': ['rbf'], 'gamma': [1, 10]}]
list(ParameterGrid(param_grid))

StarcoderdataJupyterScriptsDedupFiltered