Home > OS >  AttributeError: Can't get attribute 'create_model' on <module '__main__'
AttributeError: Can't get attribute 'create_model' on <module '__main__'

Time:05-16

I have created a neural network model and created an ensemble learning model which is the voting model. I have combined a Neural network with random forest,and xgboost. Now I saved the model and try to load it to another Jupiter notebook but I get this error AttributeError: Can't get attribute 'create_model' on <module 'main'>

Here is the code to create the models and it in 1st notebook

from keras.models import Sequential
from keras.layers import Dense
from keras.wrappers.scikit_learn import KerasClassifier
from sklearn.model_selection import StratifiedKFold
from sklearn.model_selection import cross_val_score
import numpy
 
# Function to create model, required for KerasClassifier
def create_model(input_shape=66):
    #x_shape= data_x.shape
    #input_dim=x_shape[1]
    # create model
    model = Sequential()
    model.add(Dense(12, input_dim=66, activation='relu'))
    model.add(Dense(8, activation='relu'))
    model.add(Dense(1,activation='sigmoid'))
# Compile model
    model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
    return model



seed = 7
numpy.random.seed(seed)
Kc_model = KerasClassifier(
                create_model, # Pass in function
                input_shape=66, # Pass in the dimensions to above function
                epochs=100,
                batch_size=32,
                verbose=False)
Kc_model._estimator_type = "classifier"



Kc_model.fit(x_train, y_train, epochs=100,batch_size=10)



rf = RandomForestClassifier(max_depth=15, random_state=0)
rf.fit(x_train,y_train)
rf_y_pred = rf.predict(x_test)

#Model Score
print("The accuracy score for Random Forest Classifier is")
print("Accuracy:{}%".format(round(metrics.accuracy_score(y_test, rf_y_pred)*100)))
print("Training:{}%".format(round(rf.score(x_train, y_train)*100)))
print("Test set: {}%".format(round(rf.score(x_test, y_test)*100)))

xgboost_model = XGBClassifier()
xgboost_model.fit(x_train, y_train)
xgboost_y_pred = xgboost_model.predict(x_test)

print("The accuracy score for Voting XGB Classifier is")
print("Accuracy:{}%".format(round(metrics.accuracy_score(y_test, xgboost_y_pred)*100)))

print("Training:{}%".format(round(xgboost_model.score(x_train, y_train)*100)))
print("Test set: {}%".format(round(xgboost_model.score(x_test, y_test)*100)))


from keras.wrappers.scikit_learn import KerasClassifier
import scikeras
from tensorflow import keras
voting = VotingClassifier(
    estimators = [('rf',rf),('xgboost_model',xgboost_model),('Kc_model',Kc_model) ],
    voting='soft')
#reshaping=y_test.reshape(2712,1)
voting_model =voting.fit(x_train, y_train)
voting_pred = voting_model.predict(x_test)
#Model Score
print("The accuracy score for Voting Classifier is")
print("Training:{}%".format(round(voting_model.score(x_train, y_train)*100)))
print("Test set: {}%".format(round(voting_model.score(x_test, y_test)*100)))

import pickle
# save
with open('voting_model.pkl','wb') as f:
    pickle.dump(Kc_model,f)

In the second notebook that I try to load the model , I get an error as you can see below


import pickle
import pandas as pd
with open('voting_model.pkl', 'rb') as f:
    Kc_model = pickle.load(f)

CodePudding user response:

The reason this happens is that the keras.wrappers.scikit_learn.KerasClassifier wrapper cannot be pickled. The model building function is not saved. Instead, you should pickle the fitted model:

import pickle
# save
with open('voting_model.pkl','wb') as f:
    pickle.dump(Kc_model.model, f)

Now, you can load your model and use it as you wish.

with open('voting_model.pkl', 'rb') as f:
    model = pickle.load(f)

# Predict something.
model.predict(X_test)

However, if you need a KerasClassifier instance after loading then you should re-wrap it. Then, you also need to save the classes_ attribute. Finally, now the build function would return the loaded pickle:

# Save this as well.
with open('voting_model_classes.pkl', 'wb') as f:
    pickle.dump(Kc_model.classes_, f)
import pickle
from keras.wrappers.scikit_learn import KerasClassifier

def load_model():
    with open('voting_model.pkl', 'rb') as f:
        return pickle.load(f)
    
def load_classes():
    with open('voting_model_classes.pkl', 'rb') as f:
        return pickle.load(f)
    
Kc_model = KerasClassifier(
                load_model,
                epochs=100,
                batch_size=32,
                verbose=False)
Kc_model._estimator_type = "classifier"
# We need to manually call it because it will only be called once the classifier is re-fitted.
Kc_model.model = load_model()
Kc_model.classes_ = load_classes()

# Now you can use Kc_model as KerasClassifier.

CodePudding user response:

The error is expected: the model building function gets pickled by name, and that name doesn't exist in your new notebook.

You could try SciKeras which has an initialize method (docs) which you can call to restore stuff like classes_ if you choose to serialize your Keras model using SavedModel directly (SciKeras's KerasClassifier will gladly accept a model instance).

  • Related