【问题标题】:How to pass a parameter to only one part of a pipeline object in scikit learn?如何将参数仅传递给 scikit learn 中管道对象的一部分?
【发布时间】:2016-06-08 13:00:41
【问题描述】:

我需要将参数sample_weight 传递给我的RandomForestClassifier,如下所示:

X = np.array([[2.0, 2.0, 1.0, 0.0, 1.0, 3.0, 3.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0,
        1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 5.0, 3.0,
        2.0, '0'],
       [15.0, 2.0, 5.0, 5.0, 0.466666666667, 4.0, 3.0, 2.0, 0.0, 0.0, 0.0,
        0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0,
        7.0, 14.0, 2.0, '0'],
       [3.0, 4.0, 3.0, 1.0, 1.33333333333, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0,
        0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0,
        9.0, 8.0, 2.0, '0'],
       [3.0, 2.0, 3.0, 0.0, 0.666666666667, 2.0, 2.0, 1.0, 0.0, 0.0, 0.0,
        0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0,
        5.0, 3.0, 1.0, '0']], dtype=object)

y = np.array([ 0.,  0.,  1.,  0.])

m = sklearn.ensemble.RandomForestClassifier(
        random_state=0, 
        oob_score=True, 
        n_estimators=100,
        min_samples_leaf=5, 
        max_depth=10)

m.fit(X, y, sample_weight=np.array([3,4,2,3]))

上面的代码工作得很好。然后,我尝试在这样的管道对象中执行此操作,使用管道对象而不是仅使用随机森林:

m = sklearn.pipeline.Pipeline([
    ('feature_selection', sklearn.feature_selection.SelectKBest(
        score_func=sklearn.feature_selection.f_regression,
        k=25)),
    ('model', sklearn.ensemble.RandomForestClassifier(
        random_state=0, 
        oob_score=True, 
        n_estimators=500,
        min_samples_leaf=5, 
        max_depth=10))])

m.fit(X, y, sample_weight=np.array([3,4,2,3]))

现在这会在 fit 方法中使用“ValueError: need more than 1 value to unpack”中断。

ValueError                                Traceback (most recent call last)
<ipython-input-212-c4299f5b3008> in <module>()
     25         max_depth=10))])
     26 
---> 27 m.fit(X, y, sample_weights=np.array([3,4,2,3]))

/usr/local/lib/python2.7/dist-packages/sklearn/pipeline.pyc in fit(self, X, y, **fit_params)
    128         data, then fit the transformed data using the final estimator.
    129         """
--> 130         Xt, fit_params = self._pre_transform(X, y, **fit_params)
    131         self.steps[-1][-1].fit(Xt, y, **fit_params)
    132         return self

/usr/local/lib/python2.7/dist-packages/sklearn/pipeline.pyc in _pre_transform(self, X, y, **fit_params)
    113         fit_params_steps = dict((step, {}) for step, _ in self.steps)
    114         for pname, pval in six.iteritems(fit_params):
--> 115             step, param = pname.split('__', 1)
    116             fit_params_steps[step][param] = pval
    117         Xt = X

ValueError: need more than 1 value to unpack

我正在使用sklearn 版本0.14
我认为问题在于管道中的F selection 步骤没有接受sample_weights 的参数。如何在运行“fit”时将此参数仅传递给管道中的一步?谢谢。

【问题讨论】:

  • 第二个代码示例中的m 是如何定义的? general_pipeline 的用途是什么(它似乎已定义但从未使用过)?此外,如果您还提供一些数据会有所帮助。
  • 抱歉,这是一个复制和粘贴错误。
  • 好的,你能不能也显示你的输入数据?
  • 我提供了更多信息,希望它足以重现错误。如果还不清楚,请告诉我。这有点紧急!谢谢。
  • 为什么X是一个对象数组,每行最后一个元素是一个字符串?

标签: python pandas scikit-learn pipeline


【解决方案1】:

From the documentation:

管道的目的是组装几个步骤,可以 在设置不同参数的同时交叉验证。为了这, 它可以设置各个步骤的参数使用它们的名称 以及由‘__’分隔的参数名称,如下例所示。

因此,您只需在要传递给 'model' 步骤的任何合适参数 kwarg 前面插入 model__

m.fit(X, y, model__sample_weight=np.array([3,4,2,3]))

【讨论】:

  • 你的速度稍微快了一点。第二行确实是推荐的,似乎。也可以查看this link
  • 嗯。这对我不起作用并给出同样的错误?
  • 它对我很有用(在这两种情况下m.predict(X) 返回[0, 0, 0, 0])。
  • @Sother:你确定你使用两个下划线而不是一个?如果一个人只使用一个,一个人确实会得到同样的错误。我正在使用 0.17;您可能应该更新...
  • 有一些答案误导我到pipeline.fit(X_train, y_train, fit_params={'sample_weight': sample_weight}),直到找到这个。谢谢。
【解决方案2】:

您也可以使用方法set_params 并在步骤名称前添加。

m = sklearn.pipeline.Pipeline([
    ('feature_selection', sklearn.feature_selection.SelectKBest(
        score_func=sklearn.feature_selection.f_regression,
        k=25)),
    ('model', sklearn.ensemble.RandomForestClassifier(
        random_state=0, 
        oob_score=True, 
        n_estimators=500,
        min_samples_leaf=5, 
        max_depth=10))])
m.set_params(model__sample_weight=np.array([3,4,2,3]))

【讨论】:

    【解决方案3】:

    希望我可以在上面的 @rovyko 帖子上发表评论,而不是单独的答案,但我还没有足够的 stackoverflow 声誉来离开 cmets,所以它就在这里。

    你不能使用:

    Pipeline.set_params(model__sample_weight=np.array([3,4,2,3])

    RandomForestClassifier.fit() 方法设置参数。代码(here)中指出的Pipeline.set_params() 仅用于管道中各个步骤的初始化参数。 RandomForestClassifier 没有名为 sample_weight 的初始化参数(参见其 __init__() 方法 here)。 sample_weight实际上是RandomForestClassifierfit()方法的输入参数,因此只能通过正确标记的答案是@ali_m中给出的方法来设置,即,

    m.fit(X, y, model__sample_weight=np.array([3,4,2,3])).

    【讨论】:

    • 如果您认为答案有误,您可以请求编辑答案。提交我的修改,我会接受修改。
    猜你喜欢
    • 2020-09-22
    • 2017-03-16
    • 2016-12-26
    • 2018-07-29
    • 2016-01-11
    • 1970-01-01
    • 1970-01-01
    • 2015-08-14
    相关资源
    最近更新 更多