scikit-learn是否具有正向选择/逐步回归算法?


37

我正在解决具有太多功能的问题,并且训练模型花费的时间太长。我实现了前向选择算法来选择特征。

但是,我想知道scikit-learn是否具有正向选择/逐步回归算法?


我为此创建了自己的课程,但令我惊讶的是sklearn没有该课程。
Maksud 2014年

1
使用假设检验是一种很糟糕的特征选择方法。您将不得不做很多事情,当然,您还会得到很多错误的肯定和否定。
里卡多·克鲁兹

Answers:


21

不,sklearn似乎没有向前选择算法。但是,它确实提供了递归特征消除,这是一种贪婪特征消除算法,类似于顺序向后选择。请参阅此处的文档:

http://scikit-learn.org/stable/modules/generation/sklearn.feature_selection.RFE.html


3
很好的建议,但是使用sci-kit实现的问题是特征的重要性由模型系数来量化,即模型是否具有coef_接口。这将排除基于树的方法等。但是,我认为@Maksud要求的是James在“统计学习入门”中描述的内容,其中按重要性递归地添加/删除了特征,并通过验证集的准确性对其进行了量化。 。这允许跨所有类型的模型进行特征选择,而不仅仅是线性参数模型。
eggie5

9

Sklearn DOES具有前向选择算法,尽管在scikit-learn中未将其称为。scikit-learn中称为F_regression的特征选择方法将依次包含对模型进行最大改进的特征,直到模型中存在K特征(K为输入)为止。

首先从分别回归每个要素上的标签开始,然后使用F统计量观察哪个要素对模型的改进最大。然后,它将获胜功能纳入模型。然后,再次使用F统计量或F检验,迭代其余特征以找到可最大程度改善模型的下一个特征。这样做直到模型中有K个要素。

注意,与合并到模型中的特征相关的其余特征可能不会被选择,因为它们与残差不相关(尽管它们可能与标签很好地相关)。这有助于防止多重共线性。



1
您是说选择K最佳吗?
硝基”

是。另外,您应该阅读以下内容:stats.stackexchange.com/questions/204141/…
Candic3

2
这是一种前向选择。但这不是通用的-它特定于线性回归模型,而正向选择通常可以像RFE一样与任何模型(不可知模型)一起使用,并且可以处理分类或回归问题。但是我怀疑大多数人都在寻找这个用例,在这里提到它肯定是件好事。
西蒙(Simon)

2
这不是STEPWISE的选择,因为每个p值都是针对单变量回归计算的,与所有其他协变量无关。
大卫·戴尔

9

Scikit-learn确实不支持逐步回归。这是因为通常所谓的“逐步回归”是一种基于线性回归系数的p值的算法,而scikit-learn故意避免采用推理方法进行模型学习(重要性检验等)。而且,纯OLS只是众多回归算法之一,从scikit-learn的角度来看,它既不是非常重要,也不是最好的算法之一。

但是,对于仍然需要使用线性模型进行特征选择的好方法的人,有一些建议:

  1. 使用固有稀疏模型,例如ElasticNetLasso
  2. 使用标准化您的功能StandardScaler,然后只需按即可订购您的功能model.coef_。对于完全独立的协变量,它等效于按p值排序。该课程sklearn.feature_selection.RFE将为您做到这一点,RFECV甚至会评估最佳功能数量。
  3. R2statsmodels
  4. 进行前向或后向蛮力选择,以最大程度地利用交叉验证中您喜欢的指标(协变量数可能需要大约二次时间)。兼容scikit-learn的mlxtend软件包对任何估计量和度量均支持此方法。
  5. 如果您仍然需要香草逐步回归,则可以更轻松地基于进行回归,statsmodels因为此程序包会为您计算p值。基本的前向后选择可能如下所示:

```

from sklearn.datasets import load_boston
import pandas as pd
import numpy as np
import statsmodels.api as sm

data = load_boston()
X = pd.DataFrame(data.data, columns=data.feature_names)
y = data.target


def stepwise_selection(X, y, 
                       initial_list=[], 
                       threshold_in=0.01, 
                       threshold_out = 0.05, 
                       verbose=True):
    """ Perform a forward-backward feature selection 
    based on p-value from statsmodels.api.OLS
    Arguments:
        X - pandas.DataFrame with candidate features
        y - list-like with the target
        initial_list - list of features to start with (column names of X)
        threshold_in - include a feature if its p-value < threshold_in
        threshold_out - exclude a feature if its p-value > threshold_out
        verbose - whether to print the sequence of inclusions and exclusions
    Returns: list of selected features 
    Always set threshold_in < threshold_out to avoid infinite looping.
    See https://en.wikipedia.org/wiki/Stepwise_regression for the details
    """
    included = list(initial_list)
    while True:
        changed=False
        # forward step
        excluded = list(set(X.columns)-set(included))
        new_pval = pd.Series(index=excluded)
        for new_column in excluded:
            model = sm.OLS(y, sm.add_constant(pd.DataFrame(X[included+[new_column]]))).fit()
            new_pval[new_column] = model.pvalues[new_column]
        best_pval = new_pval.min()
        if best_pval < threshold_in:
            best_feature = new_pval.argmin()
            included.append(best_feature)
            changed=True
            if verbose:
                print('Add  {:30} with p-value {:.6}'.format(best_feature, best_pval))

        # backward step
        model = sm.OLS(y, sm.add_constant(pd.DataFrame(X[included]))).fit()
        # use all coefs except intercept
        pvalues = model.pvalues.iloc[1:]
        worst_pval = pvalues.max() # null if pvalues is empty
        if worst_pval > threshold_out:
            changed=True
            worst_feature = pvalues.argmax()
            included.remove(worst_feature)
            if verbose:
                print('Drop {:30} with p-value {:.6}'.format(worst_feature, worst_pval))
        if not changed:
            break
    return included

result = stepwise_selection(X, y)

print('resulting features:')
print(result)

本示例将输出以下输出:

Add  LSTAT                          with p-value 5.0811e-88
Add  RM                             with p-value 3.47226e-27
Add  PTRATIO                        with p-value 1.64466e-14
Add  DIS                            with p-value 1.66847e-05
Add  NOX                            with p-value 5.48815e-08
Add  CHAS                           with p-value 0.000265473
Add  B                              with p-value 0.000771946
Add  ZN                             with p-value 0.00465162
resulting features:
['LSTAT', 'RM', 'PTRATIO', 'DIS', 'NOX', 'CHAS', 'B', 'ZN']

发布的向前逐步回归代码无法正常运行。向后逐步回归应提供相同的结果,但事实并非如此。重新运行回归时,返回的p值高于阈值的因子。我还使用STATA逐步运行了相同的数据集,并使用了向后逐步运行了相同的阈值,并获得了完全不同的结果。基本上,不要使用它。我将使用他的模板编写自己的向后逐步回归代码。
Michael Corley MBA LSSBB

绝对不能保证向前和向后逐步回归到同一解。并且,如果您发现我的解决方案中存在错误,请附加代码以重现它。
David Dale

1

实际上,有一个不错的算法“ Forward_Select”,它使用Statsmodels,并允许您设置自己的指标(AIC,BIC,Adjusted-R-Squared或您喜欢的任何指标),以向模型中逐步添加变量。该算法可以在此页面的注释部分中找到-向下滚动,您将在页面底部附近看到它。

https://planspace.org/20150423-forward_selection_with_statsmodels/

我还要补充一点,该算法还有一个不错的功能:您可以将其应用于分类或回归问题!您只需要告诉它。

试试看,自己看看。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.