时间序列预测的7种方法(Python代码实现)
Posted 每日一Python
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了时间序列预测的7种方法(Python代码实现)相关的知识,希望对你有一定的参考价值。
上一篇文章介绍了时间序列问题、安装statsmodels的方法和三个简单的预测方法,这篇文章介绍剩余四个预测方法。
方法4:简单指数平滑(Simple Exponential Smoothing)
从上述几个方法我们可以了解到简单平均法和移动平均法是两个极端,我们或许需要一种在两者之间的一种方法,将所有的数据都计算在内,并给与不同的数据以不同的权重;例如分配较大的权重给最近的观测点而不是过去的观测点是比较明智的;基于这种准则的方法就叫做简单指数平滑法。预测是使用加权平均计算的,权重随着观测时间越来越远而呈指数下降,最小的权重和最久的观测值关联。
0<=α<=1是平滑参数;
对于T+1的一步时间预测是Y1...YT所有观测序列值的加权平均;权重下降的速率是由参数α控制的;
如果你盯的时间够长,你就会发现Y^x的期望值是α.yt和(1-α).y^(t-1)这两个成绩的和,因此,它也可以被写成:
所以本质上我们根据α和1-α这两个权重得到了一个加权移动平均;
我们可以看到,1-α和先前的预测值y^(x-1)相乘,使表达式构成了递归表达式,
因此这种方法被叫作指数式。t+1的预测值与最近的观测值yt和最近的预测值y^t|(t-1)的加权平均相等
from statsmodels.tsa.api import ExponentialSmoothing, SimpleExpSmoothing, Holt y_hat_avg = test.copy() fit2 = SimpleExpSmoothing(np.asarray(train['Count'])).fit(smoothing_level=0.6, optimized=False) y_hat_avg['SES'] = fit2.forecast(len(test)) plt.figure(figsize=(16,8)) plt.plot(train['Count'], label='Train') plt.plot(test['Count'], label='Test') plt.plot(y_hat_avg['SES'], label='SES') plt.legend(loc='best') plt.show()
计算RMSE来验证模型的准确性:
rms = sqrt(mean_squared_error(test.Count, y_hat_avg.SES)) print(rms) RMSE = 43.3576252252
我们可以看到运用α=0.6的简单指数平滑模型可以得到一个较好的结果,我们可以用验证集来调整参数去产生一个更好的简单指数平滑模型;
方法5:霍尔特线性趋势预测(Holt's linear trend method)
我们已经学了几个模型去预测了,但是每个模型在高变化率的数据上表现都不是太好。假设比特币的价格在一直上升
如果我们用上面任意一个模型预测,都不能将这种趋势考虑进去。趋势是我们在这个时间段内观察到的整体模式。我们可以看到在这个例子中趋势是上升 的。
虽然我们可以用上面任意一种方法来预测,例如用简单法的时候假设最后两点的趋势是相同的,或者平均所有点之间的斜率得到一个平均趋势,然后用移动平均或者指数平滑法,但是我们需要一种方法无需任何假设就能准确地映射这种趋势,这种将数据集的趋势考虑进去的方法叫做霍尔特线性趋势预测法(Holt's linear trend method)。
每个时间序列数据集可以被分解为趋势、季节性和残差;沿着某种趋势的任意数据集都可以用霍尔特线性趋势预测法进行预测。
```
import statsmodels.api as sm
sm.tsa.seasonal_decompose(train.Count).plot()
result = sm.tsa.stattools.adfuller(train.Count)
plt.show()
```
我们能从上面的图表看出,数据呈现上升趋势,因此可以用霍尔特线性趋势预测去预测未来的价格;
霍尔特扩展了简单指数平滑法,允许预测具有趋势的数据。它仅仅比指数平滑多了两个运用:水平线(系列值的平均值)和趋势。用数学符号来表达它的华,我们需要用三个等式:一个是表达水平线,一个是表达趋势,一个是结合水平线和趋势来得到期望的预测值y^
我们在上述算法中预测的值被称为水平值,从上面三个等式可以看到,我们增加了水平和趋势等式来生成预测等式。
和简单指数平滑一样,水平等式表示的是观测值的加权平均,样本内一步提前预测趋势等式表示基于ℓ(t)−ℓ(t−1) 和 b(t−1)的在时间为t的加权平均预估值;
我们可以将这些等式相加来生成预测等式。我们也可以通过将趋势和水平相乘来生成乘法预测等式;当趋势是线性递增或递减时,采用加法等式,而当趋势是指数递增或递减时,则采用乘法等式。实践表明,乘法是一个更加稳固的预测器,而加法更容易理解。
y_hat_avg = test.copy() fit1 = Holt(np.asarray(train['Count'])).fit(smoothing_level=0.3, smoothing_slope=0.1) y_hat_avg['Holt_linear'] = fit1.forecast(len(test)) plt.figure(figsize=(16,8)) plt.plot(train['Count'], label='Train') plt.plot(test['Count'], label='Test') plt.plot(y_hat_avg['Holt_linear'], label='Holt_linear') plt.legend(loc='best') plt.show()
计算RMSE来检验模型的准确性:
rms = sqrt(mean_squared_error(test.Count, y_hat_avg.Holt_linear)) print(rms) RMSE = 43.0562596115
我们可以看到这个模型可以准确地映射趋势,因此相较前几个模型是一个更好的解决方案。我们仍然可以调整参数来获得一个更好的模型。
方法6-三次指数平滑法(Holt 's Winter seasonal method)
假设一个旅馆在山中避暑地,在夏天的时候将会有高访问量而在其余的时间则相对较少;因此所有者获得的利润在夏天将远远多于其他季节。这种模式每年都会重复。这种重复性被称为季节性。在固定时间间隔内显示相似的模式的数据集遭受季节性的影响。
上述提到的模型在预测时都没有考虑季节性,因此我们需要一种方法既考虑趋势又考虑季节性来预测未来价格。在这种场景中使用的方法叫做次指数平滑法(Holt 's Winter seasonal method)。三次指数平滑(Holt's Winter)的思想是除了采用水平和趋势外,还对季节性成分应用指数平滑。
因为季节性因素,三次指数平滑和其他模型相比是一个最好的选择。三次指数平滑方法包括预测等式和包含三个平滑参数α,β,γ的三个平滑等式--一个是水平等式ℓt,一个是趋势等式bt,一个是季节性成分,被表示未st:
S是季节周期的长度,0 ≤ α ≤ 1, 0 ≤ β ≤ 1 and 0 ≤ γ ≤ 1。
水平等式显示了季节性调整观测值和对于时间t的非季节性预测值的加权平均值。趋势等式与霍尔特线性方法相同。季节性等式显示了当前季节性指数和去年同季节的季节性指数的加权平均。
在这种方法中,我们也可以运用加法和乘法技术。当季节性变量在整个序列中是大体不变时用加法比较好,而当季节性变量和序列的水平值成比例变化时用乘法方法比较好。
y_hat_avg = test.copy() fit1 = ExponentialSmoothing(np.asarray(train['Count']), seasonal_periods=7, trend='add', seasonal='add').fit() y_hat_avg['Holt_Winter'] = fit1.forecast(len(test)) plt.figure(figsize=(16, 8)) plt.plot(train['Count'], label='Train') plt.plot(test['Count'], label='Test') plt.plot(y_hat_avg['Holt_Winter'], label='Holt_winter') plt.legend(loc='best') plt.show()
计算RMSE来检验模型的正确性:
rms = sqrt(mean_squared_error(test.Count, y_hat_avg.Holt_Winter)) print(rms) RMSE = 23.9614925662
我们从图表可以看出,映射正确的趋势和季节性给我们提供了一个更好的解决办法。因为数据每周重复一次,我们选择了季节性周期=7。根据数据集可以调整其余的参数。训练这个模型时我用了默认参数。可以自己调整一下参数来获得一个更好的模型。
方法7-自回归积分滑动平均模型(ARIMA)
另一个在数据科学家之间很受欢迎的模型是ARIMA,它代表自回归集成移动平均,而指数平滑模型是基于数据的趋势和季节性描述,ARIMA模型目标是描述数据之间的相互关系。ARIMA的改进是季节性ARIMA,它像三次指数平滑法一样考虑了数据集的季节性。(这篇文章没有详细介绍ARIMA和季节性ARIMA)
y_hat_avg = test.copy() fit1 = sm.tsa.statespace.SARIMAX(train.Count, order=(2,1,4), seasonal_order=(0,1,1,7)).fit() y_hat_avg['SARIMA'] = fit1.predict(start="2013-11-1",
end='2013-12-31',dynamic=True) plt.figure(figsize=(16,9)) plt.plot(train['Count'], label="Train") plt.plot(test['Count'], label="Test") plt.plot(y_hat_avg['SARIMA'], label="SARIMA") plt.legend(loc="best") plt.show()
计算RMSE来验证模型的准确性
rms = sqrt(mean_squared_error(test.Count, y_hat_avg.SARIMA)) print(rms) RMSE = 26.035582877
可以看到用季节性ARIMA生成了一个和三次指数平滑法类似的解决方案。
以上是关于时间序列预测的7种方法(Python代码实现)的主要内容,如果未能解决你的问题,请参考以下文章