时间序列分析 订阅
时间序列分析(Time-Series Analysis)是指将原来的销售分解为四部分来看——趋势、周期、时期和不稳定因素, 然后综合这些因素, 提出销售预测。强调的是通过对一个区域进行一定时间段内的连续遥感观测,提取图像有关特征,并分析其变化过程与发展规模。当然,首先需要根据检测对象的时相变化特点来确定遥感监测的周期,从而选择合适的遥感数据。 [1] 展开全文
时间序列分析(Time-Series Analysis)是指将原来的销售分解为四部分来看——趋势、周期、时期和不稳定因素, 然后综合这些因素, 提出销售预测。强调的是通过对一个区域进行一定时间段内的连续遥感观测,提取图像有关特征,并分析其变化过程与发展规模。当然,首先需要根据检测对象的时相变化特点来确定遥感监测的周期,从而选择合适的遥感数据。 [1]
信息
应    用
统计分析
外文名
Time series analysis
分    类
确定性变化分析和随机性变化分析
中文名
时间序列分析
简    介
动态数据处理的统计方法
学    科
数学
时间序列分析基础知识
时间序列是按时间顺序的一组数字序列。 [2]  时间序列的特点:时间序列建模基本步骤是:
收起全文
精华内容
下载资源
问答
  • 时间序列分析
    千次阅读
    2020-12-19 05:31:34

    时间序列分析实验报告

    基于matlab的时间序列分析在实际问题中的应用 时间序列分析(Time series analysis)是一种动态数据处理的统计方法。该方法基于随机过程理论和数理统计学方法,研究随机数据序列所遵从的统计规律,以用于解决实际问题。时间序列分析不仅可以从数量上揭示某一现象的发展变化规律或从动态的角度刻画某一现象和其他现象之间的内在的数量关系及其变化规律性,而且运用时间序列模型可以预测和控制现象的未来行为,以达到修正或重新设计系统使其达到最优状态。 时间序列是指观察或记录到的一组按时间顺序排列的数据。如某段时间内。某类产品产量的统计数据,某企业产品销售量,利润,成本的历史统计数据;某地区人均收入的历史统计数据等实际数据的时间序列。展示了研究对象在一定时期内的发展变化过程。可以从中分析寻找出其变化特征,趋势和发展规律的预测信息。时间序列预测方法的用途广泛,它的基本思路是,分析时间序列的变化特征,选择适当的模型形式和模型参数以建立预测模型,利用模型进行趋势外推预测,最后对模型预测值进行评价和修正从而得到预测结果。目前最常用的拟合平稳序列模型是ARMA模型,其中AR和MA模型可以看成它的特例。 一.时间序列的分析及建模步骤 (1) 判断序列平稳性, 若平稳转到(3),否则转到(2)。 平稳性检验是动态数据处理的必要前提,因为时间序列算法的处理对象是平稳性的数据序列,若数据序列为非平稳,则计算结果将会出错。在实际应用中,如某地区的GDP,某公司的销售额等时间序列可能是非平稳的,它们在整体上随着时间的推移而增长,其均值随时间变化而变化。通常将GDP等非平稳序列作差分或预处理。所以获得一个时间序列之后,要对其进行分析预测,首先要保证该时间序列是平稳化的。平稳性检验的方法有数据图、逆序检验、游程检验、自相关偏相关系数、特征根、参数检验等。本实验中采用数据图法,数据图法比较直观。 (2) 对序列进行差分运算。 一般而言,若某序列具有线性趋势,则可以通过对其进行一次差分而将线性趋势剔除掉。差分的实质是自回归。对线性趋势的序列,一阶差分即可提取确定性信息若序列具有二次趋势,则两次差分后可变换为平稳序列,若序列具有d次多项式趋势,则通过d次差分后可变为平稳序列。 (3) 计算序列的自相关系数和偏相关系数,判断截尾性,对序列模型进行识别。 若序列自相关系数在q步截尾(即kq时,显著的等于零)并且偏相关系数被负指数函数收敛到零,则可判断为MA(q)序列。 若序列偏相关系数在p步截尾,并且序列自相关系数被负指数函数控制收敛到零,则可判断凡为AR(p)序列。 若序列和序列皆不截尾,且自相关系数和偏相关系数都被负指数函数控制收敛到零 则序列为ARMA序列。以上都不满足,则序列是非平稳的。 (4)对模型阶数进行估计 模型定阶的方法有残差方差图法,自相关函数和偏自相关函数法,F检验法,最佳准则函数法等。本实验采用自相关函数和偏自相关函数法和AIC准则。 (5)估计模型参数。 不论是那种时间序列模型,要建立完整的估计方程就需要知道其中的参数。可以用矩估计、最小二乘估计、极大似然估计等方法得到模型中的参数。本实验采用最小二乘估计。 (6)模型适应性检验及优化,计算残差方差是否最小,若是最小转到(7),否则转到(4)。 模型的适应性检验实质上是对at的独立性检验,如果得到的模型已经是适应性模型,那么at一定是完全或基本上接近独立的,这时若再增加模型的阶数,新增加的参数可能接近等于0,剩余平方和也不会因增加模型的阶数而显著减小。常用的适应性检验方法有:散点图法,估计参数法,F检验法等。估计参数法比较粗略。 (7)根据参数建立方程,预测序列未来走势等。 将各个模型的参数估计出来之后,结合估计出来的模型的阶数,可以根据各个模型的估计方程建立具体的估计方程,代入已知的时间序列的项从而对时间序列中的未来的项进行预测。其中模型方程中的白噪声序列可以通过时间序列本身经过相关处理生成。 二.实验内容 对我国 1978—2005 年的 GDP 进行建模分析并对2006-2011年的GDP进行预测,并与实际值比较,估计预测质量。实验利用MATLAB软件进行建模仿真及预测。我国 1978—2005 年的 GDP值列于下表1 表1为我国1978-2005年的GDP (亿元) 1978年 1979年 1980年 1981年 1982年 1983年 1984年 3645.2 4062.6 4545.6 4891.6 5323.4 5962.7 7208.1 1985年 1986年 1987年 1988年 1989年 1990年 1991年 9016 19275.2 12058.6 15042.8 16992.3 18667.8 21781.5 1992年 1993年 1994年 1995年 1996年 1997年 1998年 26923.5 35333.9 48197.9 60793.7 71176.6 78973 84402.3 1999年 2000年 2001年 2002年 2003年 2004年 2005年 89677.1 99214.6 109655.2 120332.7 135822.8 159878.3 183084.8 (1)对序列做预处理,判断平稳性 设原序列数据表示为共28个数据,由序列图明显看出序列不平稳,做一阶差分运算后数据平稳。再对数据进行标准化处理,对差分后的数据序列求均值: 标准差 标准化处理公式为 数据预处理前后的对比图和标准化处理后的图如下: 图1 一次差分前后序列图对比 图2 数据标准化后的图 (2)计算自相关和偏相关系数,对序列的模型和阶数进行判断 判断依据是:AR模型自相关系数拖尾,偏相关系数截尾。 MA自相关系数截尾,偏相关系数拖尾。ARMA自相关和偏相关系数都拖尾。自相关系数拖尾可根据点图来判断,只要愈变愈小(k增大时)。对于,常采用的方法是:当k>p时,平均20个中至多有一个使﹥,则认为截尾在k=p处,因为当N很大时,样本偏相关函数(k>p)近似服从正态分布。自相关系数和偏相关系数如图3和4所示。 从图中可以看出自相关系数具有拖尾性,不是MA模型,偏相关系数在1之后≤=0.378,渐进趋于零。所以可以判定序列模型是AR模型,初步判定为1阶。也可认为模型的阶数为2,考虑到2阶计算量也不是很大,所以定为2阶。 处理后序列自相关系数 示于表一。 样本的偏相关函数,…. 示于表二。 表一 自相关系数表 0.6325 0.4502 0.3012 0.2076 0.1254 0.0823 0.1054 0.2177 0.2010 0.1640 0.0483 -0.1.81 -0.2348 -0.2642 -0.2617 -0.2550 -0.2599 -0.2001 -0.0929 -0.2172 表二 偏相关系数表 0.6325 0.

    更多相关内容
  • 对ARMA序列预测、时间序列的统计分析、时间序列的时频分析和时间序列的小波变换等给出了有关分析计算方法,结合MATLAB编程应用,介绍了MATLAB时间序列分析有关函数的功能和用法,阐述了如何利用这些函数解决工程应用...
  • 时间序列分析

    2018-03-09 16:24:35
    优秀时间序列分析教材 优秀时间序列分析教材 优秀时间序列分析教材 优秀时间序列分析教材 优秀时间序列分析教材 优秀时间序列分析教材
  • 时间序列分析.pdf

    2018-01-29 20:58:16
    时间序列分析,对于数据处理很有帮助的书籍,适合初学者
  • 时间序列分析—基于R,王燕,全文有目录。时间序列分析是应用统计学的核心基础课之一,也是计量经济学和统计预测学的核心内容。作为数理统计学的一个专业分支,时间序列分析有它非常特殊的、自成体系的一套分析方法...
  • 基于MATLAB,用神经网络对已有数据进行时间序列分析、建模、预测。内含视频教学,有数据可供练习。(教程缺乏预测部分,但是网上有简单的教学,一查就可以查到)主要可用于数学建模,美赛国赛均可。
  • 最新版恩德斯时间序列分析,高清资源。在对比了基本教材后,个人认为最好的线性时间序列分析教材,非线性还是姚奇伟老师的好
  • 非常经典的时间序列分析:预测与控制的第四版
  • 时间序列分析及应用:R语言 原书第2版 》以易于理解的方式讲述了时间序列模型及其应用 主要内容包括:趋势 平稳时间序列模型 非平稳时间序列模型 模型识别 参数估计 模型诊断 预测 季节模型 时间序列回归模型 异...
  • 时间序列分析-第五章 时间序列的预报资料讲解.pdf时间序列分析-第五章 时间序列的预报资料讲解.pdf时间序列分析-第五章 时间序列的预报资料讲解.pdf时间序列分析-第五章 时间序列的预报资料讲解.pdf时间序列分析-第...
  • Python时间序列分析指南!

    千次阅读 2021-08-01 00:17:54
    Datawhale干货译者:陈超,北京大学,数据派THU 本文约7500字,建议阅读20+分钟本文介绍了时间序列的定义、特征并结合实例给出了时间序列在Python中评价指标和方法。...

     Datawhale干货 

    译者:陈超北京大学,数据派THU

    
    
    
    本文约7500字,建议阅读20+分钟本文介绍了时间序列的定义、特征并结合实例给出了时间序列在Python中评价指标和方法。
    

    时间序列是在规律性时间间隔上记录的观测值序列。本指南将带你了解在Python中分析给定时间序列的特征的全过程。

    主要内容

    1. 什么是时间序列?

    2. 如何在Python中导入时间序列?

    3. 什么是面板数据?

    4. 时间序列可视化

    5. 时间序列的模式

    6. 时间序列的加法和乘法

    7. 如何将时间序列分解?

    8. 平稳和非平稳时间序列

    9. 如何获取平稳的时间序列?

    10. 如何检验平稳性?

    11. 白噪音和平稳序列的差异是什么?

    12. 如何去除时间序列的线性分量?

    13. 如何消除时间序列的季节性?

    14. 如何检验时间序列的季节性?

    15. 如何处理时间序列中的缺失值?

    16. 什么是自回归和偏自回归函数?

    17. 如何计算偏自回归函数?

    18. 滞后图

    19. 如何估计时间序列的预测能力?

    20. 为什么以及怎样使时间序列平滑?

    21. 如何使用Granger因果检验来获知时间序列是否对预测另一个序列帮助?

    22. 下一步是什么?

     

    1. 什么是时间序列?

    时间序列是在规律性时间间隔记录的观测值序列。

    依赖于观测值的频率,典型的时间序列可分为每小时、每天、每周、每月、每季度和每年为单位记录。有时,你可能也会用到以秒或者分钟为单位的时间序列,比如,每分钟用户点击量和访问量等等。

    1.1 为什么要分析时间序列呢?

    因为它是你做序列预测前的一步准备过程。而且,时间序列预测拥有巨大的商业重要性,因为对商业来说非常重要的需求和销量、网站访问人数、股价等都是时间序列数据。

    1.2 所以时间序列分析包括什么内容呢?

    时间序列分析包括理解序列内在本质的多个方面以便于你可更好地了解如何做出有意义并且精确的预测。

    2. 如何在Python中导入时间序列?

    所以怎样导入时间序列数据呢?典型的时间序列数据以.csv格式或者其他表格形式存储,包括两列:日期和测量值。

    让我们用pandas包里的read.csv()读取时间序列数据(一个澳大利亚药品销售的csv文件)作为一个pandas数据框。加入parse_dates=[‘date’]参数将会把日期列解析为日期字段。

    from dateutil.parser import parse
    import matplotlib as mpl
    import matplotlib.pyplot as plt
    import seaborn as sns
    import numpy as np
    import pandas as pd
    plt.rcParams.update({'figure.figsize': (10, 7), 'figure.dpi': 120})
    
    
    # Import as Dataframe
    df = pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/a10.csv', parse_dates=['date'])
    df.head()
    

    数据框时间序列

    此外,你也可以将其导入为date作为索引的pandas序列。你只需要固定pd.read_csv()里的index_col参数。

    ser = pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/a10.csv', parse_dates=['date'], index_col='date')
    ser.head()
    

    时间序列

    注意,在此序列当中,‘value’列的位置高于date以表明它是一个序列。

    3. 什么是面板数据?

    面板数据也是基于时间的数据集。

    差异在于,除了时间序列,它也包括同时测量的一个或多个相关变量。

    通常来看,面板数据当中的列包括了有助于预测Y的解释型变量,假设这些列将在未来预测阶段有用。

    面板数据的例子如下:

    # dataset source: https://github.com/rouseguy
    df = pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/MarketArrivals.csv')
    df = df.loc[df.market=='MUMBAI', :]
    df.head()
    

     

    面板数据

    4. 时间序列可视化

    让我们用matplotlib来对序列进行可视化。

     

    # Time series data source: fpp pacakge in R.
    import matplotlib.pyplot as plt
    df = pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/a10.csv', parse_dates=['date'], index_col='date')
    
    
    # Draw Plot
    def plot_df(df, x, y, title="", xlabel='Date', ylabel='Value', dpi=100):
        plt.figure(figsize=(16,5), dpi=dpi)
        plt.plot(x, y, color='tab:red')
        plt.gca().set(title=title, xlabel=xlabel, ylabel=ylabel)
        plt.show()
    
    
    plot_df(df, x=df.index, y=df.value, title='Monthly anti-diabetic drug sales in  Australia from 1992 to 2008.')
    

     

     时间序列可视化

    因为所有的值都是正值,你可以在Y轴的两侧进行显示此值以强调增长。

    # Import data
    df = pd.read_csv('datasets/AirPassengers.csv', parse_dates=['date'])
    x = df['date'].values
    y1 = df['value'].values
    
    
    # Plot
    fig, ax = plt.subplots(1, 1, figsize=(16,5), dpi= 120)
    plt.fill_between(x, y1=y1, y2=-y1, alpha=0.5, linewidth=2, color='seagreen')
    plt.ylim(-800, 800)
    plt.title('Air Passengers (Two Side View)', fontsize=16)
    plt.hlines(y=0, xmin=np.min(df.date), xmax=np.max(df.date), linewidth=.5)
    plt.show()
    

    航空乘客数据——两侧序列

    因为这是一个月度时间序列,每年遵循特定的重复模式,你可以把每年作为一个单独的线画在同一张图上。这可以让你同时比较不同年份的模式。

    4.1 时间序列的季节图

    # Import Data
    df = pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/a10.csv', parse_dates=['date'], index_col='date')
    df.reset_index(inplace=True)
    
    
    # Prepare data
    df['year'] = [d.year for d in df.date]
    df['month'] = [d.strftime('%b') for d in df.date]
    years = df['year'].unique()
    
    
    # Prep Colors
    np.random.seed(100)
    mycolors = np.random.choice(list(mpl.colors.XKCD_COLORS.keys()), len(years), replace=False)
    
    
    # Draw Plot
    plt.figure(figsize=(16,12), dpi= 80)
    for i, y in enumerate(years):
        if i > 0:        
            plt.plot('month', 'value', data=df.loc[df.year==y, :], color=mycolors[i], label=y)
            plt.text(df.loc[df.year==y, :].shape[0]-.9, df.loc[df.year==y, 'value'][-1:].values[0], y, fontsize=12, color=mycolors[i])
    
    
    # Decoration
    plt.gca().set(xlim=(-0.3, 11), ylim=(2, 30), ylabel='$Drug Sales$', xlabel='$Month$')
    plt.yticks(fontsize=12, alpha=.7)
    plt.title("Seasonal Plot of Drug Sales Time Series", fontsize=20)
    plt.show()
    

    药品销售的季节图

    每年二月会迎来药品销售的急速下降,而在三月会再度上升,接下来的4月又开始下降,以此类推。很明显,该模式在特定的某一年中重复,且年年如此。

    然而,随着年份推移,药品销售整体增加。你可以很好地看到该趋势并且在年份箱线图当中看到它是怎样变化的。同样地,你也可以做一个月份箱线图来可视化月度分布情况。

    4.2 月度(季节性)箱线图和年度(趋势)分布

    你可以季节间隔将数据分组,并看看在给定的年份或月份当中值是如何分布的,以及随时间推移它们是如何比较的。

    # Import Data
    df = pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/a10.csv', parse_dates=['date'], index_col='date')
    df.reset_index(inplace=True)
    
    
    # Prepare data
    df['year'] = [d.year for d in df.date]
    df['month'] = [d.strftime('%b') for d in df.date]
    years = df['year'].unique()
    
    
    # Draw Plot
    fig, axes = plt.subplots(1, 2, figsize=(20,7), dpi= 80)
    sns.boxplot(x='year', y='value', data=df, ax=axes[0])
    sns.boxplot(x='month', y='value', data=df.loc[~df.year.isin([1991, 2008]), :])
    
    
    # Set Title
    axes[0].set_title('Year-wise Box Plot\n(The Trend)', fontsize=18); 
    axes[1].set_title('Month-wise Box Plot\n(The Seasonality)', fontsize=18)
    plt.show()
    

    年度和月度箱线图

    箱线图将年度和月度分布变得很清晰。并且,在阅读箱线图当中,12月和1月明显有更高的药品销售量,可被归因于假期折扣季。

    到目前为止,我们已经看到了识别模式的相似之处。现在怎样才能从通常模式当中找到离群值呢?

    5. 时间序列的模式

    任何时间序列都可以被分解为如下的部分:基线水平+趋势+季节性+误差

    当在时间序列当中观测到增加或降低的斜率时,即可观测到相应的趋势。然而季节性只有在由于季节性因素导致不同的重复模式在规律性的间隔之间被观测到时才能发现。可能是由于当年的特定月份,特定月份的某一天、工作日或者甚至是当天某个时间。

    然而,并不是所有时间序列必须有一个趋势和/或季节性。时间序列可能没有不同的趋势但是有一个季节性。反之亦然。

    所以时间序列可以被看做是趋势、季节性和误差项的整合。

    fig, axes = plt.subplots(1,3, figsize=(20,4), dpi=100)
    pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/guinearice.csv', parse_dates=['date'], index_col='date').plot(title='Trend Only', legend=False, ax=axes[0])
    
    
    pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/sunspotarea.csv', parse_dates=['date'], index_col='date').plot(title='Seasonality Only', legend=False, ax=axes[1])
    
    
    pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/AirPassengers.csv', parse_dates=['date'], index_col='date').plot(title='Trend and Seasonality', legend=False, ax=axes[2])
    

    时间序列中的模式

    另一个需要考虑的方面是循环的行为。当序列当中上升和下降模式并不在固定的日历间隔出现时,就会出现循环的行为。需注意不要混淆循环的效应和季节的效应。

    所以,怎样区分循环的和季节性的模式呢?

    如果模式不是基于固定的日历频率,那它就是循环的。因为,循环效应不像季节性那样受到商业和其他社会经济因素的影响。

    6. 时间序列的加法和乘法

    基于趋势和季节性的本质,时间序列以加法或乘法的形式建模,其中序列里的每个观测值可被表达为成分的和或者积:

    加法时间序列:值=基线水平+趋势+季节性+误差

    乘法时间序列:值=基线水平*趋势*季节性*误差

    7. 怎样分解时间序列的成分?

    你可以通过将序列作基线水平,趋势,季节性指数和残差的加法或乘法组合来实现一个经典的时间序列分解。

    statsmodels包里的seasonal_decompose使用起来非常方便。

    from statsmodels.tsa.seasonal import seasonal_decompose
    from dateutil.parser import parse
    
    
    # Import Data
    df = pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/a10.csv', parse_dates=['date'], index_col='date')
    
    
    # Multiplicative Decomposition
    result_mul = seasonal_decompose(df['value'], model='multiplicative', extrapolate_trend='freq')
    
    
    # Additive Decomposition
    result_add = seasonal_decompose(df['value'], model='additive', extrapolate_trend='freq')
    
    
    # Plot
    plt.rcParams.update({'figure.figsize': (10,10)})
    result_mul.plot().suptitle('Multiplicative Decompose', fontsize=22)
    result_add.plot().suptitle('Additive Decompose', fontsize=22)
    plt.show()
    

    加法和乘法分解

    在序列开始时,设置extrapolate_trend='freq' 来注意趋势和残差中缺失的任何值。

    如果你仔细看加法分解当中的残差,它有一些遗留模式。乘法分解看起来非常随意,这很好。所以理想状况下,乘法分解应该在这种特定的序列当中优先选择。

    趋势,季节性和残差成分的数值输出被存储在result_mul 当中。让我们提取它们并导入数据框中。

    # Extract the Components ----
    # Actual Values = Product of (Seasonal * Trend * Resid)
    df_reconstructed = pd.concat([result_mul.seasonal, result_mul.trend, result_mul.resid, result_mul.observed], axis=1)
    df_reconstructed.columns = ['seas', 'trend', 'resid', 'actual_values']
    df_reconstructed.head()
    

    如果你检查一下seas, trend 和 resid列的乘积,应该确实等于actual_values。

    8. 平稳和非平稳时间序列

    平稳性是时间序列的属性之一。平稳序列的值不是时间的函数。

    也就是说,这种序列的统计属性例如均值,方差和自相关是随时间不变的常数。序列的自相关只是与前置值的相关,之后会详细介绍。

    平稳时间序列也没有季节效应。

    所以如何识别一个序列是否平稳呢?让我们通过实例来展示一下:

    平稳和非平稳时间序列

    上图来自R语言的 TSTutorial。

    所以为什么平稳序列是重要的呢?为什么我要提到它?

    我将展开讲一下,但是要理解它只是有可能通过使用特定的转换方法实现任何时间序列的平稳化。大多数统计预测方法都用于平稳时间序列。预测的第一步通常是做一些转换将非平稳数据转化为平稳数据。

    9. 如何获取平稳的时间序列?

    你可以通过以下步骤实现序列的平稳化:

    1. 差分序列(一次或多次);

    2. 对序列值进行log转换;

    3. 对序列值去n次根式值;

    4. 结合上述方法。

    实现数据平稳化最常见也最方便的方法是对序列进行差分至少一次,直到它变得差不多平稳为止。

    9.1 所以什么是差分?

    如果Y_t是t时刻的Y值,那么第一次差分Y = Yt – Yt-1。在简化的格式当中,差分序列就是从当前值中减去下一个值。

    如果第一次差分不能使数据平稳,你可以第二次差分,以此类推。

    例如,考虑如下序列: [1, 5, 2, 12, 20]

    一次差分: [5-1, 2-5, 12-2, 20-12] = [4, -3, 10, 8]

    二次差分: [-3-4, -10-3, 8-10] = [-7, -13, -2]


    9.2 为什么要在预测之前将非平稳数据平稳化?

    预测平稳序列相对容易,预测也相对更可靠。

    一个重要的原因是自回归预测模型必须是利用序列自身的滞后量作为预测变量的线性回归模型。

    我们知道线性回归在预测变量(X变量)与其他变量不相关时效果最佳。所以序列平稳化也因为移除所有持续的自相关而解决了这个问题,因此使得模型中的预测变量(序列的滞后值)几乎独立。

    现在我们已经建立了序列平稳化非常重要的概念,那怎样检验给定序列是否平稳化呢?

    10. 怎样检验平稳性?

    序列的平稳性可以通过之前我们提到的序列图看出来。

    另外一种方法是将序列分成2或多个连续的部分,计算概要统计量例如均值,方差和自相关。如果统计量显著差异,序列可能不是平稳的。

    尽管如此,你需要一个方法来从量化的角度判断一个给定序列是否平稳。可以通过‘Unit Root Tests单位根检验’来实现。这里有多种变式,但这些检验都是用来检测时间序列是否非平稳并且拥有一个单位根。

    有多种单位根检验的具体应用:

    1. 增广迪基·富勒检验(ADF Test);

    2. 科维亚特夫斯基-菲利普斯-施密特-辛-KPSS检验(趋势平稳性);

    3. 菲利普斯 佩龙检验(PP Test)。

    最常用的是ADF检验,零假设是时间序列只有一个单位根并且非平稳。所以ADF检验p值小于0.05的显著性水平,你拒绝零假设。

    KPSS检验,另一方面,用于检验趋势平稳性。零假设和p值解释与ADH检验相反。下面的代码使用了python中的statsmodels包来做这两种检验。

    from statsmodels.tsa.stattools import adfuller, kpss
    df = pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/a10.csv', parse_dates=['date'])
    
    
    # ADF Test
    result = adfuller(df.value.values, autolag='AIC')
    print(f'ADF Statistic: {result[0]}')
    print(f'p-value: {result[1]}')
    for key, value in result[4].items():
        print('Critial Values:')
        print(f'   {key}, {value}')
    
    
    # KPSS Test
    result = kpss(df.value.values, regression='c')
    print('\nKPSS Statistic: %f' % result[0])
    print('p-value: %f' % result[1])
    for key, value in result[3].items():
        print('Critial Values:')
        print(f'   {key}, {value}')
    ADF Statistic: 3.14518568930674
    p-value: 1.0
    Critial Values:
       1%, -3.465620397124192
    Critial Values:
       5%, -2.8770397560752436
    Critial Values:
       10%, -2.5750324547306476
    
    
    KPSS Statistic: 1.313675
    p-value: 0.010000
    Critial Values:
       10%, 0.347
    Critial Values:
       5%, 0.463
    Critial Values:
       2.5%, 0.574
    Critial Values:
       1%, 0.739
    


    11. 白噪音和平稳序列的差异是什么?

    如平稳序列,白噪音也不是时间的函数,它的均值和方差并不随时间变化。但是它与平稳序列的差异在于,白噪音完全随机,均值为0。

    无论怎样,在白噪音当中是没有特定模式的。如果你将FM广播的声音信号作为时间序列,你在频道之间的频段听到的空白声就是白噪音。

    从数学上来看,均值为0的完全随机的数字序列是白噪音。

    randvals = np.random.randn(1000)
    pd.Series(randvals).plot(title='Random White Noise', color='k')
    

    随机白噪音

    12. 怎样将时间序列去趋势化?

    对时间序列去趋势就是从时间序列当中移除趋势成分。但是如何提取趋势呢?有以下几个方法。

    1. 从时间序列当中减去最优拟合线。最佳拟合线可从以时间步长为预测变量获得的线性回归模型当中获得。对更复杂的模型,你可以使用模型中的二次项(x^2);

    2. 从我们之前提过的时间序列分解当中减掉趋势成分;

    3. 减去均值;

    4. 应用像Baxter-King过滤器(statsmodels.tsa.filters.bkfilter)或者Hodrick-Prescott 过滤器 (statsmodels.tsa.filters.hpfilter)来去除移动的平均趋势线或者循环成分。

    让我们来用一下前两种方法。

    # Using scipy: Subtract the line of best fit
    from scipy import signal
    df = pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/a10.csv', parse_dates=['date'])
    detrended = signal.detrend(df.value.values)
    plt.plot(detrended)
    plt.title('Drug Sales detrended by subtracting the least squares fit', fontsize=16)
    

    通过减去最小二乘拟合来对时间序列去趋势化

    # Using statmodels: Subtracting the Trend Component.
    from statsmodels.tsa.seasonal import seasonal_decompose
    df = pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/a10.csv', parse_dates=['date'], index_col='date')
    result_mul = seasonal_decompose(df['value'], model='multiplicative', extrapolate_trend='freq')
    detrended = df.value.values - result_mul.trend
    plt.plot(detrended)
    plt.title('Drug Sales detrended by subtracting the trend component', fontsize=16)
    

    通过减去趋势成分来去趋势化

    13. 怎样对时间序列去季节化?

    这里有多种方法对时间序列去季节化。以下就有几个:

    1. 取一个以长度为季节窗口的移动平均线。这将在这个过程中使序列变得平滑;

    2. 序列季节性差分(从当前值当中减去前一季节的值);

    3. 将序列值除以从STL分解当中获得的季节性指数。

    如果除以季节性指数后仍没办法得到良好的结果,再试一下序列对数转换然后再做。你之后可以通过去指数恢复到原始尺度。

    # Subtracting the Trend Component.
    df = pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/a10.csv', parse_dates=['date'], index_col='date')
    
    
    # Time Series Decomposition
    result_mul = seasonal_decompose(df['value'], model='multiplicative', extrapolate_trend='freq')
    
    
    # Deseasonalize
    deseasonalized = df.value.values / result_mul.seasonal
    
    
    # Plot
    plt.plot(deseasonalized)
    plt.title('Drug Sales Deseasonalized', fontsize=16)
    plt.plot()
    

    时间序列去季节化

    14. 怎样检验时间序列的季节性?

    常见的方法是绘制序列并在固定的时间间隔内检查可重复的模式。所以,季节性的类型由钟表或日历决定:

    1. 一天的每个小时;

    2. 一月的每天;

    3. 每周;

    4. 每月;

    5. 每年。

    然而,如果你想要一个更权威的季节性检验,使用自回归函数(ACF)图。更多关于自回归的信息将在下一部分介绍。但是当强季节性模式出现时,ACF图通常揭示了在季节窗的倍数处明显的重复峰值。

    例如,药品销售时间序列是每年都有重复模式的一个月度序列。所以,你可以看到第12,24和36条线等的峰值。

    我必须警告你在现实世界的数据集当中,这样强的模式很难见到,并且有可能被各种噪音所扭曲,所以你需要一双仔细的眼睛来捕获这些模式。

    from pandas.plotting import autocorrelation_plot
    df = pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/a10.csv')
    
    
    # Draw Plot
    plt.rcParams.update({'figure.figsize':(9,5), 'figure.dpi':120})
    autocorrelation_plot(df.value.tolist())
    

    自相关图

    除此之外,如果你想做统计检验,CHT检验可以检验季节性差异是否对序列平稳化有必要。

    15. 如何处理时间序列当中的缺失值?

    有时,你的时间序列会有缺失日期/时间。那意味着,数据没有被捕获或者在那段时间内不可用。那些天的测量值有可能为0,你可以把那些时间段填充0。

    其次,当处理时间序列时,你通常不应该用序列均值来替代缺失值,尤其是序列非平稳的时候,一个快捷粗略的处理方法来说你应该做的是向前填充之前的值。

    然而,依赖于序列的本质,你想要在得出结论之前尝试多种方法。有效的缺失值处理方法有:

    • 向后填充;

    • 线性内插;

    • 二次内插;

    • 最邻近平均值;

    • 对应季节的平均值。

    为了衡量缺失值的表现,我在时间序列当中手动引入缺失值,使用上述方法处理并衡量处理值和真实值之间的均方误差。

    # # Generate dataset
    from scipy.interpolate import interp1d
    from sklearn.metrics import mean_squared_error
    df_orig = pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/a10.csv', parse_dates=['date'], index_col='date').head(100)
    df = pd.read_csv('datasets/a10_missings.csv', parse_dates=['date'], index_col='date')
    
    
    fig, axes = plt.subplots(7, 1, sharex=True, figsize=(10, 12))
    plt.rcParams.update({'xtick.bottom' : False})
    
    
    ## 1. Actual -------------------------------
    df_orig.plot(title='Actual', ax=axes[0], label='Actual', color='red', style=".-")
    df.plot(title='Actual', ax=axes[0], label='Actual', color='green', style=".-")
    axes[0].legend(["Missing Data", "Available Data"])
    
    
    ## 2. Forward Fill --------------------------
    df_ffill = df.ffill()
    error = np.round(mean_squared_error(df_orig['value'], df_ffill['value']), 2)
    df_ffill['value'].plot(title='Forward Fill (MSE: ' + str(error) +")", ax=axes[1], label='Forward Fill', style=".-")
    
    
    ## 3. Backward Fill -------------------------
    df_bfill = df.bfill()
    error = np.round(mean_squared_error(df_orig['value'], df_bfill['value']), 2)
    df_bfill['value'].plot(title="Backward Fill (MSE: " + str(error) +")", ax=axes[2], label='Back Fill', color='firebrick', style=".-")
    
    
    ## 4. Linear Interpolation ------------------
    df['rownum'] = np.arange(df.shape[0])
    df_nona = df.dropna(subset = ['value'])
    f = interp1d(df_nona['rownum'], df_nona['value'])
    df['linear_fill'] = f(df['rownum'])
    error = np.round(mean_squared_error(df_orig['value'], df['linear_fill']), 2)
    df['linear_fill'].plot(title="Linear Fill (MSE: " + str(error) +")", ax=axes[3], label='Cubic Fill', color='brown', style=".-")
    
    
    ## 5. Cubic Interpolation --------------------
    f2 = interp1d(df_nona['rownum'], df_nona['value'], kind='cubic')
    df['cubic_fill'] = f2(df['rownum'])
    error = np.round(mean_squared_error(df_orig['value'], df['cubic_fill']), 2)
    df['cubic_fill'].plot(title="Cubic Fill (MSE: " + str(error) +")", ax=axes[4], label='Cubic Fill', color='red', style=".-")
    
    
    # Interpolation References:
    # https://docs.scipy.org/doc/scipy/reference/tutorial/interpolate.html
    # https://docs.scipy.org/doc/scipy/reference/interpolate.html
    
    
    ## 6. Mean of 'n' Nearest Past Neighbors ------
    def knn_mean(ts, n):
        out = np.copy(ts)
        for i, val in enumerate(ts):
            if np.isnan(val):
                n_by_2 = np.ceil(n/2)
                lower = np.max([0, int(i-n_by_2)])
                upper = np.min([len(ts)+1, int(i+n_by_2)])
                ts_near = np.concatenate([ts[lower:i], ts[i:upper]])
                out[i] = np.nanmean(ts_near)
        return out
    
    
    df['knn_mean'] = knn_mean(df.value.values, 8)
    error = np.round(mean_squared_error(df_orig['value'], df['knn_mean']), 2)
    df['knn_mean'].plot(title="KNN Mean (MSE: " + str(error) +")", ax=axes[5], label='KNN Mean', color='tomato', alpha=0.5, style=".-")
    
    
    ## 7. Seasonal Mean ----------------------------
    def seasonal_mean(ts, n, lr=0.7):
        """
        Compute the mean of corresponding seasonal periods
        ts: 1D array-like of the time series
        n: Seasonal window length of the time series
        """
        out = np.copy(ts)
        for i, val in enumerate(ts):
            if np.isnan(val):
                ts_seas = ts[i-1::-n]  # previous seasons only
                if np.isnan(np.nanmean(ts_seas)):
                    ts_seas = np.concatenate([ts[i-1::-n], ts[i::n]])  # previous and forward
                out[i] = np.nanmean(ts_seas) * lr
        return out
    
    
    df['seasonal_mean'] = seasonal_mean(df.value, n=12, lr=1.25)
    error = np.round(mean_squared_error(df_orig['value'], df['seasonal_mean']), 2)
    df['seasonal_mean'].plot(title="Seasonal Mean (MSE: " + str(error) +")", ax=axes[6], label='Seasonal Mean', color='blue', alpha=0.5, style=".-")
    

     缺失值处理

    你也可以根据你想实现的精确程度考虑接下来的方法。

    1. 如果你有解释变量,可以使用像随机森林或k-邻近算法的预测模型来预测它。

    2. 如果你有足够多的过去观测值,可以预测缺失值。

    3. 如果你有足够的未来观测值,回测缺失值。

    4. 从之前的周期预测相对应的部分。


    16. 什么是自相关和偏自相关函数?

    自相关是序列和自己滞后量的简单相关。如果序列显著自相关,均值和序列之前的值(滞后量)可能对预测当前值有帮助。

    偏自相关也会传递相似的信息但是它传递的是序列和它滞后量的纯粹相关,排除了其他中间滞后量对相关的贡献。

    from statsmodels.tsa.stattools import acf, pacf
    from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
    
    
    df = pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/a10.csv')
    
    
    # Calculate ACF and PACF upto 50 lags
    # acf_50 = acf(df.value, nlags=50)
    # pacf_50 = pacf(df.value, nlags=50)
    
    
    # Draw Plot
    fig, axes = plt.subplots(1,2,figsize=(16,3), dpi= 100)
    plot_acf(df.value.tolist(), lags=50, ax=axes[0])
    plot_pacf(df.value.tolist(), lags=50, ax=axes[1])
    

    自相关函数 和 偏自相关函数

    17. 怎样计算偏自相关函数?

    怎样计算偏自相关呢?

    序列滞后量(k)的偏自相关是Y的自回归方程中滞后量的系数。Y的自回归方程就是Y及其滞后量作为预测项的线性回归。

    For Example, if Y_t is the current series and Y_t-1 is the lag 1 of Y, then the partial autocorrelation of lag 3 (Y_t-3) is the coefficient $\alpha_3$ of Y_t-3 in the following equation:

    例如,如果Y_t是当前的序列,Y_t-1是Y的滞后量1,那么滞后量3(Y_t-3)的偏自相关就是下面方程中Y_t-3的系数:

    自回归方程


    18. 滞后图

    滞后图是一个时间序列对其自身滞后量的散点图。它通常用于检查自相关。如果序列中存在如下所示的任何模式,则该序列是自相关的。如果没有这样的模式,这个序列很可能是随机的白噪声。

    在下面太阳黑子面积时间序列的例子当中,随着n_lag增加,图越来越分散。

    from pandas.plotting import lag_plot
    plt.rcParams.update({'ytick.left' : False, 'axes.titlepad':10})
    
    
    # Import
    ss = pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/sunspotarea.csv')
    a10 = pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/a10.csv')
    
    
    # Plot
    fig, axes = plt.subplots(1, 4, figsize=(10,3), sharex=True, sharey=True, dpi=100)
    for i, ax in enumerate(axes.flatten()[:4]):
        lag_plot(ss.value, lag=i+1, ax=ax, c='firebrick')
        ax.set_title('Lag ' + str(i+1))
    
    
    fig.suptitle('Lag Plots of Sun Spots Area \n(Points get wide and scattered with increasing lag -> lesser correlation)\n', y=1.15)    
    
    
    fig, axes = plt.subplots(1, 4, figsize=(10,3), sharex=True, sharey=True, dpi=100)
    for i, ax in enumerate(axes.flatten()[:4]):
        lag_plot(a10.value, lag=i+1, ax=ax, c='firebrick')
        ax.set_title('Lag ' + str(i+1))
    
    
    fig.suptitle('Lag Plots of Drug Sales', y=1.05)    
    plt.show()
    

     

    药品销售的滞后图

    太阳黑子的滞后图

    19. 怎样估计时间序列的预测能力?

    时间序列越有规律性和重复性的模式,越容易被预测。“近似熵”可用于量化时间序列波动的规律性和不可预测性。

    近似熵越高,预测越难。另一个更好的选项是“样本熵”。

    样本熵类似与近似熵,但是在估计小时间序列的复杂性上结果更一致。例如,较少样本点的随机时间序列 “近似熵”可能比一个更规律的时间序列更低,然而更长的时间序列可能会有一个更高的“近似熵”。

    样本熵可以很好地处理这个问题。请看如下演示:

    # https://en.wikipedia.org/wiki/Approximate_entropy
    ss = pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/sunspotarea.csv')
    a10 = pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/a10.csv')
    rand_small = np.random.randint(0, 100, size=36)
    rand_big = np.random.randint(0, 100, size=136)
    
    
    def ApEn(U, m, r):
        """Compute Aproximate entropy"""
        def _maxdist(x_i, x_j):
            return max([abs(ua - va) for ua, va in zip(x_i, x_j)])
    
    
        def _phi(m):
            x = [[U[j] for j in range(i, i + m - 1 + 1)] for i in range(N - m + 1)]
            C = [len([1 for x_j in x if _maxdist(x_i, x_j) <= r]) / (N - m + 1.0) for x_i in x]
            return (N - m + 1.0)**(-1) * sum(np.log(C))
    
    
        N = len(U)
        return abs(_phi(m+1) - _phi(m))
    
    
    print(ApEn(ss.value, m=2, r=0.2*np.std(ss.value)))     # 0.651
    print(ApEn(a10.value, m=2, r=0.2*np.std(a10.value)))   # 0.537
    print(ApEn(rand_small, m=2, r=0.2*np.std(rand_small))) # 0.143
    print(ApEn(rand_big, m=2, r=0.2*np.std(rand_big)))     # 0.716
    0.6514704970333534
    0.5374775224973489
    0.0898376940798844
    0.7369242960384561
    # https://en.wikipedia.org/wiki/Sample_entropy
    def SampEn(U, m, r):
        """Compute Sample entropy"""
        def _maxdist(x_i, x_j):
            return max([abs(ua - va) for ua, va in zip(x_i, x_j)])
    
    
        def _phi(m):
            x = [[U[j] for j in range(i, i + m - 1 + 1)] for i in range(N - m + 1)]
            C = [len([1 for j in range(len(x)) if i != j and _maxdist(x[i], x[j]) <= r]) for i in range(len(x))]
            return sum(C)
    
    
        N = len(U)
        return -np.log(_phi(m+1) / _phi(m))
    
    
    print(SampEn(ss.value, m=2, r=0.2*np.std(ss.value)))      # 0.78
    print(SampEn(a10.value, m=2, r=0.2*np.std(a10.value)))    # 0.41
    print(SampEn(rand_small, m=2, r=0.2*np.std(rand_small)))  # 1.79
    print(SampEn(rand_big, m=2, r=0.2*np.std(rand_big)))      # 2.42
    0.7853311366380039
    0.41887013457621214
    inf
    2.181224235989778
    
    
    del sys.path[0]
    


    20. 为何要以及怎样对时间序列进行平滑处理?

    时间序列平滑处理可能在以下场景有用:

    • 在信号当中减小噪声的影响从而得到一个经过噪声滤波的序列近似。

    • 平滑版的序列可用于解释原始序列本身的特征。

    • 趋势更好地可视化。

    怎样对序列平滑处理?让我们讨论一下以下方法:

    1. 使用移动平均;

    2. 做LOESS光滑(局部回归);

    3. 做LOWESS光滑(局部加权回归)。

    移动均值就是定义宽度的滚动窗口的均值。但是你必须明智地选择窗口宽度,因为大范围窗口可能会造成序列过度平滑。例如,窗口大小等于季节持续时间时(例如:12为月度序列),将有效地抵消季节效应。

    LOESS,局部回归的简写,适应于每个点邻近的多元回归。可通过statsmodels包使用,你可以使用frac参数确定被纳入拟合回归模型的邻近数据点的百分比来控制平滑度。

    下载数据集: Elecequip.csv

    from statsmodels.nonparametric.smoothers_lowess import lowess
    plt.rcParams.update({'xtick.bottom' : False, 'axes.titlepad':5})
    
    
    # Import
    df_orig = pd.read_csv('datasets/elecequip.csv', parse_dates=['date'], index_col='date')
    
    
    # 1. Moving Average
    df_ma = df_orig.value.rolling(3, center=True, closed='both').mean()
    
    
    # 2. Loess Smoothing (5% and 15%)
    df_loess_5 = pd.DataFrame(lowess(df_orig.value, np.arange(len(df_orig.value)), frac=0.05)[:, 1], index=df_orig.index, columns=['value'])
    df_loess_15 = pd.DataFrame(lowess(df_orig.value, np.arange(len(df_orig.value)), frac=0.15)[:, 1], index=df_orig.index, columns=['value'])
    
    
    # Plot
    fig, axes = plt.subplots(4,1, figsize=(7, 7), sharex=True, dpi=120)
    df_orig['value'].plot(ax=axes[0], color='k', title='Original Series')
    df_loess_5['value'].plot(ax=axes[1], title='Loess Smoothed 5%')
    df_loess_15['value'].plot(ax=axes[2], title='Loess Smoothed 15%')
    df_ma.plot(ax=axes[3], title='Moving Average (3)')
    fig.suptitle('How to Smoothen a Time Series', y=0.95, fontsize=14)
    plt.show()
    

    平滑时间序列

    21. 如何使用Granger因果检验得知是否一个时间序列有助于预测另一个序列?

     

    Granger因果检验被用于检验是否一个时间序列可以预测另一个序列。Granger因果检验是如何工作的?

    它基于如果X引起Y的变化,Y基于之前的Y值和之前的X值的预测效果要优于仅基于之前的Y值的预测效果。

    所以需要了解Granger因果检验不能应用于Y的滞后量引起Y自身的变化的情况,而通常仅用于外源变量(不是Y的滞后量)。

    它在statsmodel包中得到了很好的实现。它采纳2列数据的二维数组作为主要参数,被预测值是第一列,而预测变量(X)在第二列。

    零假设检验:第二列的序列不能Granger预测第一列数据。如果p值小于显著性水平(0.05),你可以拒绝零假设并得出结论:X的滞后量确实有用。

    第二个参数maxlag决定有多少Y的滞后量应该纳入检验当中。

    from statsmodels.tsa.stattools import grangercausalitytests
    df = pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/a10.csv', parse_dates=['date'])
    df['month'] = df.date.dt.month
    grangercausalitytests(df[['value', 'month']], maxlag=2)
    Granger Causality
    number of lags (no zero) 1
    ssr based F test:         F=54.7797 , p=0.0000  , df_denom=200, df_num=1
    ssr based chi2 test:   chi2=55.6014 , p=0.0000  , df=1
    likelihood ratio test: chi2=49.1426 , p=0.0000  , df=1
    parameter F test:         F=54.7797 , p=0.0000  , df_denom=200, df_num=1
    
    
    Granger Causality
    number of lags (no zero) 2
    ssr based F test:         F=162.6989, p=0.0000  , df_denom=197, df_num=2
    ssr based chi2 test:   chi2=333.6567, p=0.0000  , df=2
    likelihood ratio test: chi2=196.9956, p=0.0000  , df=2
    parameter F test:         F=162.6989, p=0.0000  , df_denom=197, df_num=2
    

    在上述例子当中,实际上所有检验的p值只能无限接近于0。所以“月份”实际上可以用于预测航空乘客的数量。


    22. 下一步是什么?

    这就是我们现在要说的。我们从非常基础的内容开始,理解了时间序列不同特征。一旦分析完成之后,接下来的一步是预测。

    原文标题:

    Time Series Analysis in Python – A Comprehensive Guide with Examples

    原文链接:

    https://www.machinelearningplus.com/time-series/time-series-analysis-python/

    编辑:黄继彦

    干货学习,三连

    展开全文
  • 时间序列分析及应用

    2016-12-30 14:42:39
    本书以易于理解的方式讲述了时间序列模型及其应用,主要内容包括:趋势、平稳时间序列模型、非平稳时间序列模型、模型识别、参数估计、模型诊断、预测、季节模型、时间序列回归模型、异方差时间序列模型、谱分析入门...
  • 【BI学习心得09-时间序列分析

    千次阅读 2021-01-02 20:20:45
    时间序列实战 5.1statsmodels工具 5.2时间序列分析与回归分析的区别 5.3ARMA实战 5.3.1ARMA工具对沪市指数进行预测 5.4使用LSTM进行时间序列预测 参考资料 写在前面的话 如果你是一个股民,某只股票的股价就是一类...


    写在前面的话

    如果你是一个股民,某只股票的股价就是一类时序数据,其记录着每个时间点该股票的股价。
    如果你是一个运维人员,监控数据是一类时序数据,例如对于机器的CPU的监控数据,就是记录着每个时间点机器上CPU的实际消耗值。

    这个世界是由数据构成的,在这个世界上存在的每个物体,每时每刻都在产生着数据。而对这些数据的挖掘和利用,在这个时代,正在默默的改变人们的生活方式。例如通过可穿戴设备对个人健康的管理,就是通过设备不断采集你的个人健康数据,例如心跳、体温等等,收集完数据后套用模型计算来评估你的健康度。

    如果你的视野和想象空间足够大,你会发现你能够挖掘并利用的数据充斥在你所生活的环境中。这些能够产生数据的对象,会包括你的手机、汽车、空调、冰箱等等。当前比较火热的物联网的核心思想,其实就是构建一个可以让所有物体生产数据并挖掘其价值的网络。而通过这个网络采集的数据,就是典型的时序数据。

    时序数据用于描述一个物体在历史的时间维度上的状态变化信息,而对于时序数据的分析,就是尝试掌握并把控其变化的规律的过程。随着物联网、大数据和人工智能技术的发展,时序数据也呈一个爆发式的增长。而为了更好的支持这类数据的存储和分析,在市场上衍生出了多种多样的新兴的数据库产品。这类数据库产品的发明都是为了解决传统关系型数据库在时序数据存储和分析上的不足和缺陷,这类产品被统一归类为时序数据库。

    1.时间序列

    1.1时间序列的概念

    时间序列是按照时间排序的一组随机变量,它通常是在相等间隔的时间段内依照给定的采样率对某种潜在过程进行观测的结果。时间序列数据本质上反映的是某个或者某些随机变量随时间不断变化的趋势,而时,间序列预测方法的核心就是从数据中挖掘出这种规律,并利用其对将来的数据做出估计。

    构成要素:长期趋势,季节变动,循环变动,不规则变动。

    1)长期趋势( T )现象在较长时期内受某种根本性因素作用而形成的总的变动趋势。
    2)季节变动( S )现象在一年内随着季节的变化而发生的有规律的周期性变动。
    3)循环变动( C )现象以若干年为周期所呈现出的波浪起伏形态的有规律的变动。
    4)不规则变动(I )是一种无规律可循的变动,包括严格的随机变动和不规则的突发性影响很大的变动两种类型。
    在这里插入图片描述

    时间序列在金融、经济、商业领域拥有广泛的应用:

    • 机器学习模型,包括AR、MA、ARMA、ARIMA
    • 神经网络模型,用LSTM进行时间序列预测

    1.2时间序列的不同分类

    时间序列是按时间顺序排列的、随时间变化且相互关联的数据序列。分析时间序 列的方法构成数据分析的一个重要领域,即时间序列分析。 时间序列根据所研究的依据不同,可有不同的分类。

    1.按所研究的对象的多少分,有一元时间序列和多元时间序列。

    2.按时间的连续性可将时间序列分为离散时间序列和连续时间序列两种。

    3.按序列的统计特性分,有平稳时间序列和非平稳时间序列。如果一个时间序列的概率分布与时间t无关,则称该序列为严格的(狭义的)平稳时间序列。如果序列的 一、二阶矩存在,而且对任意时刻t满足:

    (1)均值为常数

    (2)协方差为时间间隔 τ \small \tau τ的函数。 则称该序列为宽平稳时间序列,也叫广义平稳时间序列。我们以后所研究的时间序列主 要是宽平稳时间序列。

    4.按时间序列的分布规律来分,有高斯型时间序列和非高斯型时间序列。

    2.移动平均法

    移动平均法 可以作为一种数据平滑的方式 ,以每天的气温数据为例,今天的天气可能与过去的十天的气温有线性关系;或者有的人对食物有一种节俭的美德,他们做的饭菜能看出有些是上一顿的,当然也有一部分是今天的做的,再假设隔两顿的都被倒掉了,并且每天都是这样的,那么这碗饭菜可能就是一部分上一顿的再加上一部分今天现做的,这就是一个一阶的移动平均。

    移动平均法是根据时间序列资料逐渐推移,依次计算包含一定项数的时序平均数, 以反映长期趋势的方法。当时间序列的数值由于受周期变动和不规则变动的影响,起伏 较大,不易显示出发展趋势时,可用移动平均法,消除这些因素的影响,分析、预测序列的长期趋势。 移动平均法有简单移动平均法,加权移动平均法,趋势移动平均法等。

    2.1简单移动平均法

    在这里插入图片描述
    近N 期序列值的平均值作为未来各期的预测结果。一般 N 的取值范围: 5≤N≤ 200。当历史序列的基本趋势变化不大且序列中随机变动成分较多时,N 的 取值应较大一些。否则 N 的取值应小一些。在有确定的季节变动周期的资料中,移动平均的项数应取周期长度。选择佳 N 值的一个有效方法是,比较若干模型的预测误 差。预测标准误差小者为好。

    简单移动平均法只适合做近期预测,而且是预测目标的发展趋势变化不大的情况。 如果目标的发展趋势存在其它的变化,采用简单移动平均法就会产生较大的预测偏差和滞后

    例1 某企业 1月~11月份的销售收入时间序列如表1所示。使用一次简单滑动平均法预测12月份的销售收入。

    在这里插入图片描述
    在这里插入图片描述

    2.2加权移动平均法

    在简单移动平均公式中,每期数据在求平均时的作用是等同的。但是,每期数据所包含的信息量不一样,近期数据包含着更多关于未来情况的信心。因此,把各期数据等同看待是不尽合理的,应考虑各期数据的重要性,对近期数据给予较大的权重,这就 是加权移动平均法的基本思想。

    在这里插入图片描述
    例 2 我国 1979~1988 年原煤产量如表 2 所示,试用加权移动平均法预测 1989 年 的产量

    在这里插入图片描述
    在这里插入图片描述
    在加权移动平均法中, w t \small w_{t} wt的选择,同样具有一定的经验性。一般的原则是:近期 数据的权数大,远期数据的权数小。至于大到什么程度和小到什么程度,则需要按照预 测者对序列的了解和分析来确定。

    2.3趋势移动平均法

    简单移动平均法和加权移动平均法,在时间序列没有明显的趋势变动时,能够准确 反映实际情况。但当时间序列出现直线增加或减少的变动趋势时,用简单移动平均法和 加权移动平均法来预测就会出现滞后偏差。因此,需要进行修正,修正的方法是作二次 移动平均,利用移动平均滞后偏差的规律来建立直线趋势的预测模型。这就是趋势移动平均法。 一次移动的平均数为

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    例 3 我国 1965~1985 年的发电总量如表 3 所示,试预测 1986 年和 1987 年的发 电总量。
    在这里插入图片描述
    解 由散点图 1 可以看出,发电总量基本呈直线上升趋势,可用趋势移动平均法 来预测。
    在这里插入图片描述
    趋势移动平均法对于同时存在直线趋势与周期波动的序列,是一种既能反映趋势变 化,又可以有效地分离出来周期变动的方法。

    3.指数平滑法

    指数平滑法是在移动平均法基础上发展起来的一种时间序列分析预测法,它是通过计算指数平滑值,配合一定的时间序列预测模型对现象的未来进行预测,其原理是任一期的指数平滑值都是本期实际观察值与前一期指数平滑值的加权平均。利用修匀技术,削弱短期随机波动对序列的影响,使序列平滑化,从而显示出长期趋势变化的规律。

    用序列过去值的加权均值来预测将来的值,序列中近期的数据被赋以较大的权重,远期的数据被赋以较小的权重。理由是一般情况下,某一变量值对其后继行为的影响作用是逐渐衰减的。

    3.1基础知识

    1. 前提假设:时间序列分析一般假设我们获得的数据在时域上具有一定的相互依赖关系,例如股票价格在t时刻很高,那么在t+1时刻价格也会比较高(跌停才10%);如果股票价格在一段时间内获得稳定的上升,那么在接下来的一段时间内延续上升趋势的概率也会比较大。

    2. 目标:(1)发现这种隐含的依赖关系,并增加我们对此类时间序列的理解;(2)对未观测到的或者尚未发生的时间序列进行预测。

    我们认为时间序列由两部分组成:有规律的时间序列(即有依赖关系)+噪声(无规律,无依赖)。所以,接下来要做的就是过滤噪声:

    最简单的 过 滤 噪 声 \color{red}过滤噪声 的方法是:取平均。

    3.2简单滑动平均(rolling mean)

    1. 特点:当窗口取得越长,噪声被去除的就越多,我们得到的信号就越平稳;但同时,信号的有用部分丢失原有特性的可能性就越大,而我们希望发现的规律丢失的可能性就越大。

    2. 缺点:(1)我们要等到至少获得T个信号才能进行平均,那么得到的新的信号要比原始信号短;(2)在得到S_t的时候,我们只有距离t最近的T个原始信号。但在原始信号中,可能信号之间的相互依赖关系会跨越非常长的时间长度,比如X_1可能会对X_100会产生影响,这样滑动平均就会削弱甚至隐藏这种依赖关系。

    3.2指数平均(EXPMA)

    接下来介绍一种稍微复杂但能克服以上缺点并且在现实中应用也更加广泛的方法:指数平均 (exponential smoothing,也叫exponential weighted moving average ),这种平均方法的一个重要特征就是,S_t与之前产生的所有信号有关,并且距离越近的信号所占权重越大。

    3.2.1一阶指数平滑

    当时间数列无明显的趋势变化,可用一次指数平滑预测。

    一阶指数平滑实际就是对历史数据的加权平均,它可以用于任何一种 没 有 明 显 函 数 规 律 但 确 实 存 在 某 种 前 后 关 联 \color{red}没有明显函数规律但确实存在某种前后关联 的时间序列的 短 期 预 测 \color{red}短期预测 。其预测公式为:(任一期的指数平滑值都是本期实际观察值前一期指数平滑值的加权平均)

    y t + 1 ′ = a ∗ y t + ( 1 − a ) ∗ y t ′    或 者 a l t = " S t ( 1 ) = a ∗ y t + ( 1 − a ) ∗ S t − 1 ( 1 ) " y_{t+1}'=a*y_{t}+(1-a)*y_{t}' \ \ 或者alt="S_{t}^{(1)}=a*y_{t}+(1-a)*S_{t-1}^{(1)}" yt+1=ayt+(1a)yt  alt="St(1)=ayt+(1a)St1(1)"

    a:平滑系数
    yt+1’:t+1期的预测值,即本期(t期)的平滑值
    St ; yt:t期的实际值;
    yt’:t期的预测值,即上期的平滑值St-1 。 本 期 的 平 滑 值 = 下 期 的 预 测 值 \color{red}本期的平滑值 = 下期的预测值 =

    该公式又可以写作:

    y t + 1 ′ = y t ′ + a ∗ ( y t − y t ′ ) y_{t+1}'=y_{t}'+a*(y_{t}-y_{t}') yt+1=yt+a(ytyt)

    可见:下期预测值是本期预测值与以a为折扣的本期实际值与预测值误差之和。

    1. 最突出的优点:方法非常简单,甚至只要样本末期的平滑值,就可以得到预测结果。
    2. 一次指数平滑的特点是:能够跟踪数据变化。这一特点所有指数都具有。预测过程中添加最新的样本数据后,新数据应取代老数据的地位,老数据会逐渐居于次要的地位,直至被淘汰。这样,预测值总是反映最新的数据结构
    3. 一次指数平滑有局限性:第一,预测值不能反映趋势变动、季节波动等有规律的变动;第二,这种方法多适用于短期预测,而不适合作中长期的预测;第三,由于 预 测 值 是 历 史 数 据 的 均 值 \color{red}预测值是历史数据的均值 ,因此与实际序列的变化相比有 滞 后 现 象 \color{red}滞后现象
    4. 平滑系数:指数平滑预测是否理想,很大程度上取决于平滑系数。指数平滑法对实际序列具有平滑作用,平滑系数a 越小,平滑作用越强,但对实际数据的变动反应较迟缓。

    EViews提供两种确定指数平滑系数的方法 自 动 给 定 和 人 工 确 定 \color{red}自动给定和人工确定 。选择自动给定,系统将按照 预 测 误 差 平 方 和 最 小 原 则 \color{red}预测误差平方和最小原则 自动确定系数。如果系数接近1,说明该序列近似纯随机序列,这时最新的观测值就是最理想的预测值。出于预测的考虑,有时系统给定的系数不是很理想,用户需要自己指定平滑系数值。一般来说:

    (1)如果序列变化比较平缓,平滑系数值应该比较小,比如小于0.1;
    (2)如果序列变化比较剧烈,平滑系数值可以取得大一些,如0.3~0.5;
    (3)若平滑系数值大于0.5才能跟上序列的变化,表明序列有很强的趋势,不能采用一次指数平滑进行预测。

    1. 缺点:(1)只考虑历史平均,不考虑变化趋势;(2)在实际序列的线性变动部分,指数平滑值序列出现一定的滞后偏差,偏差程度随着平滑系数a 的增大而减少,但当时间序列的变动出现直线趋势时,用一次指数平滑法来进行预测仍将存在明显的滞后偏差。因此,也需要进行修正。

    修 正 的 方 法 \color{red}修正的方法 也是在一次指数平滑的基础上再进行二次指数平滑,利用滞后偏差的规律找出曲线的发展方向和发展趋势,然后建立直线趋势预测模型,故称为二次指数平滑法。

    3.2.2二次指数平滑

    二次指数平滑是对一次指数平滑的再平滑,同时考虑历史平均和变化趋势。它适用于具线性趋势的时间数列

    我们可以看到,虽然一次指数平均在产生新的数列的时候考虑了所有的历史数据,但是仅仅考虑其静态值,即没有考虑时间序列当前的变化趋势。如果当前的股票处于上升趋势,那么当我们对明天的股票进行预测的时候,好的预测值不仅仅是对历史数据进行”平均“,而且要考虑到当前数据变化的上升趋势。同时考虑历史平均和变化趋势,这便是二阶指数平均,公式:

    y t + m = ( 2 + a m 1 − a ) y t ′ − ( 1 + a m 1 − a ) y t = ( 2 y t ′ − y t ) + m ( y t ′ − y t ) a 1 − a y_{t+m}=(2+\frac{am}{1-a})y_{t}'-(1+\frac{am}{1-a})y_{t}=(2y_{t}'-y_{t})+m(y_{t}'-y_{t})\frac{a}{1-a} yt+m=(2+1aam)yt(1+1aam)yt=(2ytyt)+m(ytyt)1aa

    式中,
    y t = a ∗ y t − 1 ′ + ( 1 − a ) ∗ y t − 1 y_{t}=a*y_{t-1}'+(1-a)*y_{t-1} yt=ayt1+(1a)yt1

    也就是:

    Y ^ t + T = a t + b t ∗ T S t ( 2 ) = a S t ( 1 ) + ( 1 − a ) S t − 1 ( 2 ) ( 2 ) \begin{array}{lcl} \hat{Y}_{t+T} &=& a_t+b_t * T \tag{$2$} \\ S_t^{(2)} &=& aS_t^{(1)}+ (1-a)S_{t-1}^{(2)} \\ \end{array} Y^t+TSt(2)==at+btTaSt(1)+(1a)St1(2)(2)
    { a t = 2 S t ( 1 ) − S t ( 2 ) b t = a 1 − a ( S t ( 1 ) − S t ( 2 ) ) ( 3 ) \begin{cases} a_t &=& 2S_t^{(1)}-S_t^{(2)} \\ b_t &=& \frac{a}{1-a}(S_t^{(1)}-S_t^{(2)}) \tag{$3$} \end{cases} {atbt==2St(1)St(2)1aa(St(1)St(2))(3)

    Y ^ t + T \hat{Y}_{t+T} Y^t+T:第t+T期预测值;
    T T T:由t期向后推移期数;

    显然,二次指数平滑是一直线方程,其截距为: ( 2 y t ′ − y t ) (2yt'-yt) (2ytyt),斜率为: ( y t ’ − y t ) a ( 1 − a ) \frac{(yt’-yt) a}{(1-a)} (1a)(ytyt)a,自变量为预测天数。

    在一次指数平滑的基础上得二次指数平滑 的计算公式为:

    S t ( 2 ) = a S t ( 1 ) + ( 1 − a ) S t − 1 ( 2 ) S_t^{(2)} = aS_t^{(1)}+ (1-a)S_{t-1}^{(2)} St(2)=aSt(1)+(1a)St1(2)

    S t ( 2 ) S_t^{(2)} St(2):第t周期的二次指数平滑值;
    S t ( 1 ) S_t^{(1)} St(1):第t周期的一次指数平滑值;
    S t − 1 ( 2 ) S_{t-1}^{(2)} St1(2): 第t-1周期的二次指数平滑值;
    a a a:加权系数(也称为平滑系数)。

    二次指数平滑法是对一次指数平滑值作再一次指数平滑的方法。它不能单独地进行预测,必须与一次指数平滑法配合,建立预测的数学模型,然后运用数学模型确定预测值。

    3.2.3三次指数平滑预测

    1. 与前两种相比,我们多考虑一个因素:季节性效应( Seasonality)。这种平均模型考虑的季节性效应在股票或者期货价格中都会比较常见,比如在过年前A股市场通常会交易比较频繁,在小麦成熟的时候小麦期货价格也会有比较明显的波动。但是,模型本身的复杂度也增加了其使用难度,我们需要一定的经验才能比较合理地设置其中复杂的参数。
    2. 三次指数平滑预测是二次平滑基础上的再平滑。 其预测公式是:

    y t + m = a m ∗ ( 3 y t ’ − 3 y t + y t ) + [ ( 6 − 5 a ) y t ’ − ( 10 − 8 a ) y t + ( 4 − 3 a ) y t ] 2 ( 1 − a ) 2 + ( y t ’ − 2 y t + y t ’ ) ∗ a 2 m 2 / 2 ( 1 − a ) 2 yt+m=\frac{am*(3yt’-3yt+yt)+[(6-5a)yt’-(10-8a)yt+(4-3a)yt]}{2(1-a)2+ (yt’-2yt+yt’)*a2m2/2(1-a)2} yt+m=2(1a)2+(yt2yt+yt)a2m2/2(1a)2am(3yt3yt+yt)+[(65a)yt(108a)yt+(43a)yt]

    式中, y t = a y t − 1 + ( 1 − a ) y t − 1 yt=ayt-1+(1-a)yt-1 yt=ayt1+(1a)yt1

    它们的基本思想都是: 预 测 值 是 以 前 观 测 值 的 加 权 和 , 且 对 不 同 的 数 据 给 予 不 同 的 权 , 新 数 据 给 较 大 的 权 , 旧 数 据 给 较 小 的 权 \color{red}预测值是以前观测值的加权和,且对不同的数据给予不同的权,新数据给较大的权,旧数据给较小的权

    3.2.4二次指数平滑法实例分析

    表中第③栏是我国1978-1996年全社会客运量的资料,据期绘制散点图,见下图,可以看出,各年的客运量资料基本呈线性趋势,但在几个不同的时期直线有不同的斜率,因此考虑用变参数线性趋势模型进行预测。具体步骤如下:

    表 4 − 1 我 国 1978 − 2002 年 全 社 会 客 运 量 及 预 测 值                       单 位 : 万 人 表4-1 我国1978-2002年全社会客运量及预测值 \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 单位:万人 4119782002                     

    年份时间t全社会客运量y各期的一次指数平滑值 S t ( 1 ) S_t^{(1)} St(1)各期的二次指数平滑值 S t ( 2 ) S_t^{(2)} St(2)atbt y ^ t + 1 = a t + b t \hat{y}_{t+1}=a_t+b_t y^t+1=at+bt
    253993.0253993.0
    19781253993253993.0253993.0253993.00.0
    19792289665275396.2266834.9283957.512841.9253993.0
    19803341785315229.5295871.7334587.329036.7296799.4
    19814384763356949.6332518.4381380.836646.8363624.0
    19825428964400158.2373102.3427214.240583.9418027.5
    19836470614442431.7414699.9470163.441597.6467798.1
    19847530217495102.9462941.7527264.148241.8511761.1
    19858620206570164.8527275.5613054.064333.8575505.8
    19869688212640993.1595506.1686480.168230.5677387.8
    198710746422704250.4660752.7747748.265246.6754710.7
    198811809592767455.4724774.3810136.464021.6812994.8
    198912791376781807.8758994.4804621.134220.1874158.1
    199013772682776332.3769397.1783267.510402.8838841.2
    199114806048794161.7784255.9804067.614858.8793670.2
    199215860855834177.7814209.0854146.429953.1818926.3
    199316996630931651.5884674.5978628.570465.5884099.5
    19941710928831028390.4970904.01085876.886229.61049094.0
    19951811725961114913.81057309.91172517.686405.81172106.3
    19961912453561193179.11138831.41247526.881521.51258923.5
    19972013260941272928.01219289.41326566.780458.01329048.3
    19982113787171336401.41289556.61383246.270267.21407024.7
    19992213944131371208.41338547.71403869.148991.11453513.4
    20002314785731435627.11396795.41474458.958247.71452860.1
    20012415341221494724.11455552.61533895.558757.21532706.6
    20022516081501562779.61519888.81605670.464336.21592652.8

    (1)第一步,计算一次指数平滑值,取 a = 0.6 , S 0 ( 2 ) = S 1 ( 1 ) = y 1 = 253993 a=0.6,S_0^{(2)}=S_1^{(1)}=y_1=253993 a=0.6,S0(2)=S1(1)=y1=253993,根据一次指数平滑公式 S t ( 1 ) = a ∗ y t + ( 1 − a ) ∗ S t − 1 ( 1 ) S_t^{(1)}=a*y_t+(1-a)*S_{t-1}^{(1)} St(1)=ayt+(1a)St1(1),可计算各期的一次指数平滑预测值:

    1978年: S 1 ( 1 ) = 0.6 ∗ y 1 + 0.4 ∗ S 0 ( 1 ) = 0.6 ∗ 253993 + 0.4 ∗ 253993 = 253993 S_1^{(1)}=0.6*y_1+0.4*S_0^{(1)}=0.6*253993+0.4*253993=253993 S1(1)=0.6y1+0.4S0(1)=0.6253993+0.4253993=253993
    1979年: S 2 ( 1 ) = 0.6 ∗ y 2 + 0.4 ∗ S 1 ( 1 ) = 0.6 ∗ 289665 + 0.4 ∗ 253993 = 275396.2 S_2^{(1)}=0.6*y_2+0.4*S_1^{(1)}=0.6*289665+0.4*253993=275396.2 S2(1)=0.6y2+0.4S1(1)=0.6289665+0.4253993=275396.2
    同理可得各年的一次指数平滑预测值,见表1中第④栏。

    (2)第二步,根据(1)式和第一步计算的,计算各期的二次指数平滑值,见表1中第⑤栏。
    1978年: S 2 ( 2 ) = 0.6 ∗ S 1 ( 1 ) + 0.4 ∗ S 0 ( 2 ) = 0.6 ∗ 253993 + 0.4 ∗ 253993 = 253993 S_2^{(2)}=0.6*S_1^{(1)}+0.4*S_0^{(2)}=0.6*253993+0.4*253993=253993 S2(2)=0.6S1(1)+0.4S0(2)=0.6253993+0.4253993=253993
    1979年: S 2 ( 2 ) = 0.6 ∗ S 2 ( 1 ) + 0.4 ∗ S 1 ( 2 ) = 0.6 ∗ 275396 + 0.4 ∗ 253993 = 266834.9 S_2^{(2)}=0.6*S_2^{(1)}+0.4*S_1^{(2)}=0.6*275396+0.4*253993=266834.9 S2(2)=0.6S2(1)+0.4S1(2)=0.6275396+0.4253993=266834.9

    其余各期以此类推。
    (3)第三步,计算各期参数变量值α、b。根据(3)式,可计算各期的α、b,分别见表第⑥、第⑦栏。如
    { a 2 − 2 S 2 ( 1 ) − S 2 ( 2 ) = 2 ∗ 275396.2 − 266834.9 = 283957.5 b 2 = a 1 − a ( S 2 ( 1 ) − S 2 ( 2 ) ) = 0.6 0.4 ( 275396.2 − 266834.9 ) = 12841.9 \begin{cases} a_2-2S_2^{(1)}-S_2^{(2)} &= & 2*275396.2-266834.9=283957.5 \\ b_2 &=& \frac{a}{1-a}(S_2^{(1)}-S_2^{(2)})=\frac{0.6}{0.4}(275396.2-266834.9)=12841.9 \end{cases} {a22S2(1)S2(2)b2==2275396.2266834.9=283957.51aa(S2(1)S2(2))=0.40.6(275396.2266834.9)=12841.9

    (4)第四步,根据(4)式和(2)式分别求各期的趋势预测值,见表中最后一栏。如:

    2000年预测值: y ^ 23 = a 22 + b 22 ∗ 1 = 1403869.1 + 148991.1 = 1452860 \hat{y}_{2 3}=a_{22}+b_{22}*1=1403869.1+148991.1=1452860 y^23=a22+b221=1403869.1+148991.1=1452860

    外推预测,得到
    2003年预测值: y ^ 26 = y ^ 25 + 1 = a 25 + b 25 ∗ 1 = 1605670.4 + 64336.2 = 1670006.7 \hat{y}_{26}=\hat{y}_{25+1}=a_{25}+b_{25}*1=1605670.4+64336.2=1670006.7 y^26=y^25+1=a25+b251=1605670.4+64336.2=1670006.7

    2004年预测值: y ^ 27 = y ^ 26 + 1 = a 25 + b 25 ∗ 2 = 1605670.4 + 64336.2 ∗ 2 = 1734342.9 \hat{y}_{27}=\hat{y}_{26+1}=a_{25}+b_{25}*2=1605670.4+64336.2*2=1734342.9 y^27=y^26+1=a25+b252=1605670.4+64336.22=1734342.9

    在这里插入图片描述

    把各年的预测值绘成曲线与原时间序列的散点图比较(见上图),可以看出,二次指数平滑法由于考虑了时间序列在不同时期直线参数的变化,其预测值与原时间序列的拟合程度非常好。上图中也给出了用最小二乘法拟合的趋势直线,相比之下,用二次指数平滑法拟合的趋势线更好地体现了原时间序列在不同时间段的变化趋势。

    4.平稳时间序列模型 :自回归AR 、移动平均 MA 、ARMA 模型

    4.1自回归AR(Auto Regressive)

    认为过去若干时刻的点通过线性组合,再加上白噪声就可以预测未来某个时刻的点
    日常生活环境中就存在白噪声,在数据挖掘的过程中,可以把它理解为一个期望为0,方差为常数的纯随机过程。

    AR模型存在一个阶数p,称为AR§模型,也叫作p阶自回归模型。指的是通过这个时刻点的前p个点,通过线性组合再加上白噪声来预测当前时刻点的值。

    AR是线性时间序列分析模型中最简单的模型,通过前面部分的数据与后面部分的数据之间的相关关系来建立回归方程:
    AR§,表示p阶的自回归过程,为自回归系数,表示白噪声,是时间序列中的数值的随机波动。这些波动会相互抵消,即累计为0
    如果只有一个时间记录点时,则为AR(1),即一阶自回归过程:

    4.2移动平均MA(Moving Average)

    与AR模型大同小异,AR模型是历史时序值的线性组合,MA是通过历史白噪声进行线性组合来影响当前时刻点。

    MA模型中的历史白噪声是通过影响历史时序值,从而间接影响到当前时刻点的预测值。
    MA模型存在一个阶数q,称为MA(q)模型,也叫作q阶移动平均模型。AR和MA模型都存在阶数,在AR模型中,用p表示,在MA模型中用q表示,这两个模型大同小异,与AR模型不同的是MA模型是历史白噪声的线性组合。

    MA模型,通过前面通过将一段时间序列中白噪声序列进行加权和,可以得到移动平均方程:

    MA(q)表示q阶移动平均过程, 为移动回归系数, 为不同时间点的白噪声
    Xt 为第t天的股票价格,而Ut为第t天的新闻影响,当天的股票价格受当天的新闻影响,也受昨天的新闻影响(但影响力要弱些,所以要乘上系数)

    4.3ARMA 模型(Auto Regressive Moving Average)

    AR模型和MA模型的混合,相比AR模型和MA模型,它有更准确的估计
    ARMA模型存在p和q两个阶数,称为ARMA(p,q)模型:

    自回归模型结合了两个模型的特点,AR解决当前数据与后期数据之间的关系,MA则可以解决随机变动,即噪声问题。

    Auto Regressive Integrated Moving Average模型,中文叫差分自回归滑动平均模型,也叫求合自回归滑动平均模型。相比于ARMA,ARIMA多了一个差分的过程,作用是对不平稳数据进行差分平稳,在差分平稳后再进行建模。ARIMA的原理和ARMA模型一样。相比于ARMA(p,q)的两个阶数,ARIMA是一个三元组的阶数(p,d,q),称为ARIMA(p,d,q)模型,其中d是差分阶数。AR,MA是ARMA的特殊形式,而ARMA是ARIMA的特殊形式。

    ARIMA模型步骤
    Step1,观察时间序列数据,是否为平稳序列
    Step2,对于非平稳时间序列要先进行d阶差分运算,化为平稳时间序列
    Step3,使用ARIMA(p, d, q)模型进行训练拟合,找到最优的(p, d, q),及训练好的模型
    Step4,使用训练好的ARIMA模型进行预测,并对差分进行还原

    ARIMA 用差分将不平稳数据先变得平稳,再用ARMA模型

    4.3.1差分小知识

    差分=序列之间做差值,目的是为了得到平稳的序列,也就是去掉前面数值的影响
    一次差分为序列之间做一次差值,二次差分为在一次差分的基础上在做一次差分

    若x=[1,4,9,16,25….](x有二次趋势)

    一次差分的结果为[4-1,9-4,16-9,25-16…] = [3,5,7,9,11…],此时x序列仍不平稳,有一次上升的趋势
    再做一次差分为[2,2,2,2…] ,此时x为平稳序列

    5.时间序列实战

    5.1statsmodels工具

    statsmodels工具包提供统计计算,包括描述性统计以及统计模型的估计和推断

    statsmodels主要包括如下子模块:
    回归模型:线性回归,广义线性模型,线性混合效应模
    方差分析(ANOVA)
    时间序列分析:AR,ARMA,ARIMA等

    import statsmodels.api as sm
    # 数据加载
    data = pd.read_csv('shanghai_index_1990_12_19_to_2019_12_11.csv', usecols=['Timestamp', 'Price'])
    data.Timestamp = pd.to_datetime(data.Timestamp)
    data = data.set_index('Timestamp')
    data['Price'] = data['Price'].apply(pd.to_numeric, errors='ignore')
    # 进行线性插补缺漏值
    data.Price.interpolate(inplace=True)
    #  返回三个部分 trend(趋势),seasonal(季节性)和residual (残留)
    result = sm.tsa.seasonal_decompose(data.Price, freq=288)
    result.plot()
    plt.show()
    

    在这里插入图片描述

    5.2时间序列分析与回归分析的区别

    在选择模型前,我们需要确定结果与变量之间的关系。回归分析训练得到的是目标变量y与自变量x(一个或多个)的相关性,然后通过新的自变量x来预测目标变量y。而时间序列分析得到的是目标变量y与时间的相关性

    在这里插入图片描述

    回归分析擅长的是多变量与目标结果之间的分析,即便是单一变量,也往往与时间无关。而时间序列分析建立在时间变化的基础上,它会分析目标变量的趋势、周期、时期和不稳定因素等。这些趋势和周期都是在时间维度的基础上,是我们要观察的重要特征

    5.3ARMA实战

    # 从statsmodels导入ARMA
    from statsmodels.tsa.arima_model import ARMA
    

    ARMA(endog,order,exog=None)
    endog:endogenous
    variable,代表内生变量,又叫非政策性变量,它是由模型决定的,不被政策左右,可以说是我们想要分析的变量,或者说是我们这次项目中需要用到的变量
    order:代表是p和q的值,也就是ARMA中的阶数
    exog:exogenous
    variables,代表外生变量。外生变量和内生变量一样是经济模型中的两个重要变量。相对于内生变量而言,外生变量又称作为政策性变量,在经济机制内受外部因素的影响,不是我们模型要研究的变量

    如果我们想要创建ARMA(7,0)模型,可以写成:ARMA(data,(7,0)),其中data是我们想要观察的变量,(7,0)代表(p,q)的阶数。

    fit函数,进行拟合
    predict(start, end)函数,进行预测,其中start为预测的起始时间,end为预测的终止时间

    # 用ARMA进行时间序列预测
    from statsmodels.tsa.arima_model import ARMA
    # 创建数据
    data = [3821, 4236, 3758, 6783, 4664, 2589, 2538, 3542, 4626, 5886, 6233, 4199, 3561, 2335, 5636, 3524, 4327, 6064, 3912, 1356, 4305, 4379, 4592, 4233, 4281, 1613, 1233, 4514, 3431, 2159, 2322, 4239, 4733, 2268, 5397, 5821, 6115, 6631, 6474, 4134, 2728, 5753, 7130, 7860, 6991, 7499, 5301, 2808, 6755, 6658, 6944, 6372, 8380, 7366, 6352, 8333, 8281, 11548, 10823, 13642, 9973, 6723, 13416, 12205, 13942, 9590, 11693, 9276, 6519, 6863, 8237, 10122, 8646, 9749, 5346, 4836, 9806, 7502, 9387, 11078, 9832, 6886, 4285, 8351, 9725, 11844, 12387, 10666, 7072, 6429]
    data=pd.Series(data)
    data_index = sm.tsa.datetools.dates_from_range('1901','1990')
    
    # 绘制数据图
    data.index = pd.Index(data_index)
    data.plot(figsize=(12,8))
    plt.show()
    # 创建ARMA模型# 创建ARMA模型
    arma = ARMA(data,(7,0)).fit()
    print('AIC: %0.4lf' %arma.aic)
    # 模型预测
    predict_y = arma.predict('1990', '2000')
    # 预测结果绘制
    fig, ax = plt.subplots(figsize=(12, 8))
    ax = data.ix['1901':].plot(ax=ax)
    predict_y.plot(ax=ax)
    plt.show()
    

    在这里插入图片描述

    5.3.1ARMA工具对沪市指数进行预测

    Step1,数据加载&探索
    按照不同的时间尺度(天,月,季度,年)可以将数据压缩,得到不同尺度的数据,然后做可视化呈现。这4个时间尺度上,我们选择“月”作为预测模型的时间尺度

    df_month = df.resample(‘M’).mean()

    Step2,模型选择&训练,在给定范围内,选择最优的超参数
    创建ARMA时间序列模型。我们并不知道p和q取什么值时,模型最优,因此可以给它们设置一个区间范围,比如都是range(0,3),然后计算不同模型的AIC数值,选择最小的AIC数值对应的那个ARMA模型

    Step3,模型预测,可视化呈现
    用这个最优的ARMA模型预测未来3个月的沪市指数走势,并将结果做可视化呈现。
    在这里插入图片描述

    # 数据加载
    df = pd.read_csv('shanghai_index_1990_12_19_to_2020_03_12.csv')
    df = df[['Timestamp', 'Price']]
    # 将时间作为df的索引
    df.Timestamp = pd.to_datetime(df.Timestamp)
    df.index = df.Timestamp
    # 数据探索
    print(df.head())
    # 按照月,季度,年来统计
    df_month = df.resample('M').mean()
    print(df_month)
    df_Q = df.resample('Q-DEC').mean()
    df_year = df.resample('A-DEC').mean()
    
    # 按照天,月,季度,年来显示沪市指数的走势
    fig = plt.figure(figsize=[15, 7])
    plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签
    plt.suptitle('沪市指数', fontsize=20)
    plt.subplot(221)
    plt.plot(df.Price, '-', label='按天')
    plt.legend()
    plt.subplot(222)
    plt.plot(df_month.Price, '-', label='按月')
    plt.plot(df_Q.Price, '-', label='按季度')
    plt.plot(df_year.Price, '-', label='按年')
    plt.legend()
    plt.show()
    

    在这里插入图片描述

    # 设置参数范围
    ps = range(0, 3)
    qs = range(0, 3)
    parameters = product(ps, qs)
    parameters_list = list(parameters)
    # 寻找最优ARMA模型参数,即best_aic最小
    results = []
    best_aic = float("inf") # 正无穷
    for param in parameters_list:
        try:
            model = ARMA(df_month.Price,order=(param[0], param[1])).fit()
        except ValueError:
            print('参数错误:', param)
            continue
        aic = model.aic
        if aic < best_aic:
            best_model = model
            best_aic = aic
            best_param = param
        results.append([param, model.aic])
    print('最优模型: ', best_model.summary())
    

    在这里插入图片描述

    # 设置future_month,需要预测的时间date_list
    future_month = 3
    last_month = pd.to_datetime(df_month2.index[len(df_month2)-1])
    date_list = []
    for i in range(future_month):
        # 计算下个月有多少天
        year = last_month.year
        month = last_month.month
        if month == 12:
            month = 1
            year = year+1
        else:
            month = month + 1
        next_month_days = calendar.monthrange(year, month)[1]
        #print(next_month_days)
        last_month = last_month + timedelta(days=next_month_days)
        date_list.append(last_month)
    print('date_list=', date_list)
    
    date_list= [Timestamp('2020-04-30 00:00:00', freq='M'), Timestamp('2020-05-31 00:00:00', freq='M'), Timestamp('2020-06-30 00:00:00', freq='M')]
    
    # 添加未来要预测的3个月
    future = pd.DataFrame(index=date_list, columns= df_month.columns)
    df_month2 = pd.concat([df_month2, future])
    df_month2['forecast'] = best_model.predict(start=0, end=len(df_month2))
    # 第一个元素不正确,设置为NaN
    df_month2['forecast'][0] = np.NaN
    print(df_month2)
    # 沪市指数预测结果显示
    plt.figure(figsize=(30,7))
    df_month2.Price.plot(label='实际指数')
    df_month2.forecast.plot(color='r', ls='--', label='预测指数')
    plt.legend()
    plt.title('沪市指数(月)')
    plt.xlabel('时间')
    plt.ylabel('指数')
    plt.show()
    

    在这里插入图片描述

    5.4使用LSTM进行时间序列预测

    LSTM,Long Short-Term Memory,长短记忆网络
    可以避免常规RNN的梯度消失,在工业界有广泛应用
    引入了三个门函数:输入门(Input Gate)、遗忘门(Forget Gate)和输出门(Output Gate)来控制输入值、记忆值和输出值
    输入门决定了当前时刻网络的状态有多少信息需要保存到内部状态中,遗忘门决定了过去的状态信息有多少需要丢弃 => 输入门和遗忘门是LSTM能够记忆长期依赖的关键
    输出门决定当前时刻的内部状态有多少信息需要输出给外部状态。
    在这里插入图片描述
    一个LSTM单元在每个时间步会接收三个输入:

    当前时刻的输入,
    自上一时刻的内部状态
    上一时刻的外部状态
    和同时作为三个“门”的输入
    是Logistic函数

    参考资料

    1. 指数平滑法
    2. 时间序列预测之一:指数平滑法(一)理论
    3. LSTM模型理论总结(产生、发展和性能等)
    4. 时间序列动态模型与静态模型_用基于树的模型接近时间序列
    5. ARIMA模型
    展开全文
  • 时间序列分析实例

    千次阅读 2022-03-02 11:37:11
    时间序列分析简介 可参考链接: 时间序列详解 时间序列针对不同曲线情况的预测方式 时间序列python实例 python建立时间序列分析 理解ACF 和PACF ADF检验理解 ADF检验补充 实例 某段时间日活预测 历史数据为2022-01-...

    时间序列分析简介

    可参考链接:
    时间序列详解
    时间序列针对不同曲线情况的预测方式
    时间序列python实例
    python建立时间序列分析
    理解ACF 和PACF
    ADF检验理解
    ADF检验补充

    实例

    某段时间日活预测
    历史数据为2022-01-13至2022-02-27的日活数据,大致画出曲线,该曲线不够平滑
    历史数据
    1、进行ADF检验

    from statsmodels.tsa.stattools import adfuller  #adf检验
    temp = np.array(data['日活'])
    t = adfuller(temp)  # ADF检验
    output=pd.DataFrame(index=['Test Statistic Value', "p-value", "Lags Used", "Number of Observations Used","Critical Value(1%)","Critical Value(5%)","Critical Value(10%)"],columns=['value'])
    output['value']['Test Statistic Value'] = t[0]
    output['value']['p-value'] = t[1]
    output['value']['Lags Used'] = t[2]
    output['value']['Number of Observations Used'] = t[3]
    output['value']['Critical Value(1%)'] = t[4]['1%']
    output['value']['Critical Value(5%)'] = t[4]['5%']
    output['value']['Critical Value(10%)'] = t[4]['10%']
    output
    

    得到一下结果,p值较大,原假设为曲线为非平稳曲线,接受原假设,且t-statistic 为 -2.28747大于5%,此曲线非平稳
    ADF检验具体参数见 时间序列分析之ADF检验
    在这里插入图片描述
    2、进行白噪声检验,曲线非白噪声

    #白噪声检验,如果序列是白噪声,则没有研究意义,返回的是统计量和p值,原假设是有白噪声
    from statsmodels.stats.diagnostic import acorr_ljungbox
    print(acorr_ljungbox(data["日活"], lags=1)) 
    

    3、对日活值进行一阶差分
    画出差分处理后的曲线图并进行ADF检验,该差分曲线为平稳曲线
    在这里插入图片描述
    在这里插入图片描述
    4、画出acf和pacf图来确定p、q值

    AR模型对应p,根据偏自相关图的截尾位置确定p,ACF与PACF图的横轴均从0开始,如果PACF在2时还在置信区间以外,从3开始之后均在置信区间以内,则定p为2。MA模型对应q,根据自相关图的截尾位置确定q,确定方法同p

    确定p、q皆为7。详细可见 ARIMA算法解析与Python实现

    import statsmodels.api as sm     #acf,pacf图
    
    fig = plt.figure(figsize=(12,8))
    ax1=fig.add_subplot(211)
    fig = sm.graphics.tsa.plot_acf(data2,lags=18,ax=ax1)
    ax2 = fig.add_subplot(212)
    fig = sm.graphics.tsa.plot_pacf(data2,lags=18,ax=ax2)
    plt.show()
    

    在这里插入图片描述
    5、建立ARIMA模型

    注意日期要改为索引不然后面会报错
    data = data.set_index(['日期'],drop=True)
    data['日活'] = data['日活'].astype('float64')
    
    from statsmodels.tsa.arima_model import ARIMA  
    model=ARIMA(data,(7,1,7)).fit(method='css')  #ARIMA(data, (p, 1, q))
    

    画出预测出来的差分和实际差分作比较

    predictions_ARIMA_diff = pd.Series(model.fittedvalues, copy=True)
    plt.figure(figsize=(10, 6))
    plt.plot(data2,label = 'real')
    plt.plot(predictions_ARIMA_diff,label = 'forecast')
    plt.legend()
    plt.show()
    

    在这里插入图片描述
    6、将预测值加到实际值上去预测后一天
    这里注意差分值和实际值的匹配

    predictions = [i + j for i, j in zip(list(predictions_ARIMA_diff), list(data["日活"][7:45]))]
    prediction_sales = pd.DataFrame(data=predictions,index=data.index[8:46],columns=['差分'])
    
    plt.figure(figsize=(10, 6))
    plt.plot(prediction_sales,label="forecast")
    plt.plot(data,label="real")
    plt.xlabel('日期',fontsize=12,verticalalignment='top')
    plt.ylabel('销量',fontsize=14,horizontalalignment='center')
    plt.legend()
    plt.show()
    

    在这里插入图片描述
    对后续进行预测
    返回预测结果, 标准误差, 和置信区间

    pridict = list(model.forecast(5)[0])
    

    在这里插入图片描述

    如果考虑季节性因素,分析方法可参考季节性ARIMA模型
    季节指数计算方式:excel处理季节性指数

    展开全文
  • 时间序列分析及应用(R语言)(原书第2版)》以易于理解的方式讲述了时间序列模型及其应用,内容包括趋势、平稳时间序列模型、非平稳时间序列模型、模型识别、参数估计、模型诊断、预测、季节模型、时间序列回归...
  • 时间序列分析及应用:R语言

    热门讨论 2014-08-12 10:44:41
    时间序列分析及应用:R语言,(原书第2版)。内容:应用R语言实现时间序列分析的具体方法与步骤,很好的一本学习用书。
  • Matlab时间序列分析

    万次阅读 多人点赞 2018-11-13 18:53:46
    在引入时间序列前,先介绍几个matlab函数 matlab中的gallery函数简析 Matlab 中的 gallery 函数是一个测试矩阵生成函数。当我们需要对某些算法进行测试的时候,可以利用gallery函数来生成各种性质的测试矩阵。其用法...
  • 使用R语言进行时间序列分析

    千次阅读 2020-04-15 15:10:54
    时间序列是将统一统计值按照时间发生的先后顺序来进行排列,时间序列分析的主要目的是根据已有数据对未来进行预测。 一个稳定的时间序列中常常包含两个部分,那么就是:有规律的时间序列+噪声。所以,在以下的方法中...
  • 【中文版】汉密尔顿--时间序列分析.pdf
  • R语言时间序列分析

    万次阅读 多人点赞 2020-05-23 00:29:48
    当拿到一个时间序列的时候,首先分析时间序列的类型,不同类型的序列有不同的处理方式。本文包含以下几个部分: 1、时间序列数据准备 2、时间序列平稳性检验 3、拟合ARIMA模型 4、ARIMA模型的检验诊断 ...
  • 时间序列(time series)是系统中某一变量的观测值按时间顺序(时间间隔相同)排列成一个数值序列,展示研究对象在一定时期内的变动过程,从中寻找和分析事物的变化特征、发展趋势和规律。它是系统中某一变量受其它...
  • 应用时间序列分析

    2012-11-07 17:04:56
    时间序列分析 北京大学时间序列分析教材

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 441,044
精华内容 176,417
关键字:

时间序列分析