第9章使用Scikit-Learn呼叫Keras的模型

優惠券活動發表於2018-06-01

第9章 使用Scikit-Learn呼叫Keras的模型

scikit-learn是最受歡迎的Python機器學習庫。本章我們將使用scikit-learn呼叫Keras生成的模型。本章將:

  • 使用scikit-learn封裝Keras的模型
  • 使用scikit-learn對Keras的模型進行交叉驗證
  • 使用scikit-learn,利用網格搜尋調整Keras模型的超參

我們開始吧。

9.1 簡介

Keras在深度學習很受歡迎,但是隻能做深度學習:Keras是最小化的深度學習庫,目標在於快速搭建深度學習模型。基於SciPy的scikit-learn,數值運算效率很高,適用於普遍的機器學習任務,提供很多機器學習工具,包括但不限於:

  • 使用K折驗證模型
  • 快速搜尋並測試超參

Keras為scikit-learn封裝了KerasClassifierKerasRegressor。本章我們繼續使用第7章的模型。

9.2 使用交叉驗證檢驗深度學習模型

Keras的KerasClassifierKerasRegressor兩個類接受build_fn引數,傳入編譯好的模型。我們加入nb_epoch=150batch_size=10這兩個引數:這兩個引數會傳入模型的fit()方法。我們用scikit-learn的StratifiedKFold類進行10折交叉驗證,測試模型在未知資料的效能,並使用cross_val_score()函式檢測模型,列印結果。

# MLP for Pima Indians Dataset with 10-fold cross validation via sklearn
from keras.models import Sequential
from keras.layers import Dense
from keras.wrappers.scikit_learn import KerasClassifier
from sklearn.cross_validation import StratifiedKFold
from sklearn.cross_validation import cross_val_score
import numpy
import pandas
# Function to create model, required for KerasClassifier
def create_model():
    # create model
    model = Sequential()
    model.add(Dense(12, input_dim=8, init=`uniform`, activation=`relu`)) model.add(Dense(8, init=`uniform`, activation=`relu`)) model.add(Dense(1, init=`uniform`, activation=`sigmoid`))
    # Compile model
    model.compile(loss=`binary_crossentropy`, optimizer=`adam`, metrics=[`accuracy`]) return model
# fix random seed for reproducibility
seed = 7
numpy.random.seed(seed)
# load pima indians dataset
dataset = numpy.loadtxt("pima-indians-diabetes.csv", delimiter=",")
# split into input (X) and output (Y) variables
X = dataset[:,0:8]
Y = dataset[:,8]
# create model
model = KerasClassifier(build_fn=create_model, nb_epoch=150, batch_size=10)
# evaluate using 10-fold cross validation
kfold = StratifiedKFold(y=Y, n_folds=10, shuffle=True, random_state=seed)
results = cross_val_score(model, X, Y, cv=kfold)
print(results.mean())

每輪訓練會輸出一次結果,加上最終的平均效能:

...
Epoch 145/150
692/692 [==============================] - 0s - loss: 0.4671 - acc: 0.7803
Epoch 146/150
692/692 [==============================] - 0s - loss: 0.4661 - acc: 0.7847
Epoch 147/150
692/692 [==============================] - 0s - loss: 0.4581 - acc: 0.7803
Epoch 148/150
692/692 [==============================] - 0s - loss: 0.4657 - acc: 0.7688
Epoch 149/150
692/692 [==============================] - 0s - loss: 0.4660 - acc: 0.7659
Epoch 150/150
692/692 [==============================] - 0s - loss: 0.4574 - acc: 0.7702
76/76 [==============================] - 0s
0.756442244065

比起手工測試,使用scikit-learn容易的多。

9.3 使用網格搜尋調整深度學習模型的引數

使用scikit-learn封裝Keras的模型十分簡單。進一步想:我們可以給fit()方法傳入引數,KerasClassifierbuild_fn方法也可以傳入引數。可以利用這點進一步調整模型。

我們用網格搜尋測試不同引數的效能:create_model()函式可以傳入optimizerinit引數,雖然都有預設值。那麼我們可以用不同的優化演算法和初始權重調整網路。具體說,我們希望搜尋:

  • 優化演算法:搜尋權重的方法
  • 初始權重:初始化不同的網路
  • 訓練次數:對模型訓練的次數
  • 批次大小:每次訓練的資料量

所有的引數組成一個字典,傳入scikit-learn的GridSearchCV類:GridSearchCV會對每組引數(2×3×3×3)進行訓練,進行3折交叉檢驗。

計算量巨大:耗時巨長。如果模型小還可以取一部分資料試試。第7章的模型可以用,因為網路和資料集都不大(1000個資料內,9個引數)。最後scikit-learn會輸出最好的引數和模型,以及平均值。

