如何向Scikit-Learn Keras模型函数传递参数

25

我有下面这段代码,使用Keras Scikit-Learn Wrapper,它运行良好:

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 __name__ == '__main__':
    main()

可以在此处下载 pima-indians-diabetes.data

现在我想要的是将值NOF_COL传递到create_model()函数的参数中,方法如下:

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

使用以下形式的create_model()函数:

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

但是它会失败并显示以下错误:

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

怎么才是正确的方式?

3个回答

22
您可以在KerasClassifier构造函数中添加一个input_dim关键字参数:
model = KerasClassifier(build_fn=create_model, input_dim=5, nb_epoch=150, batch_size=10, verbose=0)

10

上一个答案已经不再适用。

另一种方法是从create_model中返回一个函数,因为KerasClassifier的build_fn需要一个函数:

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

甚至更好的是,根据文档,sk_params可以同时接受模型参数和拟合参数。合法的模型参数是build_fn的参数。请注意,与scikit-learn中的所有其他估计器一样,build_fn应为其参数提供默认值,以便您可以创建估计器而不传递任何值到sk_params。

因此,您可以像这样定义函数:

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

并创建一个包装器:

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

1
将参数传递给 build_fn 模型,可以通过将参数传递给 __init__() 并将其直接传递给 model_build_fn 来完成。例如,调用 KerasClassifier(myparam=10) 将导致 model_build_fn(my_param=10)。
以下是示例:
class MyMultiOutputKerasRegressor(KerasRegressor):
    
    # initializing
    def __init__(self, **kwargs):
        KerasRegressor.__init__(self, **kwargs)
        
    # simpler fit method
    def fit(self, X, y, **kwargs):
        KerasRegressor.fit(self, X, [y]*3, **kwargs)

(...)

def get_quantile_reg_rpf_nn(layers_shape=[50,100,200,100,50], inDim= 4, outDim=1, act='relu'):
          # do model stuff...

初始化Keras回归器:
base_model = MyMultiOutputKerasRegressor(build_fn=get_quantile_reg_rpf_nn,
                                         layers_shape=[50,100,200,100,50], inDim= 4, 
                                         outDim=1, act='relu', epochs=numEpochs, 
                                         batch_size=batch_size, verbose=0)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接