为什么在添加多项式特征时会降低 r 平方?

数据挖掘 scikit-学习 预测建模 线性回归
2022-03-03 16:21:44

我正在尝试f(x) = ?为一组随机的x,y坐标找到最佳拟合线。

具有多项式特征的线性回归适用于大约 10 种不同的多项式,但超过 10 的 r 平方实际上开始下降!

如果新特征对线性回归没有用,我会假设它们的系数为 0,因此添加特征不应损害整体 r 平方。

在创建大量交互特征时,我在房价预测时重现了这个问题。

我的python代码如下:

创建随机数据

import numpy as np
import matplotlib.pyplot as plt


def pol(x):
    return x * np.cos(x)

x = np.linspace(0, 12, 100)
rng = np.random.RandomState(1234)
rng.shuffle(x)
x = np.sort(x[:25])
y = pol(x) + np.random.randn(25)*2


plt.scatter(x, y, color='green', s=50, marker='.')

plt.show()

回归并检查每个 R 平方

from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import PolynomialFeatures

for p in range(1,30):
    plot_range = [i/10 for i in range(0,120)]
    poly = PolynomialFeatures(p)
    X_fin = poly.fit_transform([[samp] for samp in x])
    X_fin_plot = poly.fit_transform([[samp] for samp in plot_range])
    reg = LinearRegression().fit(X_fin, y)

    from sklearn.metrics import mean_squared_error, r2_score
    print(p,r2_score(y, reg.predict(X_fin)))

显示最后的回归线

plt.scatter(x, y, color='green', s=50, marker='.')
plt.plot(plot_range,reg.predict(X_fin_plot))
plt.show()

我也有两个情节要比较。第一个是 10 个多项式特征,第二个是 40 个。注意第二个是如何错过了第一个点的大部分。 在此处输入图像描述

在此处输入图像描述

2个回答

我原来的答案不正确,所以这里是一个更正的答案:

当您使用 时PolynomialFeatures(),您不会得到预期的多项式。相反,你得到多项式加上一个交互项:

from sklearn.preprocessing import PolynomialFeatures import numpy as 
np    z = np.array([[0, 1],
                    [2, 3],
                    [4, 5]]) 
poly = PolynomialFeatures(2)
print(poly.fit_transform(z))

输出是:

[[ 1.  0.  1.  0.  0.  1.]
 [ 1.  2.  3.  4.  6.  9.]
 [ 1.  4.  5. 16. 20. 25.]]

原始多项式应如下所示:

new_z = np.hstack((z**(i+1) for i in range(2)))
print(new_z)

输出是:

[[ 0  1  0  1]
 [ 2  3  4  9]
 [ 4  5 16 25]]

这是原始多项式问题的快速 R 实现:

x = c(0.12121212, 1.09090909, 3.27272727, 3.51515152, 4, 4.24242424,
  4.72727273, 4.84848485, 5.09090909, 6.18181818, 6.78787879, 7.15151515,
  7.39393939, 7.63636364, 8.24242424, 8.60606061, 9.09090909, 9.81818182,
  9.93939394, 10.3030303, 10.54545455, 10.66666667, 11.39393939, 11.63636364,
  11.87878788)

y = c(-2.87011136,1.77132943,-1.23698978,-3.09768628,-2.11919042,-4.11234626,
  -1.1684339, 1.34601699, -2.37623758,4.20290438, 6.16349341, 3.60661197,
  2.58898819, 3.80785471, -2.96359566, -5.672873, -9.71694313, -7.62778351,
  -8.95730409, -8.04664475, -5.18464423, -6.54562138, 3.45527603, 6.11936457,
  9.30106747)

regdata = data.frame(x,y)
colnames(regdata) <- c("x","y")

r2list = list()
r2adjlist = list()
plist = list()

for (p in seq(1:29)){
  reg = lm(y~poly(x,p, raw=T), data=regdata)
  print(paste0("Poly: ", p))
  print(paste0("  R2      ", summary(reg)$r.squared))
  print(paste0("  R2_adj. ", summary(reg)$adj.r.squared))
  r2list[[p]] <-  summary(reg)$r.squared
  r2adjlist[[p]] <- summary(reg)$adj.r.squared
  plist[[p]] <- p
}

plot(plist, r2list,xlab="Polynomial", ylab="R2")
lines(plist, r2list)

取决于多项式次数的 R2 如下所示: 在此处输入图像描述

所以你最初的直觉(当然)是正确的,但你对数据的处理是不正确的。

你有 25 分,所以有一个完美的 24 次拟合多项式。这不会发生,所以 OLS 求解器出现了问题,但我不确定究竟是什么或如何检测到它。不过,当你变大时可能会遇到数值问题,这并不奇怪p:你的 x 值接近 0.1,而其他的 x 值超过 10;将它们提高到 24 次方会使它们相距很远,并且可能会产生比 python 保留的更多有效数字。

我已经做了一个演示:
https
://github.com/bmreiniger/datascience.stackexchange/blob/master/53818.ipynb 缩放 x 值有帮助,尽管我们仍然没有找到视觉上匹配完美多项式拟合的东西.

另请参阅https://stats.stackexchange.com/questions/350130/why-is-gradient-descent-so-bad-at-optimizing-polynomial-regression