使用局部加权回归(LOESS/LOWESS)预测新数据

max*_*max 14 python python-3.x pandas statsmodels

如何在python中拟合局部加权回归,以便它可用于预测新数据?

statsmodels.nonparametric.smoothers_lowess.lowess,但它仅返回原始数据集的估计值; 如此看来只做fitpredict在一起,而不是单独作为我的预期.

scikit-learn总是有一个fit方法允许稍后在新数据上使用该对象predict; 但它没有实现lowess.

Dan*_*ock 11

Lowess非常适合预测(当与插值结合使用时)!我认为代码非常简单 - 如果您有任何问题,请告诉我! Matplolib图

import matplotlib.pyplot as plt
%matplotlib inline
from scipy.interpolate import interp1d
import statsmodels.api as sm

# introduce some floats in our x-values
x = list(range(3, 33)) + [3.2, 6.2]
y = [1,2,1,2,1,1,3,4,5,4,5,6,5,6,7,8,9,10,11,11,12,11,11,10,12,11,11,10,9,8,2,13]

# lowess will return our "smoothed" data with a y value for at every x-value
lowess = sm.nonparametric.lowess(y, x, frac=.3)

# unpack the lowess smoothed points to their values
lowess_x = list(zip(*lowess))[0]
lowess_y = list(zip(*lowess))[1]

# run scipy's interpolation. There is also extrapolation I believe
f = interp1d(lowess_x, lowess_y, bounds_error=False)

xnew = [i/10. for i in range(400)]

# this this generate y values for our xvalues by our interpolator
# it will MISS values outsite of the x window (less than 3, greater than 33)
# There might be a better approach, but you can run a for loop
#and if the value is out of the range, use f(min(lowess_x)) or f(max(lowess_x))
ynew = f(xnew)


plt.plot(x, y, 'o')
plt.plot(lowess_x, lowess_y, '*')
plt.plot(xnew, ynew, '-')
plt.show()
Run Code Online (Sandbox Code Playgroud)

  • 这将使用线性插值.虽然这不是不合理的,但它与"使用lowess预测"并不完全相同.Lowess被定义为训练点子集的加权线性回归.它对新点的预测应该基于该回归的结果,而不是预测训练集的两个附近点,然后用线连接它们.对于密集的数据集,当然,差异是微不足道的.超出范围的点也应该用相应邻域的加权LR预测而不是固定值. (4认同)
  • @DanielHitchcock“如果没有足够的点来进行适当的线性插值,那么在我看来,就没有足够的点来进行适当的 LOWESS 曲线”——我同情你的论点,但那是因为我个人倾向于支持超级简单的技术。我当然不会试图说服许多使用 LOWESS 的数据科学家,让他们相信他们应该放弃它,转而使用线性插值。我没有否决你的答案,但我可以看到SO用户可能会认为它没有回答我原来的问题。 (2认同)

小智 8

我创建了一个名为 的模块moepy,它为 LOWESS 模型(包括拟合/预测)提供类似 sklearn 的 API。这使得可以使用底层局部回归模型进行预测,而不是使用其他答案中描述的插值方法。下面显示了一个极简示例。

# Imports
import numpy as np
import matplotlib.pyplot as plt
from moepy import lowess

# Data generation
x = np.linspace(0, 5, num=150)
y = np.sin(x) + (np.random.normal(size=len(x)))/10

# Model fitting
lowess_model = lowess.Lowess()
lowess_model.fit(x, y)

# Model prediction
x_pred = np.linspace(0, 5, 26)
y_pred = lowess_model.predict(x_pred)

# Plotting
plt.plot(x_pred, y_pred, '--', label='LOWESS', color='k', zorder=3)
plt.scatter(x, y, label='Noisy Sin Wave', color='C1', s=5, zorder=1)
plt.legend(frameon=False)
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

有关如何使用该模型(及其置信度和预测区间变体)的更详细指南可以在此处找到。