Search code examples
tensorflowkerasscikit-learncross-validation

I can't execute cross_val_score with scikeras.wrappers.KerasRegressor


from tensorflow import keras
from sklearn.model_selection import cross_val_score
from sklearn.datasets import make_regression
from scikeras.wrappers import KerasRegressor
X, y = make_regression(n_samples=10_000)
input_shape = X.shape[1]
model = keras.Sequential([
    keras.layers.Dense(100, activation='relu', input_dim=input_shape),
    keras.layers.Dense(200, activation='relu'),
    keras.layers.Dense(200, activation='relu'),
    keras.layers.Dense(1, activation='linear')])
model.compile(keras.optimizers.Adam(), loss='mse')

model = KerasRegressor(model, batch_size=256, verbose=1, epochs=10)

val_score = cross_val_score(model, X, y, cv=5)
plt.plot(val_score)

when I run the attached code normally it should work but for some reason it displays this error :

----------------------------------------------------------------------------------------------

Empty Traceback (most recent call last) /usr/local/lib/python3.8/dist-packages/joblib/parallel.py in dispatch_one_batch(self, iterator) 861 try: --> 862 tasks = self._ready_batches.get(block=False) 863 except queue.Empty:

13 frames Empty:

During handling of the above exception, another exception occurred:

AttributeError Traceback (most recent call last) /usr/local/lib/python3.8/dist-packages/keras/optimizers/optimizer_v2/optimizer_v2.py in _getattribute_(self, name) 864 """Overridden to support hyperparameter access.""" 865 try: --> 866 return super(OptimizerV2, self)._getattribute_(name) 867 except AttributeError as e: 868 # Needed to avoid infinite recursion with _setattr_.

AttributeError: 'Adam' object has no attribute 'build'


Solution

  • (TensorFlow 2.11) Make sure you're doing:

    from tensorflow import keras
    

    There is a difference between import keras and from tensorflow import keras:

    >>> import keras
    >>> keras.optimizers.Adam.build
    AttributeError: type object 'Adam' has no attribute 'build'
    
    >>> from tensorflow import keras
    >>> keras.optimizers.Adam.build
    <function Adam.build at 0x7f1ff29e7b50>
    

    (TensorFlow 2.9)

    Boilerplate wrapping in a get_model function appears to resolve this:

    from tensorflow import keras
    from sklearn.model_selection import cross_val_score
    from sklearn.datasets import make_regression
    from scikeras.wrappers import KerasRegressor
    X, y = make_regression(n_samples=10_000)
    
    def get_model(meta):
      X_shape_ = meta["X_shape_"]
      model = keras.Sequential()
      model.add(keras.layers.Dense(100, activation='relu', input_shape=X_shape_[1:]))
      model.add(keras.layers.Dense(200, activation='relu'))
      model.add(keras.layers.Dense(200, activation='relu'))
      model.add(keras.layers.Dense(1, activation='linear'))
      return model
    
    model = KerasRegressor(model=get_model, loss="mse", batch_size=256, verbose=1, epochs=10)
    
    cross_val_score(model, X, y, cv=5)