GridSearch:必须始终传递“Layer.call”的第一个参数

Posted

技术标签:

【中文标题】GridSearch:必须始终传递“Layer.call”的第一个参数【英文标题】:GridSearch : The first argument to `Layer.call` must always be passed 【发布时间】:2021-07-11 11:04:19 【问题描述】:

我已经构建了一个用于二进制分类的神经网络,并试图通过 GridSearch 找到最佳超参数...但我收到此错误:“必须始终传递 Layer.call 的第一个参数。”我尝试了几个主题的解决方案,但我仍然卡住了。 该错误涉及最后一行grid_result = grid.fit(X,Y)。 我在 colab.research.google 上运行代码

# Function to create the Binary Classification model
def create_BC_model(learning_rate, feature_layer):
    """Create and compile a simple linear regression model."""
    # Most simple tf.keras models are sequential.
    model = tf.keras.models.Sequential()

    # Add the layer containing the feature columns to the model.
    model.add(feature_layer)

    # Topography of the model
    
    model.add(tf.keras.layers.Dense(units=64, 
                                    activation='relu',
                                    name='Hidden1'))
    model.add(tf.keras.layers.Dense(units=32, 
                                    activation='relu', 
                                    name='Hidden2'))

    
    # Output layer.
    model.add(tf.keras.layers.Dense(units=1,
                                    activation=tf.sigmoid,
                                    name='Output'))                              
    
    model.compile(
                optimizer = tf.keras.optimizers.Adam(lr=learning_rate),
                # optimizer = tf.keras.optimizers.RMSprop(lr=my_learning_rate),                                                   
                loss=tf.keras.losses.BinaryCrossentropy(),
                metrics = [tf.keras.metrics.BinaryAccuracy(name='accuracy'),
                            tf.keras.metrics.Precision(name='precision'),
                            tf.keras.metrics.Recall(name="recall")]
                )

    return model

# GridSearch

from sklearn.model_selection import GridSearchCV
import numpy
from sklearn.model_selection import GridSearchCV
from keras.models import Sequential
from keras.layers import Dense
from keras.wrappers.scikit_learn import KerasClassifier

model = KerasClassifier(build_fn=create_BC_model(0.0005,BC_feature_layer), verbose=0)

X = trainBC_df_norm[['0','1','2','3','4','5','6','7','8','9','10','11','12','13','14','15','16','17','18','19','20',
                    '21','21','23','24']]
Y = trainBC_df_norm[['BinVal_Int2e']]

X = X.to_numpy()
Y = Y.to_numpy()

numpy.random.seed(seed)
# Split the dataset into features and label.

    
batch_size = [50, 100, 150, 200]
epochs = [500, 700, 1500]
param_grid = dict(batch_size=batch_size, epochs=epochs)
grid = GridSearchCV(estimator=model, param_grid=param_grid, n_jobs=1, cv=3)
grid_result = grid.fit(X,Y)

完整的错误:

/usr/local/lib/python3.7/dist-packages/sklearn/model_selection/_validation.py:536: FitFailedWarning: Estimator fit failed. The score on this train-test partition for these parameters will be set to nan. Details: 
ValueError: The first argument to `Layer.call` must always be passed.

    FitFailedWarning)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-56-d5109af965ea> in <module>()
        25 param_grid = dict(batch_size=batch_size, epochs=epochs)
        26 grid = GridSearchCV(estimator=model, param_grid=param_grid, n_jobs=1, cv=3)
---> 27 grid_result = grid.fit(X,Y)

4 frames
/usr/local/lib/python3.7/dist-packages/sklearn/model_selection/_search.py in fit(self, X, y, groups, **fit_params)
    737             refit_start_time = time.time()
    738             if y is not None:
--> 739                 self.best_estimator_.fit(X, y, **fit_params)
    740             else:
    741                 self.best_estimator_.fit(X, **fit_params)

/usr/local/lib/python3.7/dist-packages/tensorflow/python/keras/wrappers/scikit_learn.py in fit(self, x, y, **kwargs)
    221       raise ValueError('Invalid shape for y: ' + str(y.shape))
    222     self.n_classes_ = len(self.classes_)
--> 223     return super(KerasClassifier, self).fit(x, y, **kwargs)
    224 
    225   def predict(self, x, **kwargs):

/usr/local/lib/python3.7/dist-packages/tensorflow/python/keras/wrappers/scikit_learn.py in fit(self, x, y, **kwargs)
    153           not isinstance(self.build_fn, types.MethodType)):
    154       self.model = self.build_fn(
--> 155           **self.filter_sk_params(self.build_fn.__call__))
    156     else:
    157       self.model = self.build_fn(**self.filter_sk_params(self.build_fn))

/usr/local/lib/python3.7/dist-packages/tensorflow/python/keras/engine/base_layer.py in __call__(self, *args, **kwargs)
    940     #   not to any other argument.
    941     # - setting the SavedModel saving spec.
--> 942     inputs, args, kwargs = self._split_out_first_arg(args, kwargs)
    943     input_list = nest.flatten(inputs)
    944 

/usr/local/lib/python3.7/dist-packages/tensorflow/python/keras/engine/base_layer.py in _split_out_first_arg(self, args, kwargs)
    3046     else:
    3047       raise ValueError(
-> 3048           'The first argument to `Layer.call` must always be passed.')
    3049     return inputs, args, kwargs
    3050 

ValueError: The first argument to `Layer.call` must always be passed.

【问题讨论】:

BC_feature_layer 是什么?请举一个可重现的例子。 "BC_feature_layer" 是我运行算法的列的名称。 那为什么要在model.add(feature_layer)这里添加列名来建模? 这是输入层 【参考方案1】:

我相信KerasClassifier 要求build_fn 是一个函数,而您正在调用该函数以返回一个模型。您应该将参数放在后面作为关键字参数,如下所示:

model = KerasClassifier(create_BC_model, learning_rate=0.0005, feature_layer=BC_feature_layer, verbose=0)

【讨论】:

以上是关于GridSearch:必须始终传递“Layer.call”的第一个参数的主要内容,如果未能解决你的问题,请参考以下文章

使用 Gridsearch 进行 RFE 排名

NNI GridSearch示例

激活参数在 GridSearch 中不起作用

调参必备---GridSearch网格搜索

带有 SkLearn 管道的 GridSearch 无法正常工作

在管道/gridSearch 中使用 TFI/DF 和 CountVectorizer