web-dev-qa-db-fra.com

Comment passer un paramètre à la fonction de modèle Scikit-Learn Keras

J'ai le code suivant, en utilisant Keras Scikit-Learn Wrapper , qui fonctionne bien:

from keras.models import Sequential
from keras.layers import Dense
from sklearn import datasets
from keras.wrappers.scikit_learn import KerasClassifier
from sklearn.model_selection import StratifiedKFold
from sklearn.model_selection import cross_val_score
import numpy as np


def create_model():
    # create model
    model = Sequential()
    model.add(Dense(12, input_dim=4, 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


def main():
    """
    Description of main
    """


    iris = datasets.load_iris()
    X, y = iris.data, iris.target

    NOF_ROW, NOF_COL =  X.shape

    # 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)
    kfold = StratifiedKFold(n_splits=10, shuffle=True, random_state=seed)
    results = cross_val_score(model, X, y, cv=kfold)

    print(results.mean())
    # 0.666666666667


if __== '__main__':
    main()

Le pima-indians-diabetes.data peut être téléchargéici.

Maintenant, ce que je veux faire est de passer une valeur NOF_COL dans un paramètre de fonction create_model() de la manière suivante

model = KerasClassifier(build_fn=create_model(input_dim=NOF_COL), nb_Epoch=150, batch_size=10, verbose=0)

Avec la fonction create_model() qui ressemble à ceci:

def create_model(input_dim=None):
    # create model
    model = Sequential()
    model.add(Dense(12, input_dim=input_dim, 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

Mais cela échoue en donnant cette erreur:

TypeError: __call__() takes at least 2 arguments (1 given)

Quelle est la bonne façon de le faire?

14
neversaint

Vous pouvez ajouter un input_dim keyarg au constructeur KerasClassifier:

model = KerasClassifier(build_fn=create_model, input_dim=5, nb_Epoch=150, batch_size=10, verbose=0)
12

La dernière réponse ne fonctionne plus.

Une alternative consiste à renvoyer une fonction de create_model, car KerasClassifier build_fn attend une fonction:

def create_model(input_dim=None):
    def model():
        # create model
        nn = Sequential()
        nn.add(Dense(12, input_dim=input_dim, init='uniform', activation='relu'))
        nn.add(Dense(6, init='uniform', activation='relu'))
        nn.add(Dense(1, init='uniform', activation='sigmoid'))
        # Compile model
        nn.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
        return nn

    return model

Ou même mieux, selon documentation

sk_params prend à la fois les paramètres de modèle et les paramètres d'ajustement. Les paramètres de modèle juridique sont les arguments de build_fn. Notez que comme tous les autres estimateurs de scikit-learn, build_fn devrait fournir valeurs par défaut pour ses arguments, afin de pouvoir créer l'estimateur sans transmettre de valeur à sk_params.

Donc, vous pouvez définir votre fonction comme ceci:

def create_model(number_of_features=10): # 10 is the *default value*
    # create model
    nn = Sequential()
    nn.add(Dense(12, input_dim=number_of_features, init='uniform', activation='relu'))
    nn.add(Dense(6, init='uniform', activation='relu'))
    nn.add(Dense(1, init='uniform', activation='sigmoid'))
    # Compile model
    nn.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
    return nn

Et créez un wrapper:

KerasClassifier(build_fn=create_model, number_of_features=20, epochs=25, batch_size=1000, ...)
1
alexandrecosta