PolynomialFeatures 和 LinearRegression 返回不需要的系数

问题描述

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()

我的 graph.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

产生的结果:

enter image description here

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

我错过了什么?我尝试改变学位,但并没有变得更好。例如,当我使用度数 4 时,y 增加得非常快。

解决方法

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

您的数据确实存在正线性趋势,如果您将线性回归量(即 1 次多项式)拟合到它,这就是您在样本外的预测中看到的数据:

enter image description here

但是您已经对二次回归量进行了建模,因此它尽可能将二次曲线拟合到这些点。您的模型正在学习数据中的轻微“弯曲”作为曲线中的静止点,因此当您向右延伸时它会减小:

enter image description here

如果你认为这种行为显然是错误的,那么你肯定对数据的分布有一些假设。如果是这样,您应该使用这些来推动您的模型选择。

我尝试改变学位,但并没有好转。例如,当我使用度数 4 时,y 增加得非常快。

如果您认为二次函数不够灵活以映射数据的潜在趋势,您可以选择更高次的多项式。但是多项式的行为可能会超出数据的极值范围:

Cubic Quartic quintic
立方 四次 五行

如您所见,多项式越复杂,它对特定数据点样本的确切趋势建模的灵活性就越大,但超出数据范围的通用性越低。

这称为 overfitting

有很多策略可以避免这种情况,例如:

  • 收集更多数据
  • 给数据添加噪音
  • 添加正则化项
  • 选择更简单的模型

在这种情况下,最简单的方法是后者 - 如果您怀疑您的数据遵循线性趋势,请为其拟合线性模型

,

@iacob 提供了一个很好的答案,我只会扩展。

如果您确定 with each x,y should increase,那么您的数据点可能遵循对数缩放模式。为此调整您的代码会产生以下曲线:

Log Scale fitting

如果这符合您要查找的内容,这里是代码片段:

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) 的对数进行多项式回归(这里线性回归就足够了)。

,

我错过了什么?

也许 PolynomialFeatures 转换没有按照您的预期进行?它通常用于生成特征交互,而不是逼近多项式函数本身

当我运行您的代码时,拟合的管道对应于以下等式:

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

预测模型以与负系数相关联的 x^2 项为主。

,

这是过度拟合的一个很好的例子。您的回归量太难拟合,但 x 和 y 遵循线性趋势,因此可能想要拟合线性方程(度数 = 1)。 或者您甚至可以尝试使用 Lasso 或 Ridge 正则化引入一些偏差,但前提是您想要拟合 2 阶或更高阶的曲线