kerasclassifier gridsearchcv python scikit-learn persistence pickle keras

python - gridsearchcv - kerasclassifier



Cómo guardar el modelo Scikit-Learn-Keras en un archivo de persistencia(pickle/hd5/json/yaml) (4)

Tengo el siguiente código, usando Keras Scikit-Learn Wrapper :

from keras.models import Sequential from sklearn import datasets from keras.layers import Dense from sklearn.model_selection import train_test_split from keras.wrappers.scikit_learn import KerasClassifier from sklearn.model_selection import StratifiedKFold from sklearn.model_selection import cross_val_score from sklearn import preprocessing import pickle import numpy as np import json def classifier(X, y): """ Description of classifier """ NOF_ROW, NOF_COL = X.shape def create_model(): # create model model = Sequential() model.add(Dense(12, input_dim=NOF_COL, init=''uniform'', activation=''relu'')) model.add(Dense(6, 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 # evaluate using 10-fold cross validation seed = 7 np.random.seed(seed) model = KerasClassifier(build_fn=create_model, nb_epoch=150, batch_size=10, verbose=0) return model def main(): """ Description of main """ iris = datasets.load_iris() X, y = iris.data, iris.target X = preprocessing.scale(X) X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.4, random_state=0) model_tt = classifier(X_train, y_train) model_tt.fit(X_train,y_train) #-------------------------------------------------- # This fail #-------------------------------------------------- filename = ''finalized_model.sav'' pickle.dump(model_tt, open(filename, ''wb'')) # load the model from disk loaded_model = pickle.load(open(filename, ''rb'')) result = loaded_model.score(X_test, Y_test) print(result) #-------------------------------------------------- # This also fail #-------------------------------------------------- # from keras.models import load_model # model_tt.save(''test_model.h5'') #-------------------------------------------------- # This works OK #-------------------------------------------------- # print model_tt.score(X_test, y_test) # print model_tt.predict_proba(X_test) # print model_tt.predict(X_test) # Output of predict_proba # 2nd column is the probability that the prediction is 1 # this value is used as final score, which can be used # with other method as comparison # [ [ 0.25311464 0.74688536] # [ 0.84401423 0.15598579] # [ 0.96047372 0.03952631] # ..., # [ 0.25518912 0.74481088] # [ 0.91467732 0.08532269] # [ 0.25473493 0.74526507]] # Output of predict # [[1] # [0] # [0] # ..., # [1] # [0] # [1]] if __name__ == ''__main__'': main()

Como se indica en el código, falla en esta línea:

pickle.dump(model_tt, open(filename, ''wb''))

Con este error:

pickle.PicklingError: Can''t pickle <function create_model at 0x101c09320>: it''s not found as __main__.create_model

¿Cómo puedo evitarlo?


La respuesta aceptada es demasiado complicada. Puede guardar y restaurar completamente todos los aspectos de su modelo en un archivo .h5 . Directamente de las preguntas frecuentes de Keras :

Puede usar model.save (filepath) para guardar un modelo Keras en un solo archivo HDF5 que contendrá:

  • La arquitectura del modelo, permitiendo recrear el modelo.
  • los pesos del modelo
  • La configuración de entrenamiento (pérdida, optimizador).
  • El estado del optimizador, que permite reanudar el entrenamiento exactamente donde lo dejó.

Luego puede usar keras.models.load_model (filepath) para volver a establecer su modelo. load_model también se encargará de compilar el modelo utilizando la configuración de entrenamiento guardada (a menos que el modelo nunca se compiló en primer lugar).

Y el código correspondiente:

from keras.models import load_model model.save(''my_model.h5'') # creates a HDF5 file ''my_model.h5'' del model # deletes the existing model # returns a compiled model # identical to the previous one model = load_model(''my_model.h5'')


Otra excelente alternativa es utilizar callbacks cuando se fit su modelo. Específicamente la ModelCheckpoint llamada ModelCheckpoint , como esta:

from keras.callbacks import ModelCheckpoint #Create instance of ModelCheckpoint chk = ModelCheckpoint("myModel.h5", monitor=''val_loss'', save_best_only=False) #add that callback to the list of callbacks to pass callbacks_list = [chk] #create your model model_tt = KerasClassifier(build_fn=create_model, nb_epoch=150, batch_size=10) #fit your model with your data. Pass the callback(s) here model_tt.fit(X_train,y_train, callbacks=callbacks_list)

