【问题标题】:Natural cubic spline using patsy cr使用 patsy cr 的自然三次样条
【发布时间】:2021-02-25 12:17:40
【问题描述】:

我正在尝试使用 patsy 库制作自然三次样条。 这是我的代码:

import numpy as np
from sklearn.linear_model import LinearRegression
from patsy import cr
import matplotlib.pyplot as plt

x = df.age #some data
y = df.wage

x_basis = cr(x, df=15)
model = LinearRegression().fit(x_basis, y)
y_hat = model.predict(x_basis)
plt.scatter(x, y)
plt.plot(x, y_hat, 'r')
plt.show()

输出如下:

我认为应该只有一行。我该如何解决这个问题?

【问题讨论】:

    标签: python matplotlib regression spline smoothing


    【解决方案1】:

    这只是一个绘图问题。 plt.plot 函数默认绘制没有标记的线图。由于您的数据未按x 变量排序,因此该行来回跳转,使结果看起来很混乱。我生成了示例数据并使用plt.plot 默认值绘制,然后隐藏线并添加标记。结果是

    使用默认的plt.plot 参数

    下面的其余代码(为方便起见不再重复)

    spline_basis = patsy.cr(x, df=3)
    model = LinearRegression().fit(spline_basis, y)
    y_spline = model.predict(spline_basis)
    plt.scatter(x, y)
    plt.plot(x, y_spline, color="red")
    plt.show()
    

    plt.plotmarker='.'ls=''

    下面的其余代码(为方便起见不再重复)

    spline_basis = patsy.cr(x, df=3)
    model = LinearRegression().fit(spline_basis, y)
    y_spline = model.predict(spline_basis)
    plt.scatter(x, y)
    plt.plot(x, y_spline, ls="", marker=".", color="red") # Only this changed
    plt.show()
    

    通过重新排序数据

    下面的其余代码(为方便起见不再重复)
    如果你想画一个线图,你可以重新排列数据进行拟合,像这样:

    spline_basis = patsy.cr(x, df=3)
    model = LinearRegression().fit(spline_basis, y)
    y_spline = model.predict(spline_basis)
    plt.scatter(x, y)
    xsorted, ysorted = zip(*[(X, Y) for (X, Y) in sorted(zip(x, y_spline))]) # simple reordering
    plt.plot(xsorted, ysorted, color="red")
    plt.show()
    

    通过使用新数据进行预测

    通常,创建模型用于预测。我们的想法是使用训练数据创建模型,然后将模型与一些新数据一起使用。这个新数据可以是任何东西。如果已排序,则可以绘制为线图。在这种情况下,您可以创建新的 x 值,例如

    new_x = np.linspace(10, 100, 100)
    

    并计算它们的预测 y 值。为此,您只需要知道(并保存)几个值。实际上,只有dflower_boundupper_bound 和来自model._coef 的 4 个浮点数。

    # Fit model
    spline_basis = patsy.cr(x, df=3, lower_bound=x.min(), upper_bound=x.max())
    model = LinearRegression().fit(spline_basis, y)
    y_train = model.predict(spline_basis)
    
    # Use model
    new_x = np.linspace(10, 100, 100)  # 100 points
    spline_basis_new = patsy.cr(new_x, df=3, lower_bound=x.min(), upper_bound=x.max())
    new_y = model.predict(spline_basis_new)
    
    plt.scatter(x, y)
    plt.plot(x, y_train, color="red", ls="", marker=".")
    plt.plot(new_x, new_y, color="green")
    plt.show()
    

    其余代码

    from matplotlib import pyplot as plt
    import numpy as np
    import patsy
    from sklearn.linear_model import LinearRegression
    
    
    def dummy_data():
        np.random.seed(1)
    
        x = np.random.choice(np.arange(18, 81), size=4000)
    
        def model(x):
            a = 83 / 107520
            b = -895 / 5376
            c = 17747 / 1680
            d = -622 / 7
            return a * x ** 3 + b * x ** 2 + c * x + d
    
        def noisemodel(x):
            an = -0.0591836734693878
            bn = 5.25510204081633
            cn = -31.6326530612245
            return an * x ** 2 + bn * x + cn
    
        y = model(x)
        ynoise = np.array([np.random.randn() * noisemodel(_) for _ in x])
    
        return x, y + ynoise
    
    
    x, y = dummy_data()
    

    【讨论】:

    • 关于新数据点部分,比如我在生产中只有一个x,我应该如何应用cr然后使用保存的模型?
    • 您需要保存与训练数据一起使用的dflower_boundupper_bound(三个数字),以便使用patsy.cr 创建新的样条基。保存使用 sklearn possible with pickle 创建的回归模型。虽然,如果你只有一个线性模型,你需要做的就是保存model._coef,然后预测只是矩阵乘法。
    • 非常感谢@np8!但是这里我们仍然假设 x 有多个值,以便我们确实可以像 cr(x_new, df=10, constraints="center", lower_bound=x.min(), upper_bound=x.max()) 一样应用它?假设我的 x_new 是 150,我想获得相应的平滑值 [具有 1 x 10 维度],以便我可以在线性回归中使用它。我错过了什么?
    • 我现在不在电脑上,但如果你刚刚创建了一个只有一个值的 np.array 会起作用吗?如果没有,我想最好创建一个新问题。我不确定 patsy.cr 对其输入有什么样的先决条件。
    • 你可以在stackoverflow.com/questions/66107014/…找到我的问题。谢谢!
    【解决方案2】:

    Bruh,在传递给 patsy 函数之前对值进行排序。

    DSBA Piazza 教师助理团队

    【讨论】:

    • 这个“DSBA Piazza教师助理团队”是什么?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-09-25
    • 1970-01-01
    • 1970-01-01
    • 2010-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多