J'ai le code suivant, en utilisant 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()
Comme indiqué dans le code, il échoue à cette ligne:
pickle.dump(model_tt, open(filename, 'wb'))
Avec cette erreur:
pickle.PicklingError: Can't pickle <function create_model at 0x101c09320>: it's not found as __main__.create_model
Comment puis-je me déplacer?
Edit 1: Réponse originale sur l'enregistrement du modèle
Avec 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')
Edit 2: exemple de code complet avec jeu de données 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])
Veuillez noter que j'ai utilisé Keras uniquement, pas le wrapper. Cela ajoute seulement de la complexité à quelque chose de simple. De plus, le code est volontairement non pris en compte afin que vous puissiez avoir l'image complète.
De plus, vous avez dit que vous vouliez sortir 1 ou 0. Ce n'est pas possible dans cet ensemble de données car vous avez 3 dims et classes de sortie (Iris-setosa, Iris-versicolor, Iris-virginica). Si vous n'aviez que 2 classes, votre sortie dim et les classes seraient 0 ou 1 en utilisant la fonction de sortie sigmoïde.
Ajout juste à la réponse de gaarv - Si vous n'avez pas besoin de la séparation entre la structure du modèle (model.to_json()
) et les poids (model.save_weights()
), vous pouvez utiliser l'une des options suivantes:
keras.models.save_model
et 'keras.models.load_model` qui stockent tout ensemble dans un fichier hdf5.Une autre excellente alternative consiste à utiliser callbacks lorsque vous fit
votre modèle. Plus précisément le rappel ModelCheckpoint
, comme ceci:
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)
Cela permettra d'économiser votre formation chaque époque dans le myModel.h5
fichier. Cela offre de grands avantages, car vous pouvez arrêter votre entraînement lorsque vous le souhaitez (comme lorsque vous voyez qu'il a commencé à sur-équiper), tout en conservant la formation précédente.
Notez que cela enregistre à la fois la structure et les poids dans le même hdf5
(comme l'a montré Zach), vous pouvez donc charger votre modèle à l'aide de keras.models.load_model
.
Si vous souhaitez enregistrer uniquement vos poids séparément, vous pouvez alors utiliser le save_weights_only=True
argument lors de l'instanciation de votre ModelCheckpoint
, vous permettant de charger votre modèle comme expliqué par Gaarv. Extraire des docs :
save_weights_only: si True, seuls les poids du modèle seront enregistrés (model.save_weights (filepath)), sinon le modèle complet est enregistré (model.save (chemin du fichier)).
La réponse acceptée est trop compliquée. Vous pouvez enregistrer et restaurer entièrement chaque aspect de votre modèle dans un .h5
fichier. Directement à partir de la Keras FAQ :
Vous pouvez utiliser model.save (filepath) pour enregistrer un modèle Keras dans un seul fichier HDF5 qui contiendra:
- l'architecture du modèle, permettant de recréer le modèle
- les poids du modèle
- la configuration de la formation (perte, optimiseur)
- l'état de l'optimiseur, permettant de reprendre l'entraînement exactement là où vous vous étiez arrêté.
Vous pouvez ensuite utiliser keras.models.load_model (filepath) pour rétablir votre modèle. load_model se chargera également de compiler le modèle en utilisant la configuration de formation enregistrée (sauf si le modèle n'a jamais été compilé en premier lieu).
Et le code correspondant:
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')