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

数据挖掘 特征选择 scikit-学习
2021-10-05 20:28:34

我正在解决功能过多的问题,并且训练我的模型需要很长时间。我实现了一个前向选择算法来选择特征。

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

4个回答

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

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

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

  1. 使用固有的稀疏模型,如ElasticNetor Lasso
  2. 使用 规范化您的功能StandardScaler,然后仅按 对您的功能进行排序model.coef_对于完全独立的协变量,它相当于按 p 值排序。该课程sklearn.feature_selection.RFE将为您完成,RFECV甚至会评估最佳数量的功能。
  3. 通过调整使用前向选择的[一个实现][1]R2statsmodels.
  4. 进行蛮力向前或向后选择,以最大化您最喜欢的交叉验证指标(它可能需要大约协变量数量的二次时间)。一个 scikit-learn 兼容mlxtend包 [支持][2] 这种方法适用于任何估计器和任何度量。
  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.idxmin()
                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.idxmax()
                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)


This example would print the following output:

    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']


  [1]: http://planspace.org/20150423-forward_selection_with_statsmodels/
  [2]: http://rasbt.github.io/mlxtend/user_guide/feature_selection/SequentialFeatureSelector/

Sklearn 确实有一个前向选择算法,尽管在 scikit-learn 中没有这样称呼它。scikit-learn 中称为F_regression的特征选择方法将依次包含对模型改进最大的特征,直到模型中有K特征(K 为输入)。

它首先对每个特征上的标签进行单独回归,然后使用 F 统计量观察哪个特征对模型的改进最大。然后它将获胜特征合并到模型中。然后它遍历剩余的特征以找到下一个对模型改进最大的特征,再次使用 F 统计量或 F 检验。它会这样做,直到模型中有 K 个特征。

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

从 0.24 版开始,它确实如此!

公告文件