资讯详情

资讯详情

手把手教你用Python进行时间序列分解和预测

预测这件事, 它比较复杂。那些在这个方面做得比较不错的企业, 它们能够在同行业里表现得很突出。时间序列预测这种需求, 它不仅在各种各样的业务场景里面都存在, 而且通常情况下, 人们还需要对未来的几年的时间序列进行预测, 或者是几分钟之后的时间序列进行预测。如果你现在正准备开始做时间序列预测的话, 那么这篇文章会带你很快地掌握一些必不可少的概念。目录, 时间序列到底说的是个什么东西呢。顾名思义, 时间序列就是指那种按照固定时间间隔来记录的数据集。换句话说, 如果是一组以时间为索引的数据, 那么它就是一个时间序列。请大家注意, 这个固定时间间隔, 比如像每小时、每天、每周、每月或者每季度这样的情形, 是非常关键的。这意味着时间单位是不应该发生改变的。千万不要把这个概念和时间序列里面出现的缺失值给混为一谈。针对时间序列里可能存在的缺失值我们是有着相应的方法来对其进行填充处理的。在真正开始利用时间序列里的数据去预测未来的那个数值之前, 有一个事情是需要好好思考的, 那就是你需要提前多久给出预测报告, 这一点尤其重要。你要考虑的是, 到底是应该提前一天来预测呢, 还是应该提前一周, 或者是长达半年、甚至是十年之久, 这里我们用“界限”这个专业术语来称呼它。另外, 你还需要弄明确, 具体进行预测的这个频率是什么样子的。在进行那些关于预测未来值的详细工作之前, 先去跟那些最终要使用你的预测报告的人聊一聊, 这也是一个非常不错的想法。请问现在人们想要知道具体的操作步骤, 好把时间序列数据给画出来呢?可视化时间序列数据是数据科学家想要了解数据模式、时变性、异常值、离群值, 以及查看不同变量之间关系所要做的第一件事。从绘图查看中获得的分析和见解, 不仅将有助于建立更好的预测, 而且还将引导我们找到最合适的建模方法。在这里我们将首先绘制折线图。这里我们所使用的那个数据集, 其实是来自于从一千九百四十九年到一千九百六十年之间的每个月的航空旅客人数的一个集合。下面的这样一个示例数据, 可以让你对于这个数据的信息有一个大概的了解。#Reading Time Series DataAirpassenger pd.read_csv(AirPassengers.csv)Airpassenger.head(3)眼下我们拿折线图把数据给画出来。在下面这个例子里面, 我们用小括号把那个叫 date 的这一列变成了索引。这么一来, 时间就会自动在 x 轴上展现出来了。接着接下来, 我们再动手设置一下整个图形的大小。到最后的时候, 我们再调用 plot() 这个函数, 好把图表给绘制出来。Airpassenger Airpassenger.set_index(date)pyplot.rcParams[figure.figsize] (12,6)Airpassenger.plot()pyplot.show()在1949年到1960年这中间的这段时间里, 坐飞机去旅行的那些人的数量一直都是在不断地往上增加的。那种每隔一段时间就会出现的最高值的出现方式表明, 这种增长的情况似乎是在有规律的时间间隔里面反复重复着发生的。我们先把每一个季度里面的趋势到底是一个什么样的情况给看清楚。为了能够让人们更加容易去明白, 从各种不同的角度去看这个信息肯定是一个不错的想法。因为这样的话, 我们就需要用到那个包里面的东西, 从这个date这个变量那里把年份和季度这两个东西给弄出来才行。在这个图还没有画出来的以前, 我们还必须要把年份还有那个季度的信息给连在一起用, 只有这样子的话我们才能明白在季节这一方面旅客的数量是怎么变掉的。from datetime import datetime# Airpassenger[date] Airpassenger[date].apply(lambda x: datetime.strptime(x, %d-%m-%Y))Airpassenger[year] Airpassenger[date].apply(lambda x: x.year)Airpassenger[qtr] Airpassenger[date].apply(lambda x: x.quarter)Airpassenger[yearQtr]Airpassenger[year].astype(str)_Airpassenger[qtr].astype(str)airPassengerByQtrAirpassenger[[passengerCount, yearQtr]].groupby([yearQtr]).sum()在准备好绘制数据之后, 接下来就是专门去画那个叫做折线图的图形了, 并且还得把全部的时间标签都弄到横轴上去, 由于出现在横轴上的那些个标签的数量实在是非常多, 我们这边最后决定采取的办法是把标签给旋转着摆出来。pyplot.rcParams[figure.figsize] (14,6)pyplot.plot(airPassengerByQtr)pyplot.xticks(airPassengerByQtr.index, rotationvertical)这幅图十分的有趣, 它的呈现是十分的清晰, 表明了在那个时期里面, 也就是在一千九百四十九年到一九六十年之间所有年份的情况航空旅客人数在每个季度里面的增长情况都是十分显著的。我们通常来讲, 在分析时间序列的时候, 时间序列的要素是什么呢。对于时间序列数据来说, 它一共包括了四个主要的部分。1.趋势性这个东西, 表示的是数据随着时间流逝而变多或者变少的那个总体的方向。这个概念其实很容易就能弄明白。比如说看一个例子, 在一九四九年到一九六零年这段日子里面, 民航旅客的总数就表现为在不断地增长, 你当然也可以换一个说法, 说它是在呈现出一种向上的走势。2.季节性这个东西, 就像咱们经历的一年四季一样, 数据模式会在有规律的间隔之后再次出现, 这就构成了时间序列里的季节性组成部分。这些部分会在特定的时间间隔, 比如说天、周、月啊或者年, 这些时间段过去之后反复重复上演。有时候, 我们能够很容易地把季节性给弄清楚。有时候却未必那么容易看清。通常情况下, 大家会去绘制图表, 通过直观检验来确认是否存在季节性的元素。但是偶尔情况下, 我们可能不得不退而求其次, 依靠一些具体的统计方法来进行测试以及验证季节性究竟存不存在。3.可以把周期性看作是类似季节性的一种情况不过这里存在一个唯一的不同点, 那就是周期性并不会按照固定的规律和时间段准时出现。正是因为拥有这样的属性, 所以导致它变得非常难以被清楚地识别和发现。以地震作为例子进行说明的话, 虽然我们能够大致知道某种可能性会发生, 但是在具体的时间和具体的地点方面, 我们是完全不清楚其何时何地会真正发生的。4.在时间序列数据中, 那种突然发生的、不属于前面提到的那三类情况的变化叫做随机噪声, 也因为这种东西很难解释清楚, 所以人们才管它叫作随机波动或者随机噪声。如何分解时间序列想要获取时间序列要素的时候, 存在两种不同的技术。在进入深入的研究阶段, 以及去查看详细的相关抽取函数以前, 大家必须先明白以下这些内容。那么, 关于可加的时间序列模型以及可乘的时间序列模型这两个概念, 它们具体指的是哪一种情况呢。在所谓的可加性模型里面, 那些个各种要素彼此之间是属于一种可以加起来的关系。这里的y乘以括号t等于说就是季节加上趋势再加上周期最后还加上噪音。在可乘性模型里面, 那些要素和要素之间的相互关系是相乘的关系, 这个yt的数值其实就是季节趋势周期以及噪音两者相乘的结果。你现在可能想要知道为什么我们还需要对时间序列做分解处理, 你去看一眼, 在分解这件事儿里面的目的之一, 是为了能够对季节性的影响做出估计, 还要提供那些经过了季节性调整之后的数值, 把那个没有季节性的值拿出来以后, 就可以很轻松地去观察里面的趋势是什么了, 比如说对于美国这个国家来说, 因为里面农业领域的需求增加了, 所以在夏季的时间段里面失业率会有所下降的这样一个现象出现, 从经济学的角度来进行分析的话, 这也代表着六月份的失业率和五月份的那个数据进行对比的时候, 它是呈现出下降状态的。现在, 如果你已经知道了逻辑情况, 这并不代表真实的事情发生, 我们需要对这个事实进行调整, 也就是6月份的失业率始终都低于5月份。挑战点在于, 在现实生活里面, 时间序列有可能是一种可加性和可乘性结合在一起的情况。这就意味着, 我们也许并不总能把时间序列全部都拆分成是纯粹的可加的或者就是可乘的部分。现在, 你已经了解了那些不同的模型, 在此之后, 下面让我们一起去研究一下, 有一些用来提取时间序列要素的常用方法。经典分解法这种方法是在1920年出现, 它属于很多其他方法的起源。经典分解方法存在两种模式, 分别是加法模式和乘法模式。软件库里面的一个函数完成了经典分解方法的具体实现工作。在使用古典分解法的时候, 用户必须明确判断出时间序列属于加法类型, 还是属于乘法类型。如果你希望获取关于加法分解法和乘法分解法的更多内容, 可以参考这里提供的信息。在下面的代码中, 如果要获取时间序列的分解结果的话, 只需要进行赋值操作即可, 也就是将值直接赋予变量model就可以了。import numpy as npfrom pandas import read_csvimport matplotlib.pyplot as pltfrom statsmodels.tsa.seasonal import seasonal_decomposefrom pylab import rcParamselecequip read_csv(rC:/Users/datas/python/data/elecequip.csv)result seasonal_decompose(np.array(elecequip), modelmultiplicative, freq4)rcParams[figure.figsize] 10, 5result.plot()pyplot.figure(figsize(40,10))pyplot.show()如上图所示, 第一行所呈现的内容指的是实际数值方面的数据。在图片的下方, 有三行排列的数据展示出来, 那三行数据表示的是三个特定的因素或要素。如果把这三要素进行累加处理的话, 就足以得到最初的那份原始数据集了。其中, 第二个样本集合主要用于反映变动中的增长或者下降之类的趋势性信息。至于第三个样本集合, 它主要是用来表现具有周期性的季节性情况。当我们将观察的时间范围扩大到完全覆盖整个时间段的时候, 你就能清楚地看到所谓的趋势并非静止不动, 而是在不断发生改变, 同时也在持续产生波动现象。再来看关于季节性的部分吧, 可以非常明确地察觉到, 每隔一段规律的时间间隔之后, 就会看到一个明显上升的最高点或峰值出现。想要得到季节性调整那个数值, 你应该怎么去做呢。对于可加性模型的情况, 我们可以用yt减去st的结果来得到经过季节性调整后的值, 而对于乘法数据类型, 则可以运用yt除以st的方式来实现对值的调整。如果你此刻正在好奇, 为什么咱们非得要用经过季节性调整的数据, 那不如回头去瞧瞧刚才咱们聊过的那个关于美国失业率的例子。所以呢, 假如说季节性压根就不是咱们最在乎的那回事儿, 那么处理完的季节性调整数据就显得更管用一些。虽然说那些老办法确实挺常见的, 可是因为存在下面这些个原因, 大家其实不太推荐去用它们。还有办法可以拿来分解, 而且效果会更好, 比如说什么X11分解、SEAT分解又或者是STL分解, 当前我们要来搞搞清楚怎么在里头把它们给弄出来。与经典法、X11方法以及SEAT分解法相比的话, STL方法拥有很多显而易见的优势部分。接下来的一小块内容, 我们要把讨论的重点投向STL分解法这里来。STL分解法STL这个名字代表的是使用局部加权回归也就是Loess来做的季节性和趋势性的分解, 这个方法对于异常值具备鲁棒性, 也就是比较皮实耐造, 它有能力去处理任何种类的季节性现象, 因为这个特性还在那里摆着, 所以它就变成了一种用途广泛的分解方法, 当你在用的时候, 你可以控制住几件事情:就像任何其他的方法一样, STL也存在它自己的缺点。比如说, 它没办法自动去处理日历上面所发生的那些变换。另外, 它只提供对可加性模型进行分解的功能。但是呢, 你也是能够得到乘法分解的。你是可以首先去获取数据的日志, 然后借由反向传播这个要素来得到最终的结果。不过, 这样做的话, 就已经超出了我们这篇文章现在所讨论的范围了。Import pandas as pdImport seaborn as snsImport matplotlib.pyplot as pltFrom statsmodels.tsa.seasonal import STLelecequip read_csv(rC:/Users/datas/python/data/elecequip.csv)stl STL(elecequip, period12, robustTrue)res_robust stl.fit()fig res_robust.plot()时间序列预测的基本方法虽然目前有很多统计上的技术能够用来对时间序列的数据进行预测, 但是在这部分内容里, 我们仅仅会去介绍那些可以直接用于高效地进行时间序列预测的最直接、也是最简单的具体办法。并且我们会让这些方法充当起其他各种不同方法的底层基础来使用。中的简单移动平均SMA简单移动平均这个方法, 是所有可以用来进行预测的技术里面最为简单的一类。它的计算方式是把最后那N个具体的数值拿来求一个平均值, 从而得出移动均值的那个结果。随后我们把这个已经算出来的平均值当作是接下来那个时期里的预测值。人们选择去使用简单移动平均这种做法的原因, 究竟是什么呢。移动平均这个东西可以帮忙我们快点儿看到数据的趋势, 你能通过它来明白数据到底是在往上走还是在往下走, 它能去掉那些忽高忽低的乱样子, 这种算出移动平均值的手艺叫做尾随移动平均值, 在下面说的那个例子里面, 我们用()这个函数去拿到那个电气设备卖东西的数据移动的线。Import pandas as pdfrom matplotlib import pyplotelecequip pd.read_csv(rC:/Users/datas/python/data/elecequip.csv)# Taking moving average of last 6 obsrolling elecequip.rolling(window6)rolling_mean rolling.mean()# plot the two seriespyplot.plot(elecequip)pyplot.plot(rolling_mean, colorred)pyplot.show()另一种处理办法是采用被称为“中心移动平均”的这种技术, 在这种技术里, 会把任意指定的某个时间点, 也就是标记为t的这个时刻的最终结果, 算作是当前这个时间点的数值, 再加上前面的那些数值以及后面的那些数值, 然后把它们合在一起取一个平均的样子。如果把这个功能开关设置成等于真也就是启用的时候, 就会提供出那个中心方向的移动平均的结果数据来。elecequip[x].rolling(window3, centerTrue).mean()中的加权移动平均WMA简单移动平均这个方法是很朴素的, 因为这一方法对过去的每一个数值都是同样给予权重的。但是如果在假设最新的实际数据与实际的值是存在很近的关系的这种想法的基础上, 那么就给最新的数值分配更多的权重, 这种情况在很多时候可能反而是更加有意义的。计算WMA的时候, 其具体的操作办法就是把过去的每一个观察值, 都分别去乘上一个特定的权重。以6周的滚动窗口为例, 这种做法体现为给最近的那个数值分配6个权重单位, 同时给最末尾那个数值分配1个权重单位。import randomrand [random.randint(1, i) for i in range(100,110)]data {}data[Sales] randdf pd.DataFrame(data)weights np.array([0.5, 0.25, 0.10])sum_weights np.sum(weights)df[WMA](df[Sales].rolling(window3, centerTrue).apply(lambda x: np.sum(weights*x)/sum_weights, rawFalse))print(df[WMA])中的指数移动平均EMA在“指数移动平均”当中, 随着观察值的不断增加, 权重就会按照指数的方式来慢慢递减。这种做法一般说来是一种非常不错的平滑技巧, 可以帮我们从数据里面清除掉非常多的噪声, 这样的话就能得到更好的预测结果。import numpy as npimport pandas as pdimport matplotlib.pyplot as pltfrom statsmodels.tsa.api import ExponentialSmoothingEMA_fit ExponentialSmoothing(elecequip, seasonal_periods12, trendadd, seasonaladd).fit(use_boxcoxTrue)fcast3 EMA_fit.forecast(12)ax elecequip.plot(figsize(10,6), markero, colorblack, titleForecasts from Exponential Smoothing )ax.set_ylabel(Electrical Equipment)ax.set_xlabel(Index)# For plotting fitted values# EMA_fit.fittedvalues.plot(axax, style--, colorred)EMA_fit.forecast(12).rename(EMS Forecast).plot(axax, style--,markero, colorblue, legendTrue)这种方法接下来会讲两种不一样的写法, 它们是两个不同的变例。1.简单指数平滑, 这种预测方法, 它是被用来进行短期预测的, 当时间序列数据是满足某些特定条件的时候, 具体来说呢这个可加性模型, 它必须具有恒定的方差性质, 并且不存在季节性的影响情况出现。2.如果时间序列有趋势, 是增加的或者减少的, 并且没有季节性的可加性模型这种情况, 那么Holt指数平滑法可以用于做短期预测。下面的内容里有关于如何从中把包导入两个模型代码的内容, 现在你可以用上述提到的模型来做练习。import numpy as npimport pandas as pdimport matplotlib.pyplot as pltfrom statsmodels.tsa.api import SimpleExpSmoothing, Holt在这篇篇幅比较长的教程里面, 我们把相关的内容都讲到了。到最后, 我们学习了一些非常基本的方法在之中怎么运行, 这些方法包括移动平均也就是MA加权移动平均也就是WMA, 还有指数平滑模型也就是ESM以及他们的变体, 比方说SESM和Hotl。
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →