使用 patsy cr 的自然三次样条

Natural cubic spline using patsy cr

我正在尝试使用 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()

输出如下:

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

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

DSBA广场教师助理团队

这只是一个策划问题。 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_boundmodel._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()