当你第一次接触线性回归时,可能会觉得它太简单了——用一条直线来拟合数据,这在很多真实场景中显然不够用。比如预测房价时,面积和价格的关系往往不是简单的线性增长,而是随着面积增大,单价可能会逐渐降低。这时候就需要多项式回归来捕捉这种非线性关系。
我刚开始做数据分析时就踩过这个坑。当时用线性回归预测用户活跃度,模型在训练集上表现很差。后来把特征做了二次项转换,R2分数立刻提升了30%。这种从直线到曲线的飞跃,就是多项式回归的核心价值。
多项式回归的本质,是通过增加特征的高次项(比如x²、x³),让线性模型具备拟合非线性数据的能力。它巧妙之处在于:虽然拟合的是曲线,但本质上仍然是线性模型,因为方程对参数w而言是线性的。这意味着我们依然可以使用最小二乘法等线性回归的成熟解法。
假设原始特征矩阵X是n×m维(n个样本,m个特征),经过PolynomialFeatures转换后会变成什么样子?以degree=2为例:
原始特征:[a, b]
转换后:[1, a, b, a², ab, b²]
这个转换过程可以用张量积来解释。当include_bias=True时,系统会自动添加全1列(对应截距项)。转换后的矩阵可以表示为:
code复制[1, X, X⊗X]
其中⊗表示克罗内克积。这个操作实际上是将特征空间映射到了更高维的希尔伯特空间。我在处理传感器数据时发现,当原始特征有强交互效应时,这种映射能显著提升模型表现。
多项式回归的解可以通过正规方程获得:
w = (XᵀX)⁻¹Xᵀy
这个公式的推导其实非常直观。我们从最小化损失函数出发:
L(w) = ||Xw - y||²
对w求导并令导数为零:
2Xᵀ(Xw - y) = 0
=> XᵀXw = Xᵀy
当XᵀX可逆时,直接解得:
w = (XᵀX)⁻¹Xᵀy
这个解在数学上被称为最小二乘估计量(BLUE)。我在金融风控项目中验证过,当特征维度<1000时,用正规方程求解比梯度下降更快更稳定。
degree参数控制多项式次数,但实践中不是越大越好。我曾用波士顿房价数据做过实验:
这是因为高次项容易导致过拟合。建议从2或3开始尝试,配合交叉验证选择最优值。
interaction_only参数特别适合特征间存在物理交互的场景。比如预测化学反应速率时,设置interaction_only=True可以只保留温度×浓度这样的交叉项,避免出现温度²这种不合理的项。
include_bias=False在以下情况很有用:
多项式特征可能导致数值爆炸。我遇到过特征值在10³量级时,五次项就到10¹⁵了,这会让模型训练变得不稳定。解决方法有:
python复制from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
pipe = make_pipeline(
StandardScaler(),
PolynomialFeatures(degree=3),
Ridge(alpha=0.1)
)
不是所有的高次项都有用。可以用以下方法筛选:
python复制from sklearn.feature_selection import RFE
selector = RFE(estimator=LinearRegression(), n_features_to_select=5)
selector.fit(X_poly, y)
print(selector.support_)
推荐使用TimeSeriesSplit处理时间序列数据,用GroupKFold处理分组数据。我在电商预测项目中这样设置:
python复制from sklearn.model_selection import TimeSeriesSplit
tscv = TimeSeriesSplit(n_splits=5)
scores = cross_val_score(model, X, y, cv=tscv, scoring='neg_mean_squared_error')
当数据存在复杂非线性时,可以比较:
在我的实验中发现:对于光滑连续的函数关系,多项式回归计算效率最高;但对于存在突变或分段关系的数据,树模型表现更好。
警告信号包括:
解决方法:
高次特征间往往高度相关。可以通过:
python复制from statsmodels.stats.outliers_influence import variance_inflation_factor
vif = [variance_inflation_factor(X_poly, i) for i in range(X_poly.shape[1])]
当特征维度很高时:
去年我用多项式回归构建了一个简单的股价预测模型。关键步骤:
python复制window_size = 60
for i in range(len(X)-window_size):
X_window = X[i:i+window_size]
y_window = y[i:i+window_size]
model = make_pipeline(
PolynomialFeatures(degree=2),
StandardScaler(),
Lasso(alpha=0.01)
)
model.fit(X_window, y_window)
# 预测下一天价格
这个简单模型在平稳市场环境下能达到68%的日涨跌预测准确率。当然,实际金融建模要复杂得多,但多项式回归作为baseline非常合适。