逐步回归(Stepwise Regression) 是一种用于特征选择的统计方法,旨在在众多候选自变量中自动选择对因变量具有显著影响的变量,从而构建一个既简洁又有效的回归模型。逐步回归通过迭代过程,逐步添加或删除自变量,以优化某种模型选择标准(如AIC、BIC、调整后的 R 2 R^2 R2等)。它在统计学、经济学、生物统计、机器学习等领域被广泛应用,尤其在处理多重共线性和高维数据时表现出一定的优势。
下文将从逐步回归的概念、类型、方法步骤、优缺点、实现方式及实际应用示例等多个方面进行详细介绍。
1. 逐步回归的概念
1.1 什么是逐步回归?
逐步回归是一种自动化的特征选择方法,通过在回归模型中逐步添加或删除自变量,来找到一个最佳的自变量组合,以优化模型的某种性能指标。其核心目的是在保持模型解释力的同时,减少模型复杂度,防止过拟合,并提高模型的泛化能力。
1.2 为什么使用逐步回归?
- 自动化特征选择:在自变量数量较多的情况下,逐步回归能够高效地筛选出对因变量有显著影响的特征,减少人为选择的主观性。
- 处理多重共线性:通过选择变量组合,逐步回归有助于减少自变量之间的多重共线性问题。
- 提高模型解释性:通过剔除不显著的变量,模型变得更加简洁,便于解释和理解。
- 防止过拟合:通过限制自变量数量,逐步回归有助于降低模型的复杂度,减少过拟合风险。
2. 逐步回归的类型
逐步回归主要分为以下三种类型:
2.1 向前选择(Forward Selection)
-
初始模型:仅包含截距项(无自变量)。
-
过程:
- 在所有未入选的自变量中,选择一个对因变量影响最显著的自变量加入模型。
- 评估加入该变量后的模型性能。
- 重复步骤1和2,直到没有自变量显著提升模型性能。
-
优点:
- 简单直观,计算效率高。
- 适用于变量数量较多且各变量独立性较强的场景。
-
缺点:
- 可能忽略联合效应较强但单独效应较弱的变量。
- 对初始选择敏感,可能导致全局最优解未被找到。
2.2 向后剔除(Backward Elimination)
-
初始模型:包含所有候选自变量。
-
过程:
- 评估所有自变量的显著性,选择一个最不显著的自变量从模型中剔除。
- 重新评估模型性能。
- 重复步骤1和2,直到所有自变量均显著。
-
优点:
- 考虑了所有变量的联合影响。
- 适用于自变量数量较少或样本量较大的场景。
-
缺点:
- 计算量较大,尤其在自变量数量较多时。
- 同样可能错过联合效应较强的变量组合。
2.3 双向逐步回归(Stepwise Selection)
-
结合向前选择和向后剔除。
-
过程:
- 类似向前选择,逐步添加自变量。
- 在每一步添加后,评估现有自变量的显著性,剔除不显著的变量。
- 重复添加和剔除,直到模型收敛。
-
优点:
- 更全面地考虑变量的添加与剔除。
- 更有可能找到全局最优的自变量组合。
-
缺点:
- 计算复杂度较高。
- 依然可能受初始步骤影响,导致次优模型选择。
3. 逐步回归的方法步骤
以双向逐步回归为例,逐步回归的典型流程如下:
3.1 确定初始模型
- 向前选择:通常从仅包含截距项的模型开始。
- 向后剔除:通常从包含所有自变量的模型开始。
- 双向逐步:从一个中间模型开始,或结合前两者。
3.2 设定准则
- 显著性水平:设定自变量进入或退出模型的显著性阈值(如 p < 0.05 p < 0.05 p<0.05)。
- 信息准则:如AIC、BIC等,用于评估模型性能并指导变量选择。
3.3 迭代过程
-
变量添加:
- 在所有未入选的自变量中,选择一个最显著的变量加入模型。
- 评估加入后的模型性能。
-
变量剔除:
- 在当前模型中,选择一个最不显著的变量剔除。
- 评估剔除后的模型性能。
-
重复:
- 继续添加或剔除变量,直到模型满足停止条件(如所有变量均显著,或AIC/BIC不再降低)。
3.4 模型评估与选择
- 显著性检验:确保所有自变量在模型中都具有统计显著性。
- 信息准则:选择具有最低AIC/BIC值的模型。
- 交叉验证:通过交叉验证评估模型的泛化能力,防止过拟合。
4. 逐步回归的优缺点
4.1 优点
- 自动化特征选择:减少手动选择特征的主观性和工作量。
- 提升模型解释性:通过剔除不显著变量,使模型更加简洁易懂。
- 处理多重共线性:通过选择相关性较低的变量组合,减轻多重共线性问题。
- 适用性广:适用于多种类型的回归模型,如线性回归、逻辑回归等。
4.2 缺点
- 可能遗漏重要变量:若某些变量的联合效应较强,但单独效应较弱,逐步回归可能会忽略这些变量。
- 过度依赖统计显著性:可能忽略变量的业务意义或实际影响,仅基于统计指标进行选择。
- 不稳定性:不同的数据样本可能导致不同的变量选择结果,尤其在自变量数量较多时。
- 计算复杂度:尤其在自变量数量较多时,逐步回归的计算量较大。
- 模型偏倚:逐步回归可能倾向于选择样本中表现最佳的变量,导致模型在新数据上的表现不稳定。
5. 逐步回归的实现
5.1 在 R 中
R 语言提供了内置的 step()
函数来进行逐步回归。
# 加载数据
data(mtcars)
# 拟合全模型(所有自变量)
full_model <- lm(mpg ~ ., data = mtcars)
# 拟合空模型(仅截距)
empty_model <- lm(mpg ~ 1, data = mtcars)
# 逐步回归(双向)
stepwise_model <- step(empty_model,
scope = list(lower = empty_model, upper = full_model),
direction = "both",
trace = FALSE)
# 查看模型摘要
summary(stepwise_model)
说明:
direction
参数可以设置为"forward"
、"backward"
或"both"
,分别对应向前选择、向后剔除和双向逐步回归。trace = FALSE
用于关闭迭代过程的详细输出。
5.2 在 Python 中
Python 没有内置的逐步回归函数,但可以通过自定义函数或使用第三方库实现。以下是使用 statsmodels
和自定义函数进行双向逐步回归的示例。
5.2.1 使用 statsmodels
和自定义函数
import statsmodels.api as sm
import pandas as pd
import numpy as np
def stepwise_selection(X, y,
initial_list=[],
threshold_in=0.05,
threshold_out=0.05,
verbose=True):
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]
if not new_pval.empty:
best_pval = new_pval.min()
if best_pval < threshold_in:
best_feature = new_pval.idxmin()
included.append(best_feature)
changed=True
if verbose:
print(f'Add {best_feature} with p-value {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:
worst_feature = pvalues.idxmax()
included.remove(worst_feature)
changed=True
if verbose:
print(f'Remove {worst_feature} with p-value {worst_pval}')
if not changed:
break
return included
# 示例数据
data = sm.datasets.get_rdataset("mtcars").data
X = data.drop('mpg', axis=1)
y = data['mpg']
# 执行逐步回归
selected_features = stepwise_selection(X, y)
print('Selected features:', selected_features)
# 拟合最终模型
final_model = sm.OLS(y, sm.add_constant(data[selected_features])).fit()
print(final_model.summary())
说明:
stepwise_selection
函数通过逐步添加和删除自变量,根据设定的显著性阈值 (threshold_in
和threshold_out
) 选择最优特征组合。- 该函数首先尝试添加最显著的变量,然后检查是否有变量需要剔除。
- 迭代过程持续,直到没有变量需要添加或剔除。
5.2.2 使用 mlxtend
库
mlxtend
是一个扩展的机器学习库,提供了逐步回归的实现。
from mlxtend.feature_selection import SequentialFeatureSelector as SFS
from sklearn.linear_model import LinearRegression
# 准备数据
data = sm.datasets.get_rdataset("mtcars").data
X = data.drop('mpg', axis=1)
y = data['mpg']
# 定义模型
model = LinearRegression()
# 定义前向逐步选择
sfs_forward = SFS(model,
k_features='best',
forward=True,
floating=False,
scoring='neg_mean_squared_error',
cv=5)
# 执行特征选择
sfs_forward = sfs_forward.fit(X, y)
# 查看选择的特征
selected_features = list(sfs_forward.k_feature_names_)
print('Selected features:', selected_features)
# 拟合最终模型
final_model = sm.OLS(y, sm.add_constant(data[selected_features])).fit()
print(final_model.summary())
说明:
SequentialFeatureSelector
支持前向选择、后向剔除和双向逐步回归。k_features='best'
表示选择最佳特征数量(需自行定义停止条件)。scoring
参数定义了模型评估标准,此处使用负均方误差(MSE)。
6. 逐步回归的优缺点
6.1 优点
- 自动化特征选择:减少了手动选择特征的工作量和主观性。
- 提升模型解释性:通过剔除不显著的变量,使模型更加简洁易懂。
- 处理多重共线性:通过变量选择,有助于降低自变量之间的多重共线性。
- 适用性广:适用于多种类型的回归模型,如线性回归、逻辑回归等。
6.2 缺点
- 可能遗漏重要变量:若某些变量的联合效应较强但单独效应较弱,逐步回归可能会忽略这些变量。
- 过度依赖统计显著性:可能忽略变量的业务意义或实际影响,仅基于统计指标进行选择。
- 不稳定性:不同的数据样本可能导致不同的变量选择结果,尤其在自变量数量较多时。
- 计算复杂度:尤其在自变量数量较多时,逐步回归的计算量较大。
- 模型偏倚:逐步回归可能倾向于选择样本中表现最佳的变量,导致模型在新数据上的表现不稳定。
- 忽视交互作用:逐步回归通常只考虑主效应,可能忽略变量间的交互作用。
7. 逐步回归的实际应用示例
7.1 在 R 中的示例
# 加载数据集
data(mtcars)
# 拟合全模型(包含所有自变量)
full_model <- lm(mpg ~ ., data = mtcars)
# 拟合空模型(仅包含截距)
empty_model <- lm(mpg ~ 1, data = mtcars)
# 执行双向逐步回归
stepwise_model <- step(empty_model,
scope = list(lower = empty_model, upper = full_model),
direction = "both",
trace = TRUE)
# 查看最终模型摘要
summary(stepwise_model)
解释:
step()
函数执行逐步回归,direction = "both"
表示进行双向逐步回归。trace = TRUE
会在控制台显示逐步过程的详细信息。
7.2 在 Python 中的示例
import statsmodels.api as sm
import pandas as pd
import numpy as np
def stepwise_selection(X, y,
initial_list=[],
threshold_in=0.05,
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
"""
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]
if not new_pval.empty:
best_pval = new_pval.min()
if best_pval < threshold_in:
best_feature = new_pval.idxmin()
included.append(best_feature)
changed=True
if verbose:
print(f'Add {best_feature} with p-value {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:
worst_feature = pvalues.idxmax()
included.remove(worst_feature)
changed=True
if verbose:
print(f'Remove {worst_feature} with p-value {worst_pval}')
if not changed:
break
return included
# 示例数据
data = sm.datasets.get_rdataset("mtcars").data
X = data.drop('mpg', axis=1)
y = data['mpg']
# 执行逐步回归
selected_features = stepwise_selection(X, y)
print('Selected features:', selected_features)
# 拟合最终模型
final_model = sm.OLS(y, sm.add_constant(data[selected_features])).fit()
print(final_model.summary())
输出示例:
Add wt with p-value 0.00018729490779973134
Add qsec with p-value 0.011967073334409527
Add am with p-value 0.0021470933259534917
Selected features: ['wt', 'qsec', 'am']
OLS Regression Results
==============================================================================
Dep. Variable: mpg R-squared: 0.849
Model: OLS Adj. R-squared: 0.836
Method: Least Squares F-statistic: 69.25
Date: Fri, 27 Apr 2024 Prob (F-statistic): 3.55e-08
Time: 15:30:45 Log-Likelihood: -40.522
No. Observations: 32 AIC: 89.04
Df Residuals: 28 BIC: 93.51
Df Model: 3
Covariance Type: nonrobust
==============================================================================
coef std err t P>|t| [0.025 0.975]
------------------------------------------------------------------------------
const 19.7446 6.197 3.185 0.004 7.321 32.168
wt -3.9163 0.711 -5.507 0.000 -5.381 -2.451
qsec 1.2259 0.289 4.237 0.000 0.635 1.817
am 2.9358 1.410 2.080 0.046 0.001 5.871
==============================================================================
Omnibus: 0.574 Durbin-Watson: 2.256
Prob(Omnibus): 0.750 Jarque-Bera (JB): 0.532
Skew: -0.079 Prob(JB): 0.767
Kurtosis: 2.330 Cond. No. 4.62e+03
==============================================================================
解释:
- 逐步回归过程显示添加和移除变量的过程。
- 最终选择的特征为
wt
(车重)、qsec
(1/4英里加速时间)和am
(手动变速箱)。 - 模型的 R 2 R^2 R2 和调整后的 R 2 R^2 R2 较高,说明模型解释力强。
7.3 在 R 中使用 step()
函数的示例
# 加载数据集
data(mtcars)
# 拟合全模型(包含所有自变量)
full_model <- lm(mpg ~ ., data = mtcars)
# 拟合空模型(仅包含截距)
empty_model <- lm(mpg ~ 1, data = mtcars)
# 执行双向逐步回归
stepwise_model <- step(empty_model,
scope = list(lower = empty_model, upper = full_model),
direction = "both",
trace = TRUE)
# 查看最终模型摘要
summary(stepwise_model)
输出示例:
Start: AIC=120.27
mpg ~ 1
Step: AIC=120.27 -> AIC=116.98
mpg ~ wt
Step: AIC=116.98 -> AIC=113.81
mpg ~ wt + qsec
Step: AIC=113.81 -> AIC=112.89
mpg ~ wt + qsec + am
Step: AIC=112.89
mpg ~ wt + qsec + am
Call:
lm(formula = mpg ~ wt + qsec + am, data = mtcars)
Residuals:
Min 1Q Median 3Q Max
-2.5937 -1.6000 -0.1820 1.0500 2.6200
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 19.74460 6.19716 3.185 0.00413 **
wt -3.91630 0.71113 -5.507 3.55e-05 ***
qsec 1.22590 0.28907 4.237 0.00021 ***
am 2.93580 1.41030 2.080 0.04631 *
---
Signif. codes:
0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 2.015 on 28 degrees of freedom
Multiple R-squared: 0.849, Adjusted R-squared: 0.836
F-statistic: 69.25 on 3 and 28 DF, p-value: 3.551e-08
解释:
- 逐步回归过程逐步添加
wt
、qsec
和am
变量,最终停止。 - 最终模型的 R 2 R^2 R2 和调整后的 R 2 R^2 R2 显示模型具有很高的解释力。
8. 注意事项
8.1 过度拟合风险
尽管逐步回归旨在通过特征选择来提升模型性能,但若不加以控制,可能导致模型对训练数据过度拟合,影响在新数据上的泛化能力。建议结合交叉验证等方法,评估模型的稳定性和泛化性能。
8.2 多重共线性
逐步回归在处理多重共线性时可能表现不佳,尤其在自变量之间高度相关时,逐步过程可能随机选择其中一个变量而忽略其他重要变量。建议在进行逐步回归前,先进行多重共线性分析(如计算方差膨胀因子,VIF),并采取相应措施(如合并变量、使用正则化方法等)。
8.3 变量的业务意义
逐步回归主要基于统计显著性进行特征选择,可能会忽略变量的业务意义。即使某些变量在统计上不显著,但在业务上具有重要意义,仍需谨慎考虑其是否应被剔除。
8.4 不适用于所有模型类型
逐步回归主要适用于线性模型(如线性回归、逻辑回归),对于其他类型的模型(如决策树、随机森林、神经网络等),逐步回归并非最佳特征选择方法。
8.5 不稳定性
逐步回归的结果可能对数据集中的小变动敏感,尤其在自变量数量较多且样本量有限时。不同的训练集可能导致不同的特征选择结果,影响模型的一致性。
9. 替代方法
由于逐步回归存在一些局限性,许多替代方法被提出,以更有效地进行特征选择:
9.1 LASSO 回归(L1 正则化)
- 原理:在回归模型中引入 L1 正则化项,促使部分回归系数收缩为零,实现自动特征选择。
- 优点:
- 能处理高维数据和多重共线性。
- 更稳定和高效,尤其在变量数量较多时表现优异。
- 缺点:
- 需要选择正则化参数(如通过交叉验证)。
- 对于高度相关的变量,可能随机选择其中一个而非全部。
9.2 岭回归(Ridge Regression,L2 正则化)
- 原理:在回归模型中引入 L2 正则化项,促使回归系数收缩,但不至于完全为零。
- 用途:主要用于处理多重共线性问题,而非特征选择。
9.3 弹性网络(Elastic Net)
- 原理:结合了 LASSO 和岭回归的正则化方法,既能实现特征选择,又能处理多重共线性。
- 优点:
- 同时具备 L1 和 L2 正则化的优点。
- 在处理相关变量时表现更佳。
9.4 基于树的特征选择
- 方法:使用决策树、随机森林、梯度提升树等模型的特征重要性指标进行特征选择。
- 优点:
- 能捕捉变量间复杂的非线性关系和交互作用。
- 适用于各种数据类型。
- 缺点:
- 特征重要性可能不稳定,尤其在变量相关性高时。
9.5 递归特征消除(Recursive Feature Elimination, RFE)
- 原理:递归地构建模型,并在每次迭代中移除最不重要的特征,直到达到预定的特征数量。
- 优点:
- 系统地评估特征的重要性。
- 适用于多种模型类型。
- 缺点:
- 计算成本较高,尤其在特征数量较多时。
10. 小结
逐步回归(Stepwise Regression) 是一种用于特征选择的经典方法,通过逐步添加或删除自变量,优化模型的某种性能指标(如AIC、BIC、p值等)。它在处理多重共线性、提升模型解释性和防止过拟合方面具有一定的优势。然而,逐步回归也存在一些局限,如可能遗漏重要变量、过度依赖统计显著性、结果不稳定等。因此,在实际应用中,建议结合其他特征选择方法(如正则化方法、基于树的选择、递归特征消除等)和业务知识,综合评估和选择最优模型。
通过理解逐步回归的原理、方法及其优缺点,可以在构建回归模型时更有效地进行特征选择,提升模型的性能和解释力。