Keras with GridSearchCV로 매개변수 최적화 자동화

Keras에서 GridSearchCV를 시도했습니다.



기계 학습의 모델 정확도는 파라미터에 따라 달라집니다.
모델 구축시에 활성화 함수나 최적화 알고리즘, 중간층의 유닛수 등 다수의 파라미터를 설정합니다만, 그 때 설정한 파라미터가 최적인 것인가는, 트레이닝해 실용해 볼 때까지 모릅니다.

그러나 기계 학습의 매력은 자동으로 최적의 모델이 생성된다는 것입니다.
그렇다면, 파라미터도 자동적으로 최적화되어도 좋지 않을까! 라고 생각하는 것입니다.

Python의 기계 학습으로 유명한 scikit-learn에는 Gridsearchcv라는 모델 선택과 파라미터 튜닝까지 가능한 라이브러리가 있습니다.

사실 Keras는 scikit-learn을 래퍼하고 있으며 Gridsearchcv를 Keras의 모델 구축시에 사용할 수 있습니다.

그렇다면 Keras의 Gridsearchcv를 빠르게 해보자.

목표



Keras에서 Gridsearchcv를 사용하여 최적의 모델을 만듭니다.
데이터는 모두 대인기의 아야메(Iris) 데이터를 사용해, 품종 분류를 실시합니다.

코딩



즉시 써 봅시다.

먼저 필요한 것을 가져옵니다.
Iris 데이터는 sklearn에서 제공하는 것을 사용합니다.
import numpy as np
from sklearn import datasets, preprocessing
from sklearn.model_selection import train_test_split
from sklearn.model_selection import GridSearchCV
from keras.models import Sequential
from keras.layers.core import Dense, Activation
from keras.utils import np_utils
from keras import backend as K
from keras.wrappers.scikit_learn import KerasClassifier


Iris 데이터를 7:3으로 교육 및 테스트로 나눕니다.
iris = datasets.load_iris()
x = preprocessing.scale(iris.data)
y = np_utils.to_categorical(iris.target)
x_tr, x_te, y_tr, y_te = train_test_split(x, y, train_size  = 0.7)
num_classes = y_te.shape[1]


함수로서 신경망 모델을 정의합니다.
여기서 레이어 수를 정의하고 인수에 매개 변수를 제공합니다.
def iris_model(activation="relu", optimizer="adam", out_dim=100):
    model = Sequential()
    model.add(Dense(out_dim, input_dim=4, activation=activation))
    model.add(Dense(out_dim, activation=activation))
    model.add(Dense(num_classes, activation="softmax"))
    model.compile(loss='categorical_crossentropy', optimizer=optimizer, metrics=['accuracy'])
    return model


각 매개변수에 대한 선택사항을 정의합니다.
Gridsearchcv는 여기에 정의한 모든 매개변수 패턴을 검증합니다.
activation = ["relu", "sigmoid"]
optimizer = ["adam", "adagrad"]
out_dim = [100, 200]
nb_epoch = [10, 25]
batch_size = [5, 10]


모델 함수와 매개변수를 Gridsearchcv로 로드합니다.
KerasClassifier에서 모델을 읽고 dict에 매개 변수를 설정합니다.
GridSearchCV에서 양자를 결합하는 구조입니다.
model = KerasClassifier(build_fn=iris_model, verbose=0)
param_grid = dict(activation=activation, 
                  optimizer=optimizer, 
                  out_dim=out_dim, 
                  nb_epoch=nb_epoch, 
                  batch_size=batch_size)
grid = GridSearchCV(estimator=model, param_grid=param_grid)


훈련 시작!
grid_result = grid.fit(x_tr, y_tr)


・・・기다리는 30분・・・
···Iris 데이터의 분류라고는 말해, CPU라고 시간이 걸립니다. ···
... GPGPU라면 더 빨라질까? ···
・・・・・・・・・
···
···GPU 원한다···
・・・・・・・・・
・・・・・・・・・
···
···완료! ···

