【问题标题】:PolynomialFeatures and LinearRegression returns undesirable coefficientsPolynomialFeatures 和 LinearRegression 返回不需要的系数
【发布时间】:2021-06-18 10:45:07
【问题描述】:
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

产生的结果:

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

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

【问题讨论】:

  • 这 11 个点是 graph.csv 中唯一的数据点还是更多?

标签: python machine-learning scikit-learn regression overfitting-underfitting


【解决方案1】:

我错过了什么?

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

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

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

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      每个 x,y 应该增加。

      您的数据确实有一个积极的线性趋势,如果您将线性回归器(即 1 次多项式)拟合到它,那么您将在样本外的预测中看到数据:

      但是您已经模拟了一个二次回归量,因此它尽可能地将二次曲线拟合到这些点。您的模型正在学习数据中的轻微“弯曲”作为曲线中的固定点,因此它会随着您向右延伸而减小:

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

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

      可以选择更高次的多项式,如果您认为二次方程不够灵活,无法映射数据的潜在趋势。但是多项式的行为可能会在数据的极值之外存在很大差异:

      Cubic Quartic Quintic

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

      这被称为overfitting

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

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

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

      【讨论】:

        【解决方案4】:

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

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

        这里是代码 sn-p 如果它对应于您正在寻找的内容:

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

        【讨论】:

          猜你喜欢
          • 2017-12-18
          • 2018-03-06
          • 2019-03-14
          • 2018-08-26
          • 2015-06-24
          • 2017-11-03
          • 2020-05-16
          • 2013-05-18
          • 2016-04-24
          相关资源
          最近更新 更多