【问题标题】:Scikit-Learn feature selection using SVC based on percentile of .coef_ values基于 .coef_ 值的百分位使用 SVC 进行 Scikit-Learn 特征选择
【发布时间】:2016-08-20 18:18:46
【问题描述】:

我正在尝试编写一个 Python 类,以便使用 .coef_ 属性值来选择 scikit-learn 0.17.1 中的功能。我只想选择 .coef_ 值在第 10 个百分位及以上的特征(第 10、第 11、第 12、第 13、第 14、第 15、第 16、第 ....、第 94、第 95、第 96、第 97、第 98、第 99 , 100)。

我无法使用SelectFromModels() 执行此操作,因此我尝试为此功能选择编写一个名为ChooseCoefPercentile() 的自定义类。我正在尝试使用以下函数根据.coef_ 的百分位数选择特征:

from sklearn.datasets import load_iris
from sklearn.cross_validation import train_test_split
X_train, X_test, y_train, y_test = train_test_split(load_iris().data,
                                   load_iris().target, test_size=0.33, random_state=42)

def percentile_sep(coefs,p):
    from numpy import percentile as pc
    gt_p = coefs[coefs>pc(coefs,p)].argsort()
    return list(gt_p)

from sklearn.base import BaseEstimator, TransformerMixin
class ChooseCoefPercentile(BaseEstimator, TransformerMixin):
    def __init__(self, est_, perc=50):
        self.perc = perc
        self.est_ = est_
    def fit(self, *args, **kwargs):
        self.est_.fit(*args, **kwargs)
        return self
    def transform(self, X):
        perc_i = percentile_sep(self.est_.coef_,self.perc)
        i_ = self.est_.coef_.argsort()[::-1][perc_i[:]]
        X_tr = X[:,i_]
        self.coef_ = self.est_.coef_[i_]
        return X_tr

# Import modules
from sklearn import svm,ensemble,pipeline,grid_search

# Instantiate feature selection estimator and classifier
f_sel = ChooseCoefPercentile(svm.SVC(kernel='linear'),perc=10)
clf = ensemble.RandomForestClassifier(random_state=42,oob_score=False)

CustPipe = pipeline.Pipeline([("feat_s",f_sel),("Clf",clf)])
bf_est = grid_search.GridSearchCV(CustPipe,cv=2,param_grid={'Clf__n_estimators':[100,200]})
bf_est.fit(X_train, y_train)

我收到以下错误:

Traceback (most recent call last):
  File "C:\Python27\test.py", line 35, in <module>
    bf_est.fit(X_train, y_train)
  File "C:\Python27\lib\site-packages\sklearn\grid_search.py", line 804, in fit
    return self._fit(X, y, ParameterGrid(self.param_grid))
  File "C:\Python27\lib\site-packages\sklearn\grid_search.py", line 553, in _fit
    for parameters in parameter_iterable
  File "C:\Python27\lib\site-packages\sklearn\externals\joblib\parallel.py", line 800, in __call__
    while self.dispatch_one_batch(iterator):
  File "C:\Python27\lib\site-packages\sklearn\externals\joblib\parallel.py", line 658, in dispatch_one_batch
    self._dispatch(tasks)
  File "C:\Python27\lib\site-packages\sklearn\externals\joblib\parallel.py", line 566, in _dispatch
    job = ImmediateComputeBatch(batch)
  File "C:\Python27\lib\site-packages\sklearn\externals\joblib\parallel.py", line 180, in __init__
    self.results = batch()
  File "C:\Python27\lib\site-packages\sklearn\externals\joblib\parallel.py", line 72, in __call__
    return [func(*args, **kwargs) for func, args, kwargs in self.items]
  File "C:\Python27\lib\site-packages\sklearn\cross_validation.py", line 1531, in _fit_and_score
    estimator.fit(X_train, y_train, **fit_params)
  File "C:\Python27\lib\site-packages\sklearn\pipeline.py", line 164, in fit
    Xt, fit_params = self._pre_transform(X, y, **fit_params)
  File "C:\Python27\lib\site-packages\sklearn\pipeline.py", line 145, in _pre_transform
    Xt = transform.fit_transform(Xt, y, **fit_params_steps[name])
  File "C:\Python27\lib\site-packages\sklearn\base.py", line 458, in fit_transform
    return self.fit(X, y, **fit_params).transform(X)
  File "C:\Python27\test.py", line 21, in transform
    i_ = self.est_.coef_.argsort()[::-1][perc_i[:]]
