·
一、综述
回归分析是一种统计学习方法,用于研究 自变量(X)与因变量(Y)之间的关系。
找一个函数 f(X) 最好地拟合真实值 Y,通常表示为:Y=f(X)+ϵ。其中 ϵ 是噪声。
包括:
线性回归(Linear Regression)
逻辑回归(Logistic regressions)
多项式回归(Polynomial Regression)
逐步回归(Step Regression)
岭回归(Ridge Regression)
套索回归(Lasso Regression)
弹性网回归(ElasticNet)
二、线性回归
假设因变量与自变量之间是线性关系,通常采用 最小二乘法(OLS)
特点
- 实现简单,可解释性强
- 对异常值敏感
- 不适用于非线性问题
实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| from sklearn.linear_model import LinearRegression model = LinearRegression() model.fit(X, y) ''' LinearRegression()所创建的对象包含: .fit():训练模型 .predict():预测 .coef_:系数 .intercept_:截距 (默认参数:fit_intercept=True, copy_X=True, n_jobs=None, positive=False) fit(X, y)中的X是特征矩阵,y是目标变量,也就是分别存放y=a+bx1+cx2+...中的x和y 最终,我们可以得到: model.coef_ 各特征的 β1, β2, ... βp model.intercept_ 截距 β0 '''
|
三、逻辑回归
用于 分类问题。通过线性组合输入变量,然后用 Sigmoid 函数 转换为概率:
$$
p = \frac{1}{1 + e^{-(\beta_0 + \beta x)}}
$$
分类依据:
p>0.5 → 类别 1;
p<=0.5 → 类别 0
在python库中使用了LBFGS算法作为计算参数时的优化
【LBFGS算法:BFGS 用一种近似的方式去“模拟”海森矩阵的逆,从而加速优化。而LBFGS算法即Limited-memory BFGS,是 BFGS 的改良版,它不保存完整的海森矩阵(太大),只保存少量历史梯度信息,这样既快、又省内存,适合高维数据优化(本人尝试了解了下BFGS算法的推导,了解后觉得…怎么证明的呢,数学的脑洞真非人吧…算了线代渣渣还是老老实实直接用吧,何必和自己过不去呢)】
特点
实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| from sklearn.linear_model import LogisticRegression model = LogisticRegression() model.fit(X, y) ''' 默认参数包括: penalty='l2', # 正则化方式 dual=False, tol=1e-4, # 收敛精度阈值 C=1.0, # 正则化强度(1/λ) fit_intercept=True, # 是否学习截距项 intercept_scaling=1, class_weight=None, # 类别权重(处理不平衡样本) random_state=None, solver='lbfgs', # 优化器(默认 LBFGS) max_iter=100, # 最大迭代次数 multi_class='auto', # 自动选择 one-vs-rest 或 multinomial n_jobs=None, # 并行 CPU 核数 l1_ratio=None # 弹性网正则(ElasticNet) '''
|
四、多项式回归
通过对特征做 多项式扩展 来拟合非线性关系。例如二次模型。
特点
- 本质上还是“线性回归”
- 能拟合非线性关系
- 特征是“人为构造”的
- 容易过拟合,泛化性差
- 特征数量增长很快
实现
1 2 3 4 5 6 7 8 9
| from sklearn.preprocessing import PolynomialFeatures from sklearn.linear_model import LinearRegression
poly = PolynomialFeatures(degree=2) X_poly = poly.fit_transform(X) ''' 本处实现参数扩展,再进行拟合,参数扩展过程见详细实现代码 ''' model = LinearRegression().fit(X_poly, y)
|
详细实现代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| import numpy as np from sklearn.preprocessing import PolynomialFeatures from sklearn.linear_model import LinearRegression
X = np.array([[1], [2], [3], [4], [5]])
y = np.array([1.2, 1.9, 3.2, 3.9, 5.1])
poly = PolynomialFeatures(degree=2, include_bias=True) X_poly = poly.fit_transform(X)
print("原始 X:") print(X) print("多项式扩展后的 X_poly:") print(X_poly)
model = LinearRegression() model.fit(X_poly, y)
print("coef_(权重):", model.coef_) print("intercept_(截距):", model.intercept_)
x_new = np.array([[6]]) x_new_poly = poly.transform(x_new) y_pred = model.predict(x_new_poly) print("x=6 时的预测值:", y_pred)
|
五、逐步回归
自动筛选特征:逐步加入或删除自变量。
包括:前向选择(从无到有加入变量)后向剔除(从全到少删除变量)逐步回归(两者结合)
特点
自动特征选择
提升模型简洁性
可能陷入局部最优
计算量较大
实现
这个算法在Sklearn 无直接实现,可通过 statsmodels 或自定义迭代 p-value。
常用指标:
1、AIC
公式:AIC=2k−2ln(L),
k:模型中参数个数(包括截距)
L:模型的最大似然
在逐步回归中,常用“AIC 最小”作为选择标准,寻找一个模型尽可能简单(k尽可能小)与拟合效果尽可能好(L尽可能大)的模型。
2、BIC
公式:BIC=ln(n)k−2ln(L)
k:模型中参数个数(包括截距)
L:模型的最大似然
n:样本数量
相比于AIC,BIC 更偏向“模型简单”,更“保守”,用途与AIC类似,更适合用于担心过拟合的场景内。
3、p-value
系数的显著性检验。算得的结果表示在“变量其实没用(βj=0\beta_j = 0βj=0)”这个前提下,得到当前这么极端的估计结果的概率有多大
一般p<0.05时,认为该参数是有用的。
4、Adjusted R²
调整后的 R² ,公式:
$$
\bar{R}^2 = 1 - \frac{\text{RSS}/(n - k - 1)}{\text{TSS}/(n - 1)}
$$
n:样本数量
k:模型中参数个数(包括截距)
它对自由度做了修正:
- 加入没用变量时,R可能下降
- 加入有用变量时,R才会上升
Adjusted R² 越大越好,同时考虑了拟合效果和复杂度。
实现范例:
前向逐步回归,基于 p-value(同理也可以写成基于AIC、BIC、Adjusted R²版本)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| import statsmodels.api as sm import pandas as pd
def forward_stepwise_selection(X, y, significance_level=0.05, verbose=True): """ 基于 p-value 的前向逐步回归选择变量 X: DataFrame,自变量 y: Series 或 1D array,因变量 significance_level: 进入模型的显著性水平阈值 """ remaining_vars = list(X.columns) selected_vars = [] current_score = float('inf') best_new_score = float('inf')
while remaining_vars: scores_with_candidates = []
for candidate in remaining_vars: formula_vars = selected_vars + [candidate] X_candidate = sm.add_constant(X[formula_vars]) model = sm.OLS(y, X_candidate).fit()
candidate_pvalue = model.pvalues[candidate] scores_with_candidates.append( (model.aic, candidate, candidate_pvalue) )
scores_with_candidates.sort(key=lambda x: x[0]) best_new_score, best_candidate, best_pvalue = scores_with_candidates[0]
if verbose: print(f"尝试加入变量: {best_candidate}, AIC={best_new_score:.3f}, p-value={best_pvalue:.4f}")
if best_pvalue < significance_level and best_new_score < current_score: remaining_vars.remove(best_candidate) selected_vars.append(best_candidate) current_score = best_new_score if verbose: print(f"加入变量: {best_candidate}") else: if verbose: print("没有更多显著变量可加入,停止选择。") break
X_selected = sm.add_constant(X[selected_vars]) final_model = sm.OLS(y, X_selected).fit() return final_model, selected_vars
|
使用:
1 2 3 4 5 6 7 8 9 10 11
|
y = df['y'] X = df.drop(columns=['y'])
final_model, selected_vars = forward_stepwise_selection(X, y, significance_level=0.05)
print("\n最终选择的变量:", selected_vars) print(final_model.summary())
|
summary() 里可以看到:每个变量的 系数、标准误差、t 值、p-value以及模型整体的 R²、Adjusted R²、AIC、BIC
六、 岭回归
在线性回归的损失中加入 L2 正则项,防止过拟合。
公式:
$$
\min_{\beta} \left[ \sum (y_i - \hat{y_i})^2 + \lambda \sum \beta_j^2 \right]
$$
其中 λ 控制惩罚力度。
特点
实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| from sklearn.linear_model import Ridge model = Ridge(alpha=1.0) ''' 默认参数: alpha=1.0, *, fit_intercept=True, copy_X=True, max_iter=None, tol=1e-4, solver='auto',(Scikit-Learn 会根据 X 的大小与稀疏性自动选择最适合的 solver,等价于:稠密的小数据 → 'svd' 或 'cholesky;'稀疏矩阵 → 'sparse_cg';大规模高维数据 → 'sag' 或 'saga') positive=False, random_state=None ''' model.fit(X, y)
|
七、套索回归
损失加入 L1 正则项
公式:
$$
\min_{\beta} \left[ \sum (y_i - \hat{y_i})^2 + \lambda \sum \beta_j^2 \right]
$$
其中 λ 控制惩罚力度。
特点
- 可以把部分系数变为 0(实现特征选择)
- 更稀疏的模型
- 对共线性敏感
【与岭回归区别:
Ridge(L2):
- 会让相关特征共同分担权重(共享系数)
- 稳定性极强
- 常用于存在强共线性的数据
- 正则约束的结果是一个“圆形”
Lasso(L1):
- 会“二选一”地删除部分相关特征
- 对多重共线性可能不稳定
- 当特征之间高度相似时,Lasso 的选择会有随机性
- 正则约束的结果是一个方形,结果更易落在角上,导致出现0
总结:
岭回归(Ridge):把所有特征的系数都缩小 → 防止过拟合,多用于特征高度相关(多重共线性问题)、特征都可能有用(不希望删除任何特征)、噪声不大,样本量多的场景
套索回归(Lasso):把不重要的特征的系数直接压成 0 → 自动特征选择,多用于特征数量很多(尤其是大于样本数)、希望让模型自动筛选特征、特征中可能有很多无效变量的场景】
实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| from sklearn.linear_model import Lasso model = Lasso(alpha=0.1) ''' 默认参数: alpha=1.0,(这里改为了0.1) *, fit_intercept=True, copy_X=True, max_iter=1000, tol=1e-4, warm_start=False, positive=False, random_state=None, selection='cyclic' ''' model.fit(X, y)
|
八、弹性网回归
结合 L1(Lasso)和 L2(Ridge)
公式:
$$
\min_{\beta} \Big( \sum (y-\hat{y})^2 + \lambda_1 \sum |\beta_j| + \lambda_2 \sum \beta_j^2 \Big)
$$
特点
- 既能选择特征(L1)
- 又能处理共线性(L2)
- 适用于高维数据(p > n)
实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| from sklearn.linear_model import ElasticNet model = ElasticNet(alpha=1.0, l1_ratio=0.5) ''' 默认参数: alpha=1.0, l1_ratio=0.5,(这个参数设置为1.0是纯Lasso,设置为0是纯Ridge,设置为0.2-0.8则是典型的ElasticNet,即弹性网) *, fit_intercept=True, copy_X=True, max_iter=1000, tol=1e-4, warm_start=False, positive=False, random_state=None, selection='cyclic' ''' model.fit(X, y)
|
九、总结
| 方法 |
是否线性 |
是否支持非线性 |
是否正则化 |
特征选择 |
典型用途 |
| 线性回归 |
✔ |
✘ |
✘ |
✘ |
基本预测 |
| 逻辑回归 |
✔ |
✘ |
L2为主 |
✘ |
分类 |
| 多项式回归 |
✔ |
✔(通过特征扩展) |
✘ |
✘ |
非线性关系 |
| 逐步回归 |
✔ |
✔ |
✘ |
✔ |
自动变量筛选 |
| 岭回归 |
✔ |
✘ |
L2 |
✘ |
多重共线性 |
| 套索回归 |
✔ |
✘ |
L1 |
✔ |
稀疏模型 |
| 弹性网 |
✔ |
✘ |
L1+L2 |
✔ |
高维数据 |