# MLP for Pima Indians Dataset with grid search via sklearn
from keras.models import Sequential
from keras.layers import Dense
from keras.wrappers.scikit_learn import KerasClassifier
from sklearn.grid_search import GridSearchCV
import numpy
import pandas
# Function to create model, required for KerasClassifier
def create_model(optimizer=`rmsprop`, init=`glorot_uniform`):
    # create model
    model = Sequential()
    model.add(Dense(12, input_dim=8, init=init, activation=`relu`)) model.add(Dense(8, init=init, activation=`relu`)) model.add(Dense(1, init=init, activation=`sigmoid`))
    # Compile model
    model.compile(loss=`binary_crossentropy`, optimizer=optimizer, metrics=[`accuracy`]) return model
# fix random seed for reproducibility
seed = 7
numpy.random.seed(seed)
# load pima indians dataset
dataset = numpy.loadtxt("pima-indians-diabetes.csv", delimiter=",")
# split into input (X) and output (Y) variables
X = dataset[:,0:8]
Y = dataset[:,8]
# create model
model = KerasClassifier(build_fn=create_model)
# grid search epochs, batch size and optimizer
optimizers = [`rmsprop`, `adam`]
init = [`glorot_uniform`, `normal`, `uniform`]
epochs = numpy.array([50, 100, 150])
batches = numpy.array([5, 10, 20])
param_grid = dict(optimizer=optimizers, nb_epoch=epochs, batch_size=batches, init=init) grid = GridSearchCV(estimator=model, param_grid=param_grid)
grid_result = grid.fit(X, Y)
# summarize results
print("Best: %f using %s" % (grid_result.best_score_, grid_result.best_params_))
for params, mean_score, scores in grid_result.grid_scores_:
    print("%f (%f) with: %r" % (scores.mean(), scores.std(), params))

用CPU差不多要5分鐘,結果如下。我們發現使用均勻分佈初始化,rmsprop優化演算法,150輪,批尺寸為5時效果最好,正確率約75%:

Best: 0.751302 using {`init`: `uniform`, `optimizer`: `rmsprop`, `nb_epoch`: 150, `batch_size`: 5}
0.653646 (0.031948) with: {`init`: `glorot_uniform`, `optimizer`: `rmsprop`, `nb_epoch`: 50, `batch_size`: 5}
0.665365 (0.004872) with: {`init`: `glorot_uniform`, `optimizer`: `adam`, `nb_epoch`: 50, `batch_size`: 5}
0.683594 (0.037603) with: {`init`: `glorot_uniform`, `optimizer`: `rmsprop`, `nb_epoch`: 100, `batch_size`: 5}
0.709635 (0.034987) with: {`init`: `glorot_uniform`, `optimizer`: `adam`, `nb_epoch`: 100, `batch_size`: 5}
0.699219 (0.009568) with: {`init`: `glorot_uniform`, `optimizer`: `rmsprop`, `nb_epoch`: 150, `batch_size`: 5}
0.725260 (0.008027) with: {`init`: `glorot_uniform`, `optimizer`: `adam`, `nb_epoch`: 150, `batch_size`: 5}
0.686198 (0.024774) with: {`init`: `normal`, `optimizer`: `rmsprop`, `nb_epoch`: 50, `batch_size`: 5}
0.718750 (0.014616) with: {`init`: `normal`, `optimizer`: `adam`, `nb_epoch`: 50, `batch_size`: 5}
0.725260 (0.028940) with: {`init`: `normal`, `optimizer`: `rmsprop`, `nb_epoch`: 100, `batch_size`: 5}
0.727865 (0.028764) with: {`init`: `normal`, `optimizer`: `adam`, `nb_epoch`: 100, `batch_size`: 5}
0.748698 (0.035849) with: {`init`: `normal`, `optimizer`: `rmsprop`, `nb_epoch`: 150, `batch_size`: 5}
0.712240 (0.039623) with: {`init`: `normal`, `optimizer`: `adam`, `nb_epoch`: 150, `batch_size`: 5}
0.699219 (0.024910) with: {`init`: `uniform`, `optimizer`: `rmsprop`, `nb_epoch`: 50, `batch_size`: 5}
0.703125 (0.011500) with: {`init`: `uniform`, `optimizer`: `adam`, `nb_epoch`: 50, `batch_size`: 5}
0.720052 (0.015073) with: {`init`: `uniform`, `optimizer`: `rmsprop`, `nb_epoch`: 100, `batch_size`: 5}
0.712240 (0.034987) with: {`init`: `uniform`, `optimizer`: `adam`, `nb_epoch`: 100, `batch_size`: 5}
0.751302 (0.031466) with: {`init`: `uniform`, `optimizer`: `rmsprop`, `nb_epoch`: 150, `batch_size`: 5}
0.734375 (0.038273) with: {`init`: `uniform`, `optimizer`: `adam`, `nb_epoch`: 150, `batch_size`: 5}
...

9.4 總結

本章關於使用scikit-learn封裝並測試神經網路的效能。總結一下:

  • 如何使用scikit-learn封裝Keras模型
  • 如何使用scikit-learn測試Keras模型的效能
  • 如何使用scikit-learn調整Keras模型的超參

使用scikit-learn調整引數比手工呼叫Keras簡便的多。


相關文章