IndexError: index 6 is out of bounds for axis 0 with size 3

以下行中的 .coef_ 值的 NumPy 数组似乎存在问题:

i_ = self.est_.coef_.argsort()[::-1][perc_i[:]]

在这一行中,我试图根据它们的索引只选择那些位于第 10 个百分位以上的 .coef_ 值。索引存储在列表perc_i 中。我似乎无法使用此列表正确索引 .coef_ 数组。

出现这个错误是因为数组需要分成行吗?还是应该使用其他方法根据百分位数提取 .coef_ 值?

【问题讨论】:

  • 问题确实是 .coef_ 数组被划分为每个类的行。选择机制应该更加精确:如果一个特征高于一个类的百分位数,而另一个类没有,会发生什么?
  • 这是个好问题。我应该在 OP 中提到这一点 - 实际上,在这种情况下,我想选择该功能。假设是这种情况,有没有办法选择特征?另外,您知道SelectPercentile() 是如何处理这些情况的吗? scikit-learn.org/stable/modules/generated/…
  • FWIW 这个功能非常接近github.com/scikit-learn/scikit-learn/pull/6717 中提出的功能,所以希望 scikit-learn 很快会在SelectFromModel 中支持这个功能。
  • SelectPercentile 不处理具有不同系数的每个类:它只是计算每个特征的分数。一些估计器提供feature_importances_SelectFromModel 使用 L1-norm over per class coefficients 来分配每个特征的总体得分,但 github.com/scikit-learn/scikit-learn/pull/6181 承诺使规范可配置。
  • 乔尔谢谢。关于如何同时更改 OP 中的代码以使其正常工作的任何想法?

标签: python list python-2.7 numpy scikit-learn


【解决方案1】:

我建议根据行数使用模算术计算系数矩阵的相关列:

def transform(self, X):
    perc_i = percentile_sep(self.est_.coef_,self.perc)
    nclass=self.est_.coef_.shape[0]
    i_ = list(set(map(lambda x:x%nclass,perc_i)))
    X_tr = X[:,i_]
    self.coef_ = self.est_.coef_[i_]
    return X_tr

【讨论】:

  • 谢谢。我试过了,.fit() 部分现在可以正常工作了。对于转换,我使用了new_features = bf_est.best_estimator_.named_steps['feat_s'].transform([list(X_train)]),但我收到以下错误消息:Traceback (most recent call last): File "C:\Python27\test.py", line 37, in &lt;module&gt; new_features = bf_est.best_estimator_.named_steps['feat_s'].transform([list(X_train)]) File "C:\Python27\test.py", line 23, in transform X_tr = X[:,i_] TypeError: list indices must be integers, not tuple。我给了它一个列表[list(X_train)]。它认为这是一个元组有什么原因吗?
  • 我不确定 tuple 的问题出在哪里。但是,我刚刚尝试过bf_est.best_estimator_.named_steps['feat_s'].transform(X_train),但没有报错
  • 很抱歉给您带来了困惑。我犯了一个错误。你是对的 - 这按预期工作。谢谢你。
  • 很高兴它现在可以工作;感谢您接受答案!
猜你喜欢
  • 2021-03-26
  • 2014-11-05
  • 2018-02-24
  • 1970-01-01
  • 2020-05-01
  • 2018-09-25
  • 2018-06-01
  • 2015-11-13
相关资源
最近更新 更多