【问题标题】:Predicting on new data using locally weighted regression (LOESS/LOWESS)使用局部加权回归 (LOESS/LOWESS) 预测新数据
【发布时间】:2016-07-15 03:03:41
【问题描述】:

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

statsmodels.nonparametric.smoothers_lowess.lowess,但它只返回原始数据集的估计值;所以它似乎只将fitpredict 放在一起,而不是像我预期的那样分开。

scikit-learn 始终有一个fit 方法,该方法允许该对象稍后用于predict 的新数据;但它没有实现lowess

【问题讨论】:

标签: python python-3.x pandas statsmodels


【解决方案1】:

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

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()

【讨论】:

  • 这将使用线性插值。虽然这并非不合理,但它与“使用lowess预测”并不完全相同。 Lowess 被定义为对训练点子集的加权线性回归。它对新点的预测应该基于回归的结果,而不是预测训练集的两个附近点,然后用一条线连接它们。当然,对于密集数据集,差异是微不足道的。范围之外的点也应该使用相应邻域上的加权 LR 进行预测)而不是固定值。
  • @max 刚刚遇到类似问题的这个问题。虽然 sklearn 没有实现 LOESS,但它有一个 RANSAC 实现,这对我未经训练的眼睛来说似乎足够相似。希望这对某人有用:scikit-learn.org/stable/modules/generated/…
  • @max 这一点也不无道理,一段时间以来我一直在使用类似的方法以非参数方式缩放代谢组学数据。我将范围之外的点缩放到 LOWESS 曲线的最大值或最小值,并对其他所有内容进行线性插值。如果没有足够的点用于适当的线性插值,那么在我看来,就没有足够的点用于适当的 LOWESS 曲线。另一个注意事项,我一直在使用 R 库而不是 Python 库。 python 库有一些我无法协调的边缘效果问题。一定要爱RPy2
  • @DanielHitchcock If there are not enough points for a proper linear interpolation, then there are not enough points for a proper LOWESS curve in my opinion -- 我很赞同你的论点,但这是因为我个人偏爱超级简单的技术。我当然不会试图说服许多使用 LOWESS 的数据科学家他们应该放弃它,转而支持线性插值。我没有否决你的答案,但我可以看到 SO 用户可能会认为它没有回答我的原始问题。
  • @AleksanderLidtke RANSAC 可能在类似于 LOWESS(或实际上是线性插值)可用的情况下可用。但它肯定是一个非常不同的算法(它是不确定的;它对异常值不太敏感,因为它试图删除它们)。
【解决方案2】:

考虑改用内核回归。

statmodels 有一个implementation

如果你的数据点太多,为什么不使用 sk.learn 的radiusNeighborRegression 并指定一个三角加权函数?

【讨论】:

  • @David_R,如果您更清楚地说明您的意思(实际上展示了您的实现),那么这个答案将非常出色。只是一个建议。
  • @benjaminmgross,感谢您的留言。也许我会在这周晚些时候或这个周末找到一些时间来详细说明。
【解决方案3】:

我创建了一个名为 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)

有关如何使用模型(及其置信区间和预测区间变体)的更详细指南,请访问 here

【讨论】:

    【解决方案4】:

    目前尚不清楚拥有一个专用的 LOESS 对象是否是一个好主意,该对象具有单独的拟合/预测方法,例如 Scikit-Learn 中常见的方法。相比之下,对于神经网络,您可以拥有一个仅存储相对较小的权重集的对象。然后,拟合方法将通过使用非常大的训练数据集来优化“少数”权重。 predict 方法只需要权重来进行新的预测,而不需要整个训练集。

    另一方面,基于 LOESS 和最近邻的预测需要整个训练集才能做出新的预测。 fit 方法唯一能做的就是将训练集存储在对象中以备后用。如果xy 是训练数据,x0 是进行新预测的点,那么这个面向对象的拟合/预测解决方案将如下所示:

    model = Loess()
    model.fit(x, y)         # No calculations. Just store x and y in model.
    y0 = model.predict(x0)  # Uses x and y just stored.
    

    相比之下,在我的localreg 库中,我选择了简单:

    y0 = localreg(x, y, x0)
    

    这真的取决于设计选择,因为性能是一样的。 拟合/预测方法的一个优点是您可以像在 Scikit-Learn 中那样拥有一个统一的界面,其中一个模型可以很容易地被另一个模型交换。拟合/预测方法也鼓励使用机器学习的方式来思考它,但从这个意义上说,LOESS 并不是很有效,因为它需要为每个新预测存储和使用所有数据。后一种方法更倾向于将 LOESS 作为散点图平滑算法的起源,这是我更喜欢考虑的方式。这也可以解释为什么 statsmodel 会这样做。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-10-04
      • 2015-03-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-07
      • 2014-12-18
      相关资源
      最近更新 更多