2017-04-22 171 views
1

我讀過,你不能與Keras進行交叉驗證,當你也想使用模型回調,但然後this post表明它是可能的。但是,我很難將其融入到我的背景中。Keras回調時運行交叉驗證

爲了更詳細地瞭解這一點,我正在關注machinelearningmastery blog,並使用the iris dataset

這是一個三類分類問題,我試圖使用多層感知器(現在爲測試層)。我現在的目標是在模型回調中工作,以便保存最佳模型的權重。下面,我嘗試在我的部分network_mlp。爲了表明模型沒有回調,我還包括network_mlp_no_callbacks

你應該能夠複製/粘貼到python會話並運行它,沒問題。要複製我看到的錯誤,請取消註釋最後一行。

錯誤:RuntimeError: Cannot clone object <keras.wrappers.scikit_learn.KerasClassifier object at 0x7f7e1c9d2290>, as the constructor does not seem to set parameter callbacks

編碼:第一部分中的數據讀出;其次是具有回調的模型,這是不工作的;第三是沒有回調的模型,它可以工作(提供上下文)。

#!/usr/bin/env python 

import numpy as np 
import pandas, math, sys, keras 
from keras.models import Sequential 
from keras.callbacks import EarlyStopping, ModelCheckpoint 
from keras.layers import Dense 
from keras.wrappers.scikit_learn import KerasClassifier 
from sklearn.preprocessing import MinMaxScaler 
from sklearn.model_selection import cross_val_score 
from sklearn.model_selection import KFold 
from keras.utils import np_utils 
from keras.utils.np_utils import to_categorical 
from sklearn.preprocessing import LabelEncoder 

def read_data_mlp(train_file): 
    train_data = pandas.read_csv("iris.csv", header=None) 
    train_data = train_data.values 
    X = train_data[:,0:4].astype(float) 
    Y = train_data[:,4] 
    X = X.astype('float32') 

    scaler = MinMaxScaler(feature_range=(0, 1)) 

    # encode class values as integers 
    encoder = LabelEncoder() 
    encoder.fit(Y) 
    encoded_Y = encoder.transform(Y) 
    # convert integers to dummy variables (i.e. one hot encoded) 
    dummy_y = np_utils.to_categorical(encoded_Y) 

    X_train_s = scaler.fit_transform(X) 

    return (X_train_s, dummy_y) 

def network_mlp(X, Y, out_dim=10, b_size=30, num_classes=3, epochs=10): 
    #out_dim is the dimensionality of the hidden layer; 
    #b_size is the batch size. There are 150 examples total. 

    filepath="weights_mlp.hdf5" 

    def mlp_model(): 
      model = Sequential() 
      model.add(Dense(out_dim, input_dim=4, activation='relu', kernel_initializer='he_uniform')) 
      model.add(Dense(num_classes, activation='softmax')) 
      model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy']) 
      return model 

    checkpoint = ModelCheckpoint(filepath, monitor='val_acc', verbose=1, save_best_only=True, mode='max') 
    callbacks_list = [checkpoint] 
    estimator = KerasClassifier(build_fn=mlp_model, epochs=epochs, batch_size=b_size, verbose=0, callbacks=callbacks_list) 
    kfold = KFold(n_splits=10, shuffle=True, random_state=7) 
    results = cross_val_score(estimator, X, Y, cv=kfold) 
    print("MLP: %.2f%% (%.2f%%)" % (results.mean()*100, results.std()*100)) 

    return 0 

def network_mlp_no_callbacks(X, Y, out_dim=10, b_size=30, num_classes=3, epochs=10): 

    def mlp_model(): 
      model = Sequential() 
      model.add(Dense(out_dim, input_dim=4, activation='relu', kernel_initializer='he_uniform')) 
      model.add(Dense(num_classes, activation='softmax')) 
      model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy']) 
      return model 

    estimator = KerasClassifier(build_fn=mlp_model, epochs=epochs, batch_size=b_size, verbose=0) 
    kfold = KFold(n_splits=10, shuffle=True, random_state=7) 
    results = cross_val_score(estimator, X, Y, cv=kfold) 
    print("MLP: %.2f%% (%.2f%%)" % (results.mean()*100, results.std()*100)) 

    return 0 

if __name__=='__main__': 

    X, Y = read_data_mlp('iris.csv') 
    network_mlp_no_callbacks(X, Y, out_dim=10, b_size=30, num_classes=3, epochs = 10) 
    #network_mlp(X, Y, out_dim=10, b_size=30, num_classes=3, epochs = 10) 

問題:如何將模型回調合併到KerasClassifier中?

回答

1

該解決方案與您引用的其他答案相當接近,但稍有不同,因爲它們使用多個估算器,而您只有一個。我可以通過將fit_params={'callbacks': callbacks_list}添加到cross_val_score調用中,從estimator初始化中刪除回調列表,並將save_best_only更改爲False,從而使檢查點工作正常。

所以現在的代碼network_mlp小節看起來是這樣的:

checkpoint = ModelCheckpoint(filepath, monitor='val_acc', verbose=1, save_best_only=False, mode='max') 
callbacks_list = [checkpoint] 
estimator = KerasClassifier(build_fn=mlp_model, epochs=epochs, batch_size=b_size, verbose=0) 
kfold = KFold(n_splits=10, shuffle=True, random_state=7) 
results = cross_val_score(estimator, X, Y, cv=kfold, fit_params={'callbacks': callbacks_list}) 

save_best_only=False是必要的,因爲你沒有驗證拆分成立的神經網絡,從而val_acc不可用。如果您想使用驗證子拆分,可以將估算器初始化更改爲:

estimator = KerasClassifier(build_fn=mlp_model, epochs=epochs, batch_size=b_size, verbose=0, validation_split=.25) 

祝您好運!