PolynomialFeatures 和 LinearRegression 返回不理想的系数

3
import os
import pandas as pd
import matplotlib.pyplot as plt

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

csv_path = os.path.join('', 'graph.csv')
graph = pd.read_csv(csv_path)

y = graph['y'].copy()
x = graph.drop('y', axis=1)

pipeline = Pipeline([('pf', PolynomialFeatures(2)), ('clf', LinearRegression())])
pipeline.fit(x, y)

predict = [[16], [20], [30]]

plt.plot(x, y, '.', color='blue')
plt.plot(x, pipeline.predict(x), '-', color='black')
plt.plot(predict, pipeline.predict(predict), 'o', color='red')
plt.show()

我的图表.csv:

x,y
1,1
2,2
3,3
4,4
5,5
6,5.5
7,6
8,6.25
9,6.4
10,6.6
11,6.8

产生的结果如下:

输入图像描述

显然,它产生了错误的预测;对于每个 x,y 应该增加。

我错过了什么?我尝试改变度数,但改善效果不大。例如,当我使用 4 度时,y 增长得非常非常快。


1
graph.csv 文件中,这 11 个数据点是唯一的吗?还是还有其他的数据? - ranka47
4个回答

7

随着每个 x 的增加,y 应该增加。

你的数据确实存在正的线性趋势,如果你对其进行线性回归(即一次多项式),在样本数据之外的预测中就会看到这一点:

enter image description here

但是你已经建立了一个二次回归器,因此它会尽可能地拟合这些点的二次曲线。你的模型正在学习曲线中的平稳点处的轻微“弯曲”,因此随着向右延伸,它会逐渐下降:

enter image description here

如果你认为这种行为显然是错误的,那么你一定对数据的分布有一些假设。如果是这样,你应该使用它们来驱动你的模型选择。
我尝试改变度数,但效果并不好。例如当我使用4次方时,y 值增长非常快。
如果你认为二次函数不足以映射数据的潜在趋势,可以选择更高次数的多项式。但多项式的行为在数据的极值点之外可能会出现很大的分歧。
三次方程 四次方程 五次方程
三次方程 四次方程 五次方程

正如您所看到的,多项式越复杂,就越能灵活地建模您特定数据点的确切趋势,但在您的数据范围之外,它的泛化能力就越弱。

这就是所谓的过拟合

有许多避免这种情况的策略,例如:

  • 收集更多的数据
  • 向您的数据添加噪声
  • 添加正则化项
  • 选择一个更简单的模型

在这种情况下,最简单的方法是后者-如果您怀疑您的数据遵循线性趋势,则将线性模型拟合到它上面。


6

@iacob提供了一个非常好的答案,我只想补充一下。

如果你确信"对于每个x,y应该增加",那么你的数据点可能遵循对数缩放模式。将你的代码适应这种情况可以得出以下曲线:

对数尺度拟合

如果这符合你的要求,下面是代码片段:

import os
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

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

csv_path = os.path.join('', 'graph.csv')
graph = pd.read_csv(csv_path)

y = graph['y'].copy()
x = graph.drop('y', axis=1)

x_log = np.log(x)

pipeline = Pipeline([('pf', PolynomialFeatures(1)), ('clf', LinearRegression())])
pipeline.fit(x_log, y)

predict = np.log([[16], [20], [30]])

plt.plot(np.exp(x_log), y, '.', color='blue')
plt.plot(np.exp(x_log), pipeline.predict(x_log), '-', color='black')
plt.plot(np.exp(predict), pipeline.predict(predict), 'o', color='red')
plt.show()

请注意,我们只是使用x数据点的对数(x_log)进行多项式回归(在这里,线性回归已足够)。


2

我错过了什么吗?

也许 PolynomialFeatures 转换没有做你期望的事情?它通常用于生成特征交互,而不是逼近多项式函数本身。

当我运行您的代码时,拟合的流水线对应以下方程:

y = 1.36105 * x - 0.0656177 * x^2 - 0.370606

预测模型主要受到x^2项的影响,该项与负系数相关。


1
这是一个很好的 过拟合 的例子。你的回归器试图过分拟合,但 x 和 y 遵循线性趋势,因此可能需要拟合一条线性方程(degree=1)。或者,如果您想拟合二次或更高次曲线,则可以尝试使用Lasso或Ridge正则化引入一些偏差。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接