Scikit-Learn 包装器和 RandomizedSearchCV:RuntimeError

Posted

技术标签:

【中文标题】Scikit-Learn 包装器和 RandomizedSearchCV:RuntimeError【英文标题】:Scikit-Learn wrapper and RandomizedSearchCV: RuntimeError 【发布时间】:2021-01-22 07:44:14 【问题描述】:

我在看书

使用 Scikit-Learn、Keras 和 Tensorflow 进行机器学习实践:构建智能系统的概念、工具和技术

在第 11 章(Keras 的 ANN 简介)中解释说,可以在 scikit-learn 中封装一个 tensorflow 模型以使用一些有用的工具,例如 RandomizedSearchCV,这对于ANN超参数的随机搜索(ANN结构、学习率、激活函数等)

但我在随机搜索结束时收到一个奇怪的错误。具体来说,在随机搜索之后,在每个组合的末尾我都会得到:

RuntimeError                              Traceback (most recent call last)
<ipython-input-35-094d1018c18c> in <module>()
     13 rnd_search_cv.fit(X_train, y_train, epochs=100, 
     14                   validation_data=(X_valid, y_valid),
---> 15                   callbacks=[keras.callbacks.EarlyStopping(patience=10)])

1 frames
/usr/local/lib/python3.6/dist-packages/sklearn/model_selection/_search.py in fit(self, X, y, groups, **fit_params)
    734             # of the params are estimators as well.
    735             self.best_estimator_ = clone(clone(base_estimator).set_params(
--> 736                 **self.best_params_))
    737             refit_start_time = time.time()
    738             if y is not None:

/usr/local/lib/python3.6/dist-packages/sklearn/base.py in clone(estimator, safe)
     80             raise RuntimeError('Cannot clone object %s, as the constructor '
     81                                'either does not set or modifies parameter %s' %
---> 82                                (estimator, name))
     83     return new_object
     84 

RuntimeError: Cannot clone object <tensorflow.python.keras.wrappers.scikit_learn.KerasRegressor object at 0x7f16ce468fd0>, as the constructor either does not set or modifies parameter learning_rate

我按照本章的每一步,即:

模型参数化功能

# build model given a set of parameters
input_shape = X_train[0].shape
X_new = X_test[:3]

def build_model(n_hidden=1, n_neurons=30, learning_rate=3e-3):
    model = keras.models.Sequential()
    model.add(keras.layers.InputLayer(input_shape=input_shape))
    for layer in range(n_hidden):
        model.add(keras.layers.Dense(n_neurons, activation="relu"))
    model.add(keras.layers.Dense(1))
    optimizer = keras.optimizers.SGD(lr=learning_rate)
    model.compile(optimizer=optimizer, loss="mse")
    return model

Scikit 模型包装器

keras_reg = keras.wrappers.scikit_learn.KerasRegressor(build_model)

我也测试了模型,效果很好

keras_reg.fit(X_train, y_train, epochs=100, validation_data=(X_valid, y_valid), 
              callbacks=[keras.callbacks.EarlyStopping(patience=10)])
mse_test = keras_reg.score(X_test, y_test)
y_pred = keras_reg.predict(X_new)

但是当我使用 RandomizedSearchCV

# use RandomSearch (or grid search)

from scipy.stats import reciprocal
from sklearn.model_selection import RandomizedSearchCV

param_distribs = 
    "n_hidden": [0, 1, 2, 3],
    "n_neurons": np.arange(1, 100),
    "learning_rate": reciprocal(3e-4, 3e-2)


rnd_search_cv = RandomizedSearchCV(keras_reg, param_distribs, n_iter=10, cv=3)
rnd_search_cv.fit(X_train, y_train, epochs=100, 
                  validation_data=(X_valid, y_valid),
                  callbacks=[keras.callbacks.EarlyStopping(patience=10)])

我得到了上面的RuntimeError

我正在使用 tensorflow 2.3.0 开发 colab

import tensorflow as tf
tf.__version__

2.3.0

有人知道为什么吗?

【问题讨论】:

尝试删除这一行 model.add(tf.keras.layers.InputLayer(input_shape=input_shape)) 【参考方案1】:

我遇到了同样的问题,它似乎是由于没有在 param_distribs 字典中分配可迭代的值(或者至少是 Scikit-Learn 认为可迭代的值)。我发现解决此问题的一种方法是将这些值替换为可迭代的等价物:

param_distribs = 
"n_hidden": [0, 1, 2, 3],
"n_neurons": np.arange(1, 100).tolist(),
"learning_rate": np.arange(3e-4, 3e-2).tolist()

虽然这不能完全重现 Géron 的代码,但它似乎确实有效!

【讨论】:

以上是关于Scikit-Learn 包装器和 RandomizedSearchCV:RuntimeError的主要内容,如果未能解决你的问题,请参考以下文章

装饰器、包装器和适配器模式之间有啥区别?

C++ 库的 JNI 包装器和未定义的符号错误

如何通过 Rest API Python 包装器和 WooCommerce Shipment Tracking 插件插入货运跟踪代码

keras + scikit-learn 包装器,当 GridSearchCV 与 n_jobs >1 时似乎挂起

如何在交叉验证中获得 Keras scikit-learn 包装器的训练和验证损失?

装饰器和迭代器