Python实现前向逐步回归(stepwise)

93ca31520210821e1ae6324dc59cfbf7.png

来源:我不爱机器学习
本文约1200字,建议阅读5分钟
本文为你介绍用statsmodels写的向前逐步回归的工具。


Python的statsmodels包含了一些R风格的统计模型和工具。在内部实现上,statsmodels使用patsy包将数据转化为矩阵并建立线性模型,具体信息参见pasty主页http://patsy.readthedocs.io/en/latest/overview.html。

但是,Python的statsmodels工具中没有向前逐步回归算法。逐步回归的基本思想是将变量逐个引入模型,每引入一个解释变量后都要进行F检验,并对已经选入的解释变量逐个进行t检验,当原来引入的解释变量由于后面解释变量的引入变得不再显著时,则将其删除。以确保每次引入新的变量之前回归方程中只包含显著性变量。

这是一个反复的过程,直到既没有显著的解释变量选入回归方程,也没有不显著的解释变量从回归方程中剔除为止。以保证最后所得到的解释变量集是最优的(https://baike.baidu.com/item/%E9%80%90%E6%AD%A5%E5%9B%9E%E5%BD%92/585832?fr=aladdin)。

网上有人用statsmodels写了一个向前逐步回归的工具,具体网址见https://planspace.org/20150423-forward_selection_with_statsmodels/。我试了一下,速度还不错,比我用sklearn写的要好。具体代码如下:

import statsmodels.formula.api as smf
import pandas as pd
 
def forward_selected(data, response):
    """前向逐步回归算法,源代码来自https://planspace.org/20150423-forward_selection_with_statsmodels/
    使用Adjusted R-squared来评判新加的参数是否提高回归中的统计显著性
    Linear model designed by forward selection.
    Parameters:
    -----------
    data : pandas DataFrame with all possible predictors and response
    response: string, name of response column in data
    Returns:
    --------
    model: an "optimal" fitted statsmodels linear model
           with an intercept
           selected by forward selection
           evaluated by adjusted R-squared
    """
    remaining = set(data.columns)
    remaining.remove(response)
    selected = []
    current_score, best_new_score = 0.0, 0.0
    while remaining and current_score == best_new_score:
        scores_with_candidates = []
        for candidate in remaining:
            formula = "{} ~ {} + 1".format(response,
                                           ' + '.join(selected + [candidate]))
            score = smf.ols(formula, data).fit().rsquared_adj
            scores_with_candidates.append((score, candidate))
        scores_with_candidates.sort()
        best_new_score, best_candidate = scores_with_candidates.pop()
        if current_score < best_new_score:
            remaining.remove(best_candidate)
            selected.append(best_candidate)
            current_score = best_new_score
    formula = "{} ~ {} + 1".format(response,
                                   ' + '.join(selected))
    model = smf.ols(formula, data).fit()
 
    return model
 
 
def main():
 
    '''
    首先从网上读取普林斯顿大学52位员工的工资信息,工资文件一共有6列,各列意义解释如下:
    sx = Sex, coded 1 for female and 0 for male
    rk = Rank, coded
        1 for assistant professor,
        2 for associate professor, and
        3 for full professor
    yr = Number of years in current rank
    dg = Highest degree, coded 1 if doctorate, 0 if masters
    yd = Number of years since highest degree was earned
    sl = Academic year salary, in dollars.
    '''
    url = "http://data.princeton.edu/wws509/datasets/salary.dat"
    data = pd.read_csv(url, sep='\\s+')
 
    #将sl(年收入)设为目标变量
    model = forward_selected(data, 'sl')
 
    #打印出最后的回归模型
    print(model.model.formula)
    # sl ~ rk + yr + 1
    print(model.params)
    # Intercept          16203.268154
    # rk[T.associate]     4262.284707
    # rk[T.full]          9454.523248
    # yr                   375.695643
    # dtype: float64
    # 0.835190760538
 
    print(model.rsquared_adj)
    # 0.835190760538
 
if __name__ == '__main__':
    main()

最好,该方法也有缺点。随着模型中参数增多,Adjusted R-squared的增加不太明显,所以后来加的很多参数对模型的影响不大。

下面是在我自己的数据集(包含98个参数)上做的测试图,我们看到,当参数个数多于7个时,再增加参数,模型的R2并不能显著增加,所以最终模型取前7个参数即可。

c132126d1895f8e199ff51cb6b0ce021.png                       

作者:carlwu

链接:https://blog.youkuaiyun.com/carlwu/article/details/80017560

编辑:黄继彦

371df7370301c5b4d74b56c6fd33f5e5.png

以下是一个使用Python实现向后逐步回归算法的示例代码: ```python import numpy as np from sklearn.linear_model import LinearRegression def backward_stepwise_regression(X, y, n_features): # X为特征矩阵,y为目标向量,n_features为要选择的特征数 # 假设X和y已经进行了预处理,如标准化、缺失值填充等 # 构造初始特征集合 remaining_features = set(range(X.shape[1])) selected_features = [] # 训练基准模型,并计算性能指标 model = LinearRegression() model.fit(X, y) mse = np.mean((model.predict(X) - y) ** 2) r2 = model.score(X, y) # 迭代选择特征 while len(selected_features) < n_features: # 计算每个特征的性能指标 candidate_mses = [] candidate_r2s = [] for feature in remaining_features: features = selected_features + [feature] model.fit(X[:, features], y) candidate_mse = np.mean((model.predict(X[:, features]) - y) ** 2) candidate_r2 = model.score(X[:, features], y) candidate_mses.append(candidate_mse) candidate_r2s.append(candidate_r2) # 选择性能指标最优的特征 best_idx = np.argmin(candidate_mses) selected_features.append(remaining_features.pop(best_idx)) mse = candidate_mses[best_idx] r2 = candidate_r2s[best_idx] # 训练最终模型,并返回结果 model.fit(X[:, selected_features], y) return model, selected_features, mse, r2 ``` 在以上示例代码中,我们使用了Scikit-learn库中的LinearRegression类来训练线性回归模型,并计算了MSE和R平方作为性能指标。在每次迭代中,我们计算了每个特征加入后的性能指标,并选择了性能指标最优的特征加入到已选特征集合中。最终,我们使用已选特征训练最终模型,并返回结果。 使用示例代码可以这样调用: ```python # 生成随机特征矩阵和目标向量 X = np.random.rand(100, 10) y = np.random.rand(100) # 调用向后逐步回归算法 model, selected_features, mse, r2 = backward_stepwise_regression(X, y, n_features=5) # 输出结果 print('Selected Features:', selected_features) print('MSE:', mse) print('R2:', r2) ``` 以上代码将随机生成一个10个特征的特征矩阵和目标向量,并使用向后逐步回归算法选择5个最优特征,并训练最终模型,并输出结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值