Python中用标准化回归系数筛选重要预测变量的技术咨询
回归模型特征重要性评估相关问题解答
Minitab官方博客文章明确指出,不建议使用常规未标准化的回归系数或p值判断变量/特征重要性,标准化回归系数、R²变化量是更可靠的评估依据。
早年社区流传的标准化系数statsmodels实现代码如下:
import statsmodels.api as sm from scipy.stats.mstats import zscore print(sm.OLS(zscore(y), zscore(x)).fit().summary())
测试复现结果
测试1:未标准化输入的Lasso模型输出
lasso_model = Lasso(alpha = 0.01) selected_columns = list(X.columns) lasso_model.fit(X, y) list(zip(selected_columns, lasso_model.coef_))
输出结果:
[('AGE', -0.00013116073118093452), ('DISTANCE', 2.2924058071269675e-05), ('TOTDELAY', -0.0002569583237660659), ('STD/STA', -0.01334152988447677), ('WEBRSVN', -0.020335870566292973), ('WEBCI', 0.08571155146491262), ('AIRPTCI', 0.0327097907845398)...]
测试2:zscore标准化输入的OLS模型输出
import statsmodels.api as sm from scipy.stats.mstats import zscore sm.OLS(zscore(y), zscore(X)).fit().summary()
输出结果:
coef std err t P>|t| [0.025 0.975] AGE -0.0297 0.002 -14.843 0.000 -0.034 -0.026 DISTANCE -0.0005 0.003 -0.181 0.856 -0.006 0.005 TOTDELAY -0.0391 0.002 -20.945 0.000 -0.043 -0.035 STD/STA -0.0528 0.002 -22.003 0.000 -0.058 -0.048 WEBRSVN -0.1155 0.003 -37.834 0.000 -0.121 -0.110 WEBCI 0.2147 0.003 81.803 0.000 0.210 0.220 AIRPTCI 0.0958 0.002 46.530 0.000 0.092 0.100 ...
核心问题解答
1. 2015年社区的标准化系数计算方法是否正确?现有生态有没有更规范的实现?标准化系数计算时机怎么选?
- 方法正确性:这个zscore标准化后跑OLS取系数的写法核心逻辑是对的,但有两个细节要注意:一是
scipy.stats.mstats.zscore默认按样本标准差(除以n-1)做转换,和统计教材里标准化回归系数的定义完全匹配,唯一的问题是如果数据有缺失值,这个版本会自动跳过缺失值计算,普通场景用没问题;二是写法里没给OLS加常数项,这其实不算错——因为标准化后自变量和因变量的均值都是0,常数项算出来必然是0,加不加都不影响斜率系数的结果。 - 现有官方实现:现在不用自己手写zscore了,两个常用稳定方案:
- statsmodels拟合OLS时,只要输入是标准化后的特征和标签,
fit().params直接输出标准化系数,搭配StandardScaler做转换可以避免scipy zscore的版本兼容问题; - scikit-learn的线性模型只要在Pipeline里前置
StandardScaler,拟合后输出的coef_就是标准化系数,不需要额外手动计算。
- statsmodels拟合OLS时,只要输入是标准化后的特征和标签,
- 计算时机:标准化系数没有强制要求必须在模型选择前一次性算完,完全支持迭代计算——不管是做特征筛选、逐步回归、正则化调参,每一轮迭代只要保证当前入模的所有特征和因变量,都用全量训练集拟合的同一份标准化规则转换,计算出来的系数就可以横向对比。绝对不能每轮迭代单独对当前特征子集做标准化,否则系数尺度不一致,对比没有意义。
2. 标准化系数判断特征重要性的阈值怎么定?所有系数绝对值都小于0.3代表什么?
- 首先说死:行业内根本没有通用的固定阈值来划分“重要特征”和“非重要特征”。标准化系数的绝对值本质含义是「其他变量保持不变时,这个特征每变1个标准差,因变量会跟着变多少个标准差」,数值大小完全和场景、数据质量绑定:工程、理化实验这类噪声极低的场景,重要特征的系数可能到0.5甚至0.8以上;但用户行为、社科类这类噪声大、影响因素杂的场景,系数能到0.1就算是业务价值很高的特征了。网上传的0.3阈值只是部分社科教材里提的“中等效应”参考值,完全不能当通用筛选规则用。
- 你这次测出来所有系数绝对值都没到0.3是非常正常的结果,一般对应三种情况:
- 你做的就是用户行为/社科类场景,本来就不存在能单点强影响结果的特征,单个特征的独立解释力本来就弱;
- 选的特征之间有多重共线性,单个特征的解释力被其他相关特征拆分了,这时候光看标准化系数会低估特征的实际作用,得结合共线性检验、R²变化量一起判断;
- 你用的Lasso正则化强度设高了,大系数被正则项压小了,这时候的系数不能直接和无正则的OLS系数比大小。
3. 标准化后训练Lasso能不能直接用系数判断重要性?StandardScaler()是不是对应标准化工具?
- 只要流程对:只在训练集上拟合StandardScaler的转换规则,用同一个规则转训练/验证/测试集,且Lasso的alpha参数是通过交叉验证选出来的最优值,那模型输出的
coef_绝对值完全可以直接用来比特征重要性,甚至比无正则OLS的标准化系数更靠谱——毕竟Lasso本身就能缓解多重共线性带来的系数不稳定问题。这里最容易踩的坑是别拿全量数据去拟合scaler再做交叉验证,那会造成数据泄露,算出来的系数是偏的。 StandardScaler()就是干这个z-score标准化活的官方工具,它做的转换就是(x - 特征均值)/特征样本标准差,和你之前手动调zscore的逻辑完全一致,还支持Pipeline封装、异常值兼容,比手动调scipy的zscore更适合正式建模流程。
对应的无数据泄露实现示例:
from sklearn.preprocessing import StandardScaler from sklearn.linear_model import Lasso from sklearn.pipeline import make_pipeline # 用Pipeline把标准化和模型封装在一起,交叉验证时不会泄露数据 lasso_pipe = make_pipeline( StandardScaler(), Lasso(alpha=0.01) ) lasso_pipe.fit(X_train, y_train) # 输出的就是标准化后的系数,可以直接对比绝对值判断重要性 list(zip(X.columns, lasso_pipe.named_steps['lasso'].coef_))
提个醒:如果特征之间强共线性很严重,不管是标准化系数还是Lasso系数,都可能出现重要性排序乱跳的问题,这时候搭配置换重要性、R²变化量(就是逐个打乱特征值看模型效果掉多少)做交叉验证,出来的重要性结论会稳很多。
内容的提问来源于stack exchange,提问作者Edison
相关产品推荐
相关产品推荐

