【问题标题】:Tensorflow DNNClassifier and scikit-learn GridSearchCV issuesTensorflow DNNClassifier 和 scikit-learn GridSearchCV 问题
【发布时间】:2017-09-23 23:46:50
【问题描述】:

现在已经有几个小时了,我尝试使用 GridSearchCV 对 tensorflow DNN 模型执行超参数优化。我的代码的最新版本如下:

import random
from tensorflow.contrib.learn.python import learn
from sklearn import datasets
from sklearn.model_selection import GridSearchCV
from sklearn.metrics import accuracy_score

random.seed(42)
iris = datasets.load_iris()
feature_columns = learn.infer_real_valued_columns_from_input(iris.data)
classifier = learn.DNNClassifier(
          feature_columns=feature_columns,
          hidden_units=[10, 20, 10],
          n_classes=3)
grid_search = GridSearchCV(
          classifier, {'hidden_units': [[5, 5], [10, 10]]},
          scoring='accuracy',
          fit_params={'steps': [50]})
grid_search.fit(iris.data, iris.target)
score = accuracy_score(iris.target, grid_search.predict(iris.data))

其实我是从a test in the tensorflow library itself拿的。

当我运行它时,我收到以下错误:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-4-dce950001f99> in <module>()
     16           scoring='accuracy',
     17           fit_params={'steps': [50]})
---> 18 grid_search.fit(iris.data, iris.target)
     19 score = accuracy_score(iris.target, grid_search.predict(iris.data))

/home/nmiotto/Development/upday/hellseher/playground/lib/python3.5/site-packages/sklearn/model_selection/_search.py in fit(self, X, y, groups)
    943             train/test set.
    944         """
--> 945         return self._fit(X, y, groups, ParameterGrid(self.param_grid))
    946 
    947 

/home/nmiotto/Development/upday/hellseher/playground/lib/python3.5/site-packages/sklearn/model_selection/_search.py in _fit(self, X, y, groups, parameter_iterable)
    548                                      n_candidates * n_splits))
    549 
--> 550         base_estimator = clone(self.estimator)
    551         pre_dispatch = self.pre_dispatch
    552 

/home/nmiotto/Development/upday/hellseher/playground/lib/python3.5/site-packages/sklearn/base.py in clone(estimator, safe)
     68     for name, param in six.iteritems(new_object_params):
     69         new_object_params[name] = clone(param, safe=False)
---> 70     new_object = klass(**new_object_params)
     71     params_set = new_object.get_params(deep=False)
     72 

TypeError: __init__() got an unexpected keyword argument 'params'

我正在使用Python 3.5.2 已将所有库更新到最新版本,更准确地说:

$ pip3 freeze
numpy==1.12.1
scikit-learn==0.18.1
scipy==0.19.0
tensorflow==1.1.0

我的想法已经用完了,我无法弄清楚我错过了什么。任何帮助,将不胜感激。 我当然假设我不必在现有库中打补丁或破解任何东西。

【问题讨论】:

    标签: python python-3.x tensorflow scikit-learn


    【解决方案1】:

    此问题来自克隆估算器,如堆栈错误中所述。

    new_object = klass(**new_object_params)
    

    new_object_params 由以下几行返回:

    new_object_params = estimator.get_params(deep=False)
    

    正如您所观察到的,估计器是您的 DNNClassifier,它的克隆被用来做 gridsearchCV。但estimator.get_params(deep=False) 返回以下内容:

    {'params': {'head': <tensorflow.contrib.learn.python.learn.estimators.head._MultiClassHead object at 0x7f720df04490>, 
    'hidden_units': [10, 20, 10], 
    'feature_columns': (_RealValuedColumn(column_name='', dimension=4, default_value=None, dtype=tf.float64, normalizer=None),),
    'embedding_lr_multipliers': None, 'optimizer': None, 'dropout': None,
    'gradient_clip_norm': None, 
    'activation_fn': <function relu at 0x7f7221aa8b18>, 'input_layer_min_slice_size': None}}
    

    如您所见,第一个参数名为params。现在将尝试将其设置为 DNNClassifier 的 init_method 以获取新对象。

    但是在tenserflow 1.1.0版本中,init参数是这样的:

      def __init__(self,
                   hidden_units,
                   feature_columns,
                   model_dir=None,
                   n_classes=2,
                   weight_column_name=None,
                   optimizer=None,
                   activation_fn=nn.relu,
                   dropout=None,
                   gradient_clip_norm=None,
                   enable_centered_bias=False,
                   config=None,
                   feature_engineering_fn=None,
                   embedding_lr_multipliers=None,
                   input_layer_min_slice_size=None,
                   label_keys=None):
    ...
    ...
    

    这里没有名为params 的参数。因此出现错误。

    但是如果你看到 tensorflow 的当前 master 分支的 init() 方法,它是这样的: https://github.com/tensorflow/tensorflow/blob/master/tensorflow/contrib/learn/python/learn/estimators/dnn.py#L327

        super(DNNClassifier, self).__init__(
            model_fn=_dnn_model_fn,
            model_dir=model_dir,
            config=config,
            params={
                "head":
                    head_lib.multi_class_head(
                        n_classes,
                        weight_column_name=weight_column_name,
                        enable_centered_bias=enable_centered_bias,
                        label_keys=label_keys),
                "hidden_units": hidden_units,
                "feature_columns": self._feature_columns,
                "optimizer": optimizer,
                "activation_fn": activation_fn,
                "dropout": dropout,
                "gradient_clip_norm": gradient_clip_norm,
                "embedding_lr_multipliers": embedding_lr_multipliers,
                "input_layer_min_slice_size": input_layer_min_slice_size,
            },
            feature_engineering_fn=feature_engineering_fn)
    

    因此,您在 master 分支中查看的测试可能与此代码更改有关。您可以下载当前分支并自己编译库,以消除此错误。

    否则,在1.1.0版本中搜索如何网格搜索。

    【讨论】:

    • 我尝试了当前的主版本,但仍然没有运气(同样的错误)。此外,该测试似乎并没有真正起作用,它可能不是真正的测试,而更像是他们很久以前编写的用于尝试某些东西的 hacky 脚本,但现在坏了
    • @NicolaMiotto 我没有使用主分支检查它。我会在测试后回复你。同时,您可以使用 ParameterGrid 和 cross_val_score 的组合来达到相同的效果。如果您需要,我可以在此处编辑答案以包含它。
    猜你喜欢
    • 2020-11-22
    • 2018-10-19
    • 2013-10-01
    • 2018-05-14
    • 2014-02-21
    • 2017-12-08
    • 2018-01-27
    相关资源
    最近更新 更多