【问题标题】:TypeError: get_params() missing 1 required positional argument: 'self'类型错误:get_params() 缺少 1 个必需的位置参数:'self'
【发布时间】:2015-07-13 15:38:24
【问题描述】:

我试图使用带有 python-3.4 的 scikit-learn 包进行网格搜索,

from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model.logistic import LogisticRegression
from sklearn.pipeline import Pipeline
from sklearn.grid_search import GridSearchCV
import pandas as pd
from sklearn.cross_validation import train_test_split
from sklearn.metrics import precision_score, recall_score, accuracy_score
from sklearn.preprocessing import LabelBinarizer
import numpy as np

pipeline = Pipeline([
    ('vect', TfidfVectorizer(stop_words='english')),
    ('clf', LogisticRegression)
])

parameters = {
    'vect__max_df': (0.25, 0.5, 0.75),
    'vect__stop_words': ('english', None),
    'vect__max_features': (2500, 5000, 10000, None),
    'vect__ngram_range': ((1, 1), (1, 2)),
    'vect__use_idf': (True, False),
    'vect__norm': ('l1', 'l2'),
    'clf__penalty': ('l1', 'l2'),
    'clf__C': (0.01, 0.1, 1, 10)
}

if __name__ == '__main__':
    grid_search = GridSearchCV(pipeline, parameters, n_jobs=-1, verbose=1, scoring='accuracy', cv = 3)
    df = pd.read_csv('SMS Spam Collection/SMSSpamCollection', delimiter='\t', header=None)
    lb = LabelBinarizer()
    X, y = df[1], np.array([number[0] for number in lb.fit_transform(df[0])])
    X_train, X_test, y_train, y_test = train_test_split(X, y)
    grid_search.fit(X_train, y_train)
    print('Best score: ', grid_search.best_score_)
    print('Best parameter set:')
    best_parameters = grid_search.best_estimator_.get_params()
    for param_name in sorted(best_parameters):
        print(param_name, best_parameters[param_name])

但是,它并没有运行成功,错误信息是这样的:

Fitting 3 folds for each of 1536 candidates, totalling 4608 fits
Traceback (most recent call last):
  File "/home/xiangru/PycharmProjects/machine_learning_note_with_sklearn/grid search.py", line 36, in <module>
    grid_search.fit(X_train, y_train)
  File "/usr/local/lib/python3.4/dist-packages/sklearn/grid_search.py", line 732, in fit
    return self._fit(X, y, ParameterGrid(self.param_grid))
  File "/usr/local/lib/python3.4/dist-packages/sklearn/grid_search.py", line 493, in _fit
    base_estimator = clone(self.estimator)
  File "/usr/local/lib/python3.4/dist-packages/sklearn/base.py", line 47, in clone
    new_object_params[name] = clone(param, safe=False)
  File "/usr/local/lib/python3.4/dist-packages/sklearn/base.py", line 35, in clone
    return estimator_type([clone(e, safe=safe) for e in estimator])
  File "/usr/local/lib/python3.4/dist-packages/sklearn/base.py", line 35, in <listcomp>
    return estimator_type([clone(e, safe=safe) for e in estimator])
  File "/usr/local/lib/python3.4/dist-packages/sklearn/base.py", line 35, in clone
    return estimator_type([clone(e, safe=safe) for e in estimator])
  File "/usr/local/lib/python3.4/dist-packages/sklearn/base.py", line 35, in <listcomp>
    return estimator_type([clone(e, safe=safe) for e in estimator])
  File "/usr/local/lib/python3.4/dist-packages/sklearn/base.py", line 45, in clone
    new_object_params = estimator.get_params(deep=False)
TypeError: get_params() missing 1 required positional argument: 'self'

我也试过只用

if __name__ == '__main__':
    pipeline.get_params()

它给出了同样的错误信息。 谁知道如何解决这个问题?

【问题讨论】:

  • 这个错误几乎总是具有误导性,并且实际上意味着你调用的是类的实例方法,而不是实例(比如调用dict.keys()而不是@ 987654326@ 在名为 ddict 上)。 best_estimator_ 是否为您提供估计器类型而不是估计器类型的实例?如果是这样,那就是问题所在;您必须通过调用该类型(使用适当的参数)来构建估计值。

标签: python scikit-learn


【解决方案1】:

此错误几乎总是具有误导性,实际上意味着您正在调用类的实例方法,而不是实例(例如在 @ 上调用 dict.keys() 而不是 d.keys() 987654326@ 命名为 d)。*

这正是这里发生的事情。 The docs 暗示 best_estimator_ 属性,就像初始化器的 estimator 参数一样,不是一个估计器instance,它是一个估计器type,并且“A object为每个网格点实例化该类型的。"

所以,如果你想调用方法,你必须为某个特定的网格点构造一个该类型的对象。

但是,快速浏览一下文档,如果您想要获取用于返回最佳分数的最佳估计器的特定实例的参数,那不只是best_params_ ? (对不起,这部分有点猜测......)


对于Pipeline 调用,您肯定有一个实例。该方法唯一的documentation 是一个参数规范,它表明它采用一个可选参数deep。但在幕后,它可能会将get_params() 调用转发给它的一个属性。对于('clf', LogisticRegression),看起来你是用class LogisticRegression 构造它,而不是那个类的实例,所以如果这就是它最终转发到的东西,那就可以解释问题。


* 错误显示“缺少 1 个必需的位置参数:'self'”而不是“必须在实例上调用”或其他内容的原因是在 Python 中,d.keys() 有效地变成了dict.keys(d) ,并且以这种方式显式调用它是完全合法的(有时很有用),所以 Python 不能真正告诉你 dict.keys() 是非法的,只是它缺少 self 参数。

【讨论】:

【解决方案2】:

我终于解决了这个问题。原因正如阿巴纳特所说。

首先我尝试了:

pipeline = LogisticRegression()

parameters = {
    'penalty': ('l1', 'l2'),
    'C': (0.01, 0.1, 1, 10)
}

而且效果很好。

凭着这种直觉,我将管道修改为:

pipeline = Pipeline([
    ('vect', TfidfVectorizer(stop_words='english')),
    ('clf', LogisticRegression())
])

注意LogisticRegression 后面有一个()。 这次成功了。

【讨论】:

  • () 表示您正在调用它。调用一个类会构造一个类的实例。正如我在回答中解释的那样,这正是您必须做的。
  • @abarnert 谢谢!我明白你的想法。
  • 我遇到了与 lda = discriminant_analysis.LinearDiscriminantAnalysis() 类似的问题。实例化后忘记()
  • 如果@abarnert 给了你正确的解决方案,我认为合适的做法是选择他的答案作为解决方案——而不是你自己的。
  • @abarnert 的回答也帮助了我!为什么不将其标记为原始问题的答案,而不是这个?
【解决方案3】:

改变逻辑回归

pipeline = Pipeline([
('vect', TfidfVectorizer(stop_words='english')),
('clf', LogisticRegression)
 ])

LogisticRegression()

问题就解决了。

【讨论】:

  • 此信息已存在于 2015 年的现有答案中。
猜你喜欢
  • 2022-01-03
  • 2021-07-14
  • 2019-10-02
  • 2017-06-24
  • 2016-05-27
  • 2017-08-21
  • 2021-09-21
  • 2020-11-10
  • 2018-04-05
相关资源
最近更新 更多