python - 如何在 scikit-learn 的管道内对转换参数进行网格搜索

标签 python machine-learning scikit-learn pipeline

我的目标是使用一个模型选择最重要的变量,并使用另一个模型使用这些变量进行预测。在下面的示例中,我使用了两个 RandomForestClassifier,但第二个模型可以是任何其他分类器。

RF 有一个带有阈值参数的转换方法。我想对不同的可能阈值参数进行网格搜索。

这是一个简化的代码片段:

# Transform object and classifier
rf_filter = RandomForestClassifier(n_estimators=200, n_jobs=-1, random_state=42, oob_score=False)
clf = RandomForestClassifier(n_jobs=-1, random_state=42, oob_score=False)

pipe = Pipeline([("RFF", rf_filter), ("RF", clf)])

# Grid search parameters
rf_n_estimators = [10, 20]
rff_transform = ["median", "mean"] # Search the threshold parameters

estimator = GridSearchCV(pipe,
                         cv = 3, 
                         param_grid = dict(RF__n_estimators = rf_n_estimators,
                                           RFF__threshold = rff_transform))

estimator.fit(X_train, y_train)

错误是ValueError: Invalid parameter threshold for estimator RandomForestClassifier

我认为这可行,因为 the docs说:

If None and if available, the object attribute threshold is used.

我尝试在网格搜索之前设置阈值属性 (rf_filter.threshold = "median"),它起作用了;但是,我不知道如何对其进行网格搜索。

有没有办法迭代通常预期在分类器的转换方法中提供的不同参数?

最佳答案

按照您所描述的相同方法,即使用分组到管道中的两个不同的随机森林分类器进行特征选择和分类,我遇到了同样的问题。

RandomForestClassifier 类的实例没有名为threshold 的属性。您确实可以手动添加一个,使用您描述的方式或使用

setattr(object, 'threshold', 'mean')

但主要问题似乎是 get_params 方法检查 BaseEstimator 任何成员的有效属性的方式:

class BaseEstimator(object):
"""Base class for all estimators in scikit-learn

Notes
-----
All estimators should specify all the parameters that can be set
at the class level in their __init__ as explicit keyword
arguments (no *args, **kwargs).
"""

@classmethod
def _get_param_names(cls):
    """Get parameter names for the estimator"""
    try:
        # fetch the constructor or the original constructor before
        # deprecation wrapping if any
        init = getattr(cls.__init__, 'deprecated_original', cls.__init__)

        # introspect the constructor arguments to find the model parameters
        # to represent
        args, varargs, kw, default = inspect.getargspec(init)
        if not varargs is None:
            raise RuntimeError("scikit-learn estimators should always "
                               "specify their parameters in the signature"
                               " of their __init__ (no varargs)."
                               " %s doesn't follow this convention."
                               % (cls, ))
        # Remove 'self'
        # XXX: This is going to fail if the init is a staticmethod, but
        # who would do this?
        args.pop(0)
    except TypeError:
        # No explicit __init__
        args = []
    args.sort()
    return args

的确,正如明确规定的那样,所有的估计器都应该指定所有可以设置的参数 在类级别的 __init__ 作为显式关键字参数。

所以我尝试将 threshold 指定为 __init__ 函数中的参数,默认值为“mean”(无论如何这是当前实现中的默认值)

    def __init__(self,
             n_estimators=10,
             criterion="gini",
             max_depth=None,
             min_samples_split=2,
             min_samples_leaf=1,
             max_features="auto",
             bootstrap=True,
             oob_score=False,
             n_jobs=1,
             random_state=None,
             verbose=0,
             min_density=None,
             compute_importances=None,
             threshold="mean"): # ADD THIS!

然后将这个参数的值赋给类的一个参数。

    self.threshold = threshold # ADD THIS LINE SOMEWHERE IN THE FUNCTION __INIT__

当然,这意味着修改 RandomForestClassifier 类(在/python2.7/site-packages/sklearn/ensemble/forest.py 中),这可能不是最好的方法……但它为我工作!我现在能够对不同的阈值参数进行网格搜索(和交叉验证),从而选择不同数量的特征。

关于python - 如何在 scikit-learn 的管道内对转换参数进行网格搜索,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23174964/

相关文章:

python - 不使用<int :pk>构建django详细 View 和 ListView

python - 使用 BeautifulSoup 从多个 svg 帧创建循环 svg 动画

python - DQN Pytorch Loss 不断增加

python - 缩放数据时,为什么训练数据集使用 'fit' 和 'transform' ,而测试数据集只使用 'transform' ?

python - 如何绘制文本 K 均值聚类的结果?

python - 在 C++/Cython 中,是否可以仅声明相关属性在 Python 中可见?

python - 使用python,如何在目录中找到不同的python脚本然后运行它

python - 通过 Python 创建 X 输入矩阵和 y 输出向量

machine-learning - 反向传播,所有输出趋于1

python - 具有缺失值的 SMOTE