如何预测 scikit-learn 中的时间序列?

Posted

技术标签:

【中文标题】如何预测 scikit-learn 中的时间序列?【英文标题】:How to predict time series in scikit-learn? 【发布时间】:2014-01-17 10:26:00 【问题描述】:

Scikit-learn 使用基于 fitpredict 方法的非常方便的方法。我有适合fitpredict 格式的时间序列数据。

例如我有以下Xs

[[1.0, 2.3, 4.5], [6.7, 2.7, 1.2], ..., [3.2, 4.7, 1.1]]

以及对应的ys

[[1.0], [2.3], ..., [7.7]]

这些数据具有以下含义。存储在ys 中的值形成一个时间序列。 Xs 中的值是相应的与时间相关的“因素”,已知它们会对ys 中的值产生一些影响(例如:温度、湿度和大气压力)。

现在,我当然可以使用fit(Xs,ys)。但是后来我得到了一个模型,其中ys 中的未来值仅取决于因素,而不依赖于先前的Y 值(至少直接),这是模型的限制。我想要一个模型,其中Y_n 也依赖于Y_n-1Y_n-2 等等。例如,我可能想使用指数移动平均线作为模型。在 scikit-learn 中最优雅的方法是什么

添加

正如 cmets 中提到的,我可以通过添加 ys 来扩展 Xs。但是这种方式有一些局限性。例如,如果我将 y 的最后 5 个值作为 5 个新列添加到 X,则有关 ys 的时间排序信息将丢失。例如,X 中没有指示第 5 列中的值在第 4 列中的值之后,依此类推。作为一个模型,我可能希望对最后五个ys 进行线性拟合,并使用找到的线性函数进行预测。但是,如果我在 5 列中有 5 个值,那就不是那么简单了。

增加了 2 个

为了让我的问题更清楚,我想举一个具体的例子。我想要一个“线性”模型,其中y_n = c + k1*x1 + k2*x2 + k3*x3 + k4*EMOV_n,其中 EMOV_n 只是一个指数移动平均线。如何在 scikit-learn 中实现这个简单的模型?

【问题讨论】:

您可以简单地将[np.nan] + ys[:-1] 添加为因素之一 behzad.nouri,我已经扩展了我的问题作为对您评论的回复。 我认为最好的办法是尝试几种不同的简单模型,包括@behzad.nouri 建议的模型,并使用交叉验证来查看是否有任何一个模型比其他模型表现更好并获得一种直觉。时间准确的时间信息可能没有您想象的那么重要。我会在神经网络中使用扩展的 Xs 向量想法,看看是否可行。在这种方法中,您可以保留您的时间信息,即使 n.n.就像一个黑匣子。 您的数据是否托管在任何地方?我可以看看吗? 很遗憾没有托管日期,上面的例子只是一个例子(真实数据有更复杂的结构)。 【参考方案1】:

关于指数加权移动平均线,这可能是您正在寻找的:

import pandas, numpy
ewma = pandas.stats.moments.ewma
EMOV_n = ewma( ys, com=2 )

这里,com 是一个参数,您可以阅读有关here 的信息。然后你可以将EMOV_nXs 结合起来,使用类似:

Xs = numpy.vstack((Xs,EMOV_n))

然后您可以查看各种线性模型,here,然后执行以下操作:

from sklearn import linear_model
clf = linear_model.LinearRegression()
clf.fit ( Xs, ys )
print clf.coef_

祝你好运!

【讨论】:

当 ys 不存在时我们如何找到 EMOV_n。例如。 “测试”数据 你有关于 'ewma' 的 giude 链接吗?我想知道它到底是什么。【参考方案2】:

根据 Wikipedia,EWMA 可以很好地处理固定数据,但在存在趋势或季节性的情况下,它就无法正常工作。在这些情况下,您应该分别使用二阶或三阶 EWMA 方法。我决定看看 pandas ewma 函数,看看它是如何处理趋势的,这就是我想出的:

import pandas, numpy as np
ewma = pandas.stats.moments.ewma

# make a hat function, and add noise
x = np.linspace(0,1,100)
x = np.hstack((x,x[::-1]))
x += np.random.normal( loc=0, scale=0.1, size=200 )
plot( x, alpha=0.4, label='Raw' )

# take EWMA in both directions with a smaller span term
fwd = ewma( x, span=15 )          # take EWMA in fwd direction
bwd = ewma( x[::-1], span=15 )    # take EWMA in bwd direction
c = np.vstack(( fwd, bwd[::-1] )) # lump fwd and bwd together
c = np.mean( c, axis=0 )          # average  

# regular EWMA, with bias against trend
plot( ewma( x, span=20 ), 'b', label='EWMA, span=20' )

# "corrected" (?) EWMA
plot( c, 'r', label='Reversed-Recombined' )

legend(loc=8)
savefig( 'ewma_correction.png', fmt='png', dpi=100 )

如您所见,EWMA 逆势而上。我们可以通过在两个方向上取 EWMA 然后取平均值来纠正这个问题(不必自己实现二阶方案)。我希望你的数据是固定的!

【讨论】:

感谢康纳的 EWMA 示例!但我很好奇你为什么不把这称为二阶方案?通过偏移和平均两个等距的一阶方案,您正在创建一个二阶方案。我知道这是语义,但我只是指出你不会白白得到一些东西:-) 我不确定我所说的是否正确。处理趋势和季节性的二阶和三阶 Holt-Winters 方案具有比简单地取两个方向的平均值更复杂的数学。将来,我建议使用 HoltWinters() R 函数,因为它可以处理二阶和三阶数据以及预测。示例here 是的,我同意 Holt-Winters 具有一些复杂的能力来解决平滑中固有的一些问题。感谢您的链接!我只是提醒您注意您通过平均前向和后向版本将您的方案提升到二阶的事实。实际上,我看到的平均结果比using your Holt-Winters scheme 更好。顺便说一句,很棒的博文! 您在这里似乎没有预测到任何东西。您只需尝试将一条线放入您已经知道的数据中。

以上是关于如何预测 scikit-learn 中的时间序列?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Python scikit-learn 中输出随机森林中每棵树的回归预测?

如何在 Python scikit-learn 中输出随机森林中每棵树的回归预测?

scikit-learn:如何缩减“y”预测结果

如何使用 scikit-learn 的 LinearRegression() 捕获时间序列数据的趋势以进行预测

如何在 Scikit-Learn 中重用 LabelBinarizer 进行输入预测

如何在 scikit-learn 中使用交叉验证获得预测概率