如何在scikit-learn的"管道"中使用自定义功能选择功能

10 python scikit-learn

假设我想通过交叉验证和使用pipeline类比较特定(监督)数据集的不同降维方法,该数据集包含n> 2个特征.

例如,如果我想尝试使用PCA和LDA,我可以做类似的事情:

from sklearn.cross_validation import cross_val_score, KFold
from sklearn.pipeline import Pipeline
from sklearn.naive_bayes import GaussianNB
from sklearn.preprocessing import StandardScaler
from sklearn.lda import LDA
from sklearn.decomposition import PCA

clf_all = Pipeline(steps=[
    ('scaler', StandardScaler()),           
    ('classification', GaussianNB())   
    ])

clf_pca = Pipeline(steps=[
    ('scaler', StandardScaler()),    
    ('reduce_dim', PCA(n_components=2)),
    ('classification', GaussianNB())   
    ])

clf_lda = Pipeline(steps=[
    ('scaler', StandardScaler()), 
    ('reduce_dim', LDA(n_components=2)),
    ('classification', GaussianNB())   
    ])

# Constructing the k-fold cross validation iterator (k=10)  

cv = KFold(n=X_train.shape[0],  # total number of samples
           n_folds=10,           # number of folds the dataset is divided into
           shuffle=True,
           random_state=123)

scores = [
    cross_val_score(clf, X_train, y_train, cv=cv, scoring='accuracy')
            for clf in [clf_all, clf_pca, clf_lda]
    ]
Run Code Online (Sandbox Code Playgroud)

但是现在,让我们说 - 基于一些"领域知识" - 我假设特征3和4可能是"好的特征"(数组的第三和第四列X_train),我想将它们与其他方法.

我如何在pipeline?中包含这样的手动功能选择?

例如

def select_3_and_4(X_train):
    return X_train[:,2:4]

clf_all = Pipeline(steps=[
    ('scaler', StandardScaler()),
    ('feature_select', select_3_and_4),           
    ('classification', GaussianNB())   
    ]) 
Run Code Online (Sandbox Code Playgroud)

显然不会奏效.

所以我假设我必须创建一个特征选择类,它具有一个返回数组的两列的transform虚方法和fit方法numpy?或者,还有更好的方法?

小智 26

我只想发布我的解决方案的完整性,也许它对一个或另一个有用:

class ColumnExtractor(object):

    def transform(self, X):
        cols = X[:,2:4] # column 3 and 4 are "extracted"
        return cols

    def fit(self, X, y=None):
        return self
Run Code Online (Sandbox Code Playgroud)

然后,它可以用在Pipeline这样的:

clf = Pipeline(steps=[
    ('scaler', StandardScaler()),
    ('reduce_dim', ColumnExtractor()),           
    ('classification', GaussianNB())   
    ])
Run Code Online (Sandbox Code Playgroud)

编辑:一般解决方案

对于更通用的解决方案,如果要选择并堆叠多个列,基本上可以使用以下类,如下所示:

import numpy as np

class ColumnExtractor(object):

    def __init__(self, cols):
        self.cols = cols

    def transform(self, X):
        col_list = []
        for c in self.cols:
            col_list.append(X[:, c:c+1])
        return np.concatenate(col_list, axis=1)

    def fit(self, X, y=None):
        return self

    clf = Pipeline(steps=[
    ('scaler', StandardScaler()),
    ('dim_red', ColumnExtractor(cols=(1,3))),   # selects the second and 4th column      
    ('classification', GaussianNB())   
    ])
Run Code Online (Sandbox Code Playgroud)


Ari*_*iel 5

添加塞巴斯蒂安Raschka的和eickenberg的答案,变压器对象应持要求scikit学习的中指定的文件.

有几个更多的要求不是仅仅拥有健美的转变,如果你想估算人员使用的参数估计,如实施set_params.

  • 实现`set_params`的推荐方法是从BaseEstimator继承它,例如通过使用语句`class my_class(TransformerMixin,BaseEstimator)`定义你的类.除非你确定需要,否则不要编写自己的`set_params`方法. (3认同)

eic*_*erg 3

如果您想使用该Pipeline对象,那么是的,干净的方法是编写一个转换器对象。这样做的肮脏方法是

select_3_and_4.transform = select_3_and_4.__call__
select_3_and_4.fit = lambda x: select_3_and_4
Run Code Online (Sandbox Code Playgroud)

select_3_and_4按照您在管道中的方式使用它。显然你也可以写一个类。

否则,X_train[:, 2:4]如果您知道其他功能不相关,您也可以只提供给您的管道。

数据驱动的特征选择工具可能偏离主题,但总是有用的:在您的情况下检查例如sklearn.feature_selection.SelectKBest使用sklearn.feature_selection.f_classifsklearn.feature_selection.f_regression与例如。k=2