pythonscikit-learnkeraswrappersummary

keras: returning model.summary() vs scikit learn wrapper


While working with keras, I learned that using a wrapper comes with adverse effects for keras and scikit learn api requests. I am interested in a solution to have both.

Variant 1: scikit Wrapper

from keras.wrappers.scikit_learn import KerasClassifier

    def model():
        model = Sequential()
        model.add(Dense(10, input_dim=4, activation='relu'))
        model.add(Dense(3, activation='softmax'))
        model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
        return model

estimator = KerasClassifier(build_fn=model, epochs=100, batch_size=5)
model.fit(X, y)

-> This lets me print scikit commands such as accuracy_score() or classification_report(). However, model.summary() does not work:

AttributeError: 'KerasClassifier' object has no attribute 'summary'

Variant 2: No Wrapper

model = Sequential()
model.add(Dense(10, input_dim=4, activation='relu'))
model.add(Dense(3, activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
model.fit(X, y, epochs=100, batch_size=5)

-> This lets me print model.summary() but not the scikit commands.

ValueError: Mix type of y not allowed, got types {'multiclass', 'multilabel-indicator'}

Is there a way that enables to use both?


Solution

  • KerasClassifier is just a wrapper over the actual Model in keras so that the actual methods of the keras api can be routed to the methods used in scikit, so it can be used in conjunction with scikit utilities. But internally it just uses the model which can be accessed by using estimator.model.

    Example illustrating the above:

    from keras.models import Sequential
    from keras.layers import Dense
    from keras.wrappers.scikit_learn import KerasClassifier
    from sklearn.datasets import make_classification
    def model():
        model = Sequential()
        model.add(Dense(10, input_dim=20, activation='relu'))
        model.add(Dense(2, activation='softmax'))
        model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
        return model
    
    estimator = KerasClassifier(build_fn=model, epochs=100, batch_size=5)
    X, y = make_classification()
    estimator.fit(X, y)
    
    # This is what you need
    estimator.model.summary()
    

    The output for this is:

    Layer (type)                 Output Shape              Param #   
    =================================================================
    dense_9 (Dense)              (None, 10)                210       
    _________________________________________________________________
    dense_10 (Dense)             (None, 2)                 22        
    =================================================================
    Total params: 232
    Trainable params: 232
    Non-trainable params: 0
    _________________________________________________________________