결과를 출력합니다.
최고의 점수와 그 매개 변수입니다.
print (grid_result.best_score_)
print (grid_result.best_params_)




95%··· 뭐 그렇네요.

이제 먼저 남겨둔 테스트 데이터로 모델을 검증해 봅시다.
덧붙여서 Keras를 gridsearchcv 해 버리면 model.evaluate 할 수없는 것 같습니다.
그래서 테스트 데이터의 정답과 추측치를 아날로그와 비교하고 있습니다.
grid_eval = grid.predict(x_te)
def y_binary(i):
    if   i == 0: return [1, 0, 0]
    elif i == 1: return [0, 1, 0]
    elif i == 2: return [0, 0, 1]
y_eval = np.array([y_binary(i) for i in grid_eval])
accuracy = (y_eval == y_te)
print (np.count_nonzero(accuracy == True) / (accuracy.shape[0] * accuracy.shape[1]))



98%!
아주 좋은 느낌입니다.

모델은 이런 느낌이 되고 있습니다.
model = iris_model(activation=grid_result.best_params_['activation'], 
                   optimizer=grid_result.best_params_['optimizer'], 
                   out_dim=grid_result.best_params_['out_dim'])
model.summary()




어때?
Iris 데이터는 특이치가 많고 최선을 다해 100%가 되지 않습니다.
트레이닝을 파라미터의 조합만 돌리기 때문에 시간은 걸립니다만, 파라미터를 수작업으로 탐색하는 것보다는 편하네요.

이하, 코드 전문입니다.
import numpy as np
from sklearn import datasets, preprocessing
from sklearn.model_selection import train_test_split
from sklearn.model_selection import GridSearchCV
from keras.models import Sequential
from keras.layers.core import Dense, Activation
from keras.utils import np_utils
from keras import backend as K
from keras.wrappers.scikit_learn import KerasClassifier


# import data and divided it into training and test purposes
iris = datasets.load_iris()
x = preprocessing.scale(iris.data)
y = np_utils.to_categorical(iris.target)
x_tr, x_te, y_tr, y_te = train_test_split(x, y, train_size  = 0.7)
num_classes = y_te.shape[1]


# Define model for iris classification
def iris_model(activation="relu", optimizer="adam", out_dim=100):
    model = Sequential()
    model.add(Dense(out_dim, input_dim=4, activation=activation))
    model.add(Dense(out_dim, activation=activation))   
    model.add(Dense(num_classes, activation="softmax"))
    model.compile(loss='categorical_crossentropy', optimizer=optimizer, metrics=['accuracy'])
    return model

# Define options for parameters
activation = ["relu", "sigmoid"]
optimizer = ["adam", "adagrad"]
out_dim = [100, 200]
nb_epoch = [10, 25]
batch_size = [5, 10]


# Retrieve model and parameter into GridSearchCV
model = KerasClassifier(build_fn=iris_model, verbose=0)
param_grid = dict(activation=activation, 
                  optimizer=optimizer, 
                  out_dim=out_dim, 
                  nb_epoch=nb_epoch, 
                  batch_size=batch_size)
grid = GridSearchCV(estimator=model, param_grid=param_grid)


# Run grid search
grid_result = grid.fit(x_tr, y_tr)


# Get the best score and the optimized mode
print (grid_result.best_score_)
print (grid_result.best_params_)

# Evaluate the model with test data
grid_eval = grid.predict(x_te)
def y_binary(i):
    if   i == 0: return [1, 0, 0]
    elif i == 1: return [0, 1, 0]
    elif i == 2: return [0, 0, 1]
y_eval = np.array([y_binary(i) for i in grid_eval])
accuracy = (y_eval == y_te)
print (np.count_nonzero(accuracy == True) / (accuracy.shape[0] * accuracy.shape[1]))


# Now see the optimized model
model = iris_model(activation=grid_result.best_params_['activation'], 
                   optimizer=grid_result.best_params_['optimizer'], 
                   out_dim=grid_result.best_params_['out_dim'])
model.summary()

좋은 웹페이지 즐겨찾기