【问题标题】:Python polynomial regression plotting wrong?Python多项式回归绘制错误?
【发布时间】:2020-03-26 02:51:41
【问题描述】:

块引用

python 新手,尝试对某些数据完成三阶多项式回归。当我使用多项式回归时,我没有得到我期望的拟合。我试图理解为什么 python 中的多项式回归比 excel 中的更差。当我在 excel 中拟合相同的数据时,我得到一个 ≈.95 的确定系数,并且该图看起来像一个三阶多项式。然而,使用sickitlearn 它是≈0.78,并且拟合看起来几乎是线性的。发生这种情况是因为我没有足够的数据吗?在我的 x 轴上将 x 作为 datetime64[ns]type 还会影响回归吗?代码运行。但是,我不确定这是编码问题还是其他问题。

我正在使用 anaconda (python 3.7) 并在 spyder 中运行代码

import operator
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import PolynomialFeatures
#import data
data = pd.read_excel(r'D:\Anaconda\Anaconda\XData\data.xlsx', skiprows = 0)

x=np.c_[data['Date']]
y=np.c_[data['level']]
#regression
polynomial_features= PolynomialFeatures(degree=3)
x_poly = polynomial_features.fit_transform(x)

model = LinearRegression()
model.fit(x_poly, y)
y_poly_pred = model.predict(x_poly)
#check regression stats
rmse = np.sqrt(mean_squared_error(y,y_poly_pred))
r2 = r2_score(y,y_poly_pred)
print(rmse)
print(r2)

#plot
plt.scatter(x, y, s=10)

# sort the values of x b[![enter image description here][1]][1]efore line plot
sort_axis = operator.itemgetter(0)
sorted_zip = sorted(zip(x,y_poly_pred), key=sort_axis)
x, y_poly_pred = zip(*sorted_zip)
plt.plot(x, y_poly_pred, color='m')
plt.show()

【问题讨论】:

    标签: python numpy scikit-learn anaconda non-linear-regression


    【解决方案1】:

    问题在于在 x 轴上使用 datetime64[ns] 类型。关于datetime64[ns]sklearn 内部的处理方式有an issue on github。在这种情况下,datetime64[ns] 特征被缩放为 10¹⁸ 的特征:

    x_poly
    Out[91]: 
    array([[1.00000000e+00, 1.29911040e+18, 1.68768783e+36, 2.19249281e+54],
           [1.00000000e+00, 1.33617600e+18, 1.78536630e+36, 2.38556361e+54],
           [1.00000000e+00, 1.39129920e+18, 1.93571346e+36, 2.69315659e+54],
           [1.00000000e+00, 1.41566400e+18, 2.00410456e+36, 2.83713868e+54],
           [1.00000000e+00, 1.43354880e+18, 2.05506216e+36, 2.94603190e+54],
           [1.00000000e+00, 1.47061440e+18, 2.16270671e+36, 3.18050764e+54],
           [1.00000000e+00, 1.49670720e+18, 2.24013244e+36, 3.35282236e+54],
           [1.00000000e+00, 1.51476480e+18, 2.29451240e+36, 3.47564662e+54],
           [1.00000000e+00, 1.57610880e+18, 2.48411895e+36, 3.91524174e+54]])
    

    处理它的最简单方法是使用StandardScaler 或使用pd.to_numeric 转换日期时间并对其进行缩放:

    scaler = StandardScaler()
    x_scaled = scaler.fit_transform(np.c_[data['Date']])
    

    或者干脆

    x_scaled = np.c_[pd.to_numeric(data['Date'])] / 10e17  # convert and scale
    

    这提供了适当缩放的功能:

    x_poly = polynomial_features.fit_transform(x_scaled)
    x_poly
    Out[94]: 
    array([[1.        , 1.2991104 , 1.68768783, 2.19249281],
           [1.        , 1.336176  , 1.7853663 , 2.38556361],
           [1.        , 1.3912992 , 1.93571346, 2.69315659],
           [1.        , 1.415664  , 2.00410456, 2.83713868],
           [1.        , 1.4335488 , 2.05506216, 2.9460319 ],
           [1.        , 1.4706144 , 2.16270671, 3.18050764],
           [1.        , 1.4967072 , 2.24013244, 3.35282236],
           [1.        , 1.5147648 , 2.2945124 , 3.47564662],
           [1.        , 1.5761088 , 2.48411895, 3.91524174]])
    

    编辑:保留您的x 以供情节使用。要进行预测,您应该对要预测的特征应用相同的转换。之后的结果将如下所示:

    x = np.c_[data['Date']]
    x_scaled = np.c_[pd.to_numeric(data['Date'])] / 10e17  # convert and scale
    polynomial_features = PolynomialFeatures(degree=3)
    x_poly = polynomial_features.fit_transform(x_scaled)
    
    model = LinearRegression()
    model.fit(x_poly, y)
    y_poly_pred = model.predict(x_poly)
    
    # test to predict
    s_test = pd.to_datetime(pd.Series(['1/1/2013', '5/5/2019']))
    x_test = np.c_[s_test]
    x_poly_test = polynomial_features.transform(np.c_[pd.to_numeric(s_test)] / 10e17)
    y_test_pred = model.predict(x_poly_test)
    
    plt.scatter(x, y, s=10)
    # plot predictions as red dots
    plt.scatter(x_test, y_test_pred, s=10, c='red')
    plt.plot(x, y_poly_pred, color='m')
    plt.show()
    

    【讨论】:

    • 谢谢,这确实修复了 R^2 和形状。但是你是如何让 X 轴显示日期的呢?我将代码从 x=np.c_[data['date']] 更改为 x_scaled = np.c_[pd.to_numeric(data['Date'])] / 10e17 但 x asis 显示 1.3-1.5 而不是一年。
    • 另外我这样做的原因是我可以预测 2021 年和 22 年的水平。
    • @G_EXL_snake 编辑了答案。在您的情况下,3 次多项式回归是否足够好 - 这是一个完全不同的故事。
    猜你喜欢
    • 1970-01-01
    • 2023-01-17
    • 2020-05-08
    • 2016-06-10
    • 2018-02-16
    • 2017-02-21
    • 2017-04-23
    • 2014-06-13
    相关资源
    最近更新 更多