Esto guardará su entrenamiento cada época en el archivo myModel.h5 . Esto proporciona grandes beneficios, ya que puede detener su entrenamiento cuando lo desee (como cuando ve que ha comenzado a adaptarse en exceso), y aún retener el entrenamiento anterior.

Tenga en cuenta que esto guarda la estructura y los pesos en el mismo archivo hdf5 (como lo mostró Zach), por lo que puede cargar su modelo utilizando keras.models.load_model .

Si desea guardar solo sus pesos por separado, puede usar el argumento save_weights_only=True al crear una instancia de su ModelCheckpoint , lo que le permite cargar su modelo como lo explica Gaarv. Extraer de la callbacks :

save_weights_only: si es Verdadero, solo se guardarán los pesos del modelo (model.save_weights (filepath)), de lo contrario se guardará el modelo completo (model.save (filepath)).


Solo agregando a la respuesta de gaarv: si no necesita la separación entre la estructura del modelo ( model.to_json() ) y los pesos ( model.save_weights() ), puede usar uno de los siguientes:

  • Use los keras.models.save_model y ''keras.models.load_model` que almacenan todo junto en un archivo hdf5.
  • Use pickle para serializar el objeto Modelo (o cualquier clase que contenga referencias a él) en el archivo / red / lo que sea ..
    Desafortunadamente, Keras no admite pickles por defecto. Puedes usar mi solución parcheada que agrega esta característica faltante. El código de trabajo está aquí: http://zachmoshe.com/2017/04/03/pickling-keras-models.html

Edición 1 : Respuesta original sobre guardar modelo.

Con HDF5:

# saving model json_model = model_tt.model.to_json() open(''model_architecture.json'', ''w'').write(json_model) # saving weights model_tt.model.save_weights(''model_weights.h5'', overwrite=True) # loading model from keras.models import model_from_json model = model_from_json(open(''model_architecture.json'').read()) model.load_weights(''model_weights.h5'') # dont forget to compile your model model.compile(loss=''binary_crossentropy'', optimizer=''adam'')

Edición 2 : ejemplo de código completo con dataset de iris

# Train model and make predictions import numpy import pandas from keras.models import Sequential, model_from_json from keras.layers import Dense from keras.utils import np_utils from sklearn import datasets from sklearn import preprocessing from sklearn.model_selection import train_test_split from sklearn.preprocessing import LabelEncoder # fix random seed for reproducibility seed = 7 numpy.random.seed(seed) # load dataset iris = datasets.load_iris() X, Y, labels = iris.data, iris.target, iris.target_names X = preprocessing.scale(X) # 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) y = np_utils.to_categorical(encoded_Y) def build_model(): # create model model = Sequential() model.add(Dense(4, input_dim=4, init=''normal'', activation=''relu'')) model.add(Dense(3, init=''normal'', activation=''sigmoid'')) model.compile(loss=''categorical_crossentropy'', optimizer=''adam'', metrics=[''accuracy'']) return model def save_model(model): # saving model json_model = model.to_json() open(''model_architecture.json'', ''w'').write(json_model) # saving weights model.save_weights(''model_weights.h5'', overwrite=True) def load_model(): # loading model model = model_from_json(open(''model_architecture.json'').read()) model.load_weights(''model_weights.h5'') model.compile(loss=''categorical_crossentropy'', optimizer=''adam'') return model X_train, X_test, Y_train, Y_test = train_test_split(X, y, test_size=0.3, random_state=seed) # build model = build_model() model.fit(X_train, Y_train, nb_epoch=200, batch_size=5, verbose=0) # save save_model(model) # load model = load_model() # predictions predictions = model.predict_classes(X_test, verbose=0) print(predictions) # reverse encoding for pred in predictions: print(labels[pred])

Tenga en cuenta que solo usé Keras, no el envoltorio. Solo agrega algo de complejidad en algo simple. Además, el código es voluntario, no factorizado, por lo que puede tener la imagen completa.

Además, dijo que desea generar 1 o 0. No es posible en este conjunto de datos porque tiene 3 dims y clases de salida (Iris-setosa, Iris-versicolor, Iris-virginica). Si solo tuviera 2 clases, su salida dim y las clases serían 0 o 1 usando la función de salida sigmoidea.