【Python】时间序列分析

I. 数据探索

 1. 趋势分解

def decompose(timeseries,p=7):
    '''
    时间序列趋势分解的函数,timeseries是所需要分析的时序数据,p是需要确认的周期性的期数
    '''
    from statsmodels.tsa.seasonal import seasonal_decompose
    # 使画图中中文显示正常
    plt.rcParams['font.sans-serif']=['Heiti TC']
    plt.rcParams['axes.unicode_minus'] = False
    plt.rcParams.update({'font.size': 12})
    # 返回包含三个部分 trend(趋势部分) , seasonal(季节性部分) 和residual (残留部分)
    decomposition = seasonal_decompose(timeseries,period=p)
    
    trend = decomposition.trend
    seasonal = decomposition.seasonal
    residual = decomposition.resid
    plt.figure(facecolor='white',figsize=(14,12))
    plt.subplot(411)
    plt.plot(timeseries, label='Original({})'.format(timeseries.name))
    plt.legend(loc='best')
    plt.subplot(412)
    plt.plot(trend, label='Trend')
    plt.legend(loc='best')
    plt.subplot(413)
    plt.plot(seasonal,label='Seasonality')
    plt.legend(loc='best')
    plt.subplot(414)
    plt.plot(residual, label='Residuals')
    plt.legend(loc='best')
    plt.tight_layout()
    plt.show()
    return trend , seasonal, residual

trend,seasonal,residual = decompose(data.price,p=365)

2. 数据平稳性检验

平稳性概念:假定某个时间序列是由一系列随机过程生成的,即假定时间序列的每一个数值都是从一个概率分布中随机得到,如果满足下列条件:

  • 均值u是与时间t无关的常数;
  • 方差是与时间t无关的常数;
  • 协方差是只与时间间隔K有关,与时间t无关的常数

则称随机时间序列是平稳的,而该随机过程是平稳随机过程。

为什么需要时间序列的平稳性?

时间序列分析方法是利用样本信息来推测总体信息。根据统计学常识,肯定是分析的随机变量越少越好,而通过每个变量获得的样本信息越多越好。但是时间序列分析的数据结构有它的特殊性,对随机序列而言,在任意时刻t的序列值Xt都是一个随机变量,而且由于时间的不可重复性,该变量在任意时刻只能获得唯一的样本观测值。所以在样本信息较少的情况下,是无法获得其他辅助信息的,如果序列平稳则可以有效解决这个问题。

2.1. 单位根检验(Dickey-Fuller test) DF检测

判断依据:如果检验统计量(TS)大于临界值(CV),则否决原假设(即序列不是平稳的)。如果TS小于CV,则不能否决原假设(即序列是平稳的)。

DF检验仅适用于AR(1)模型的检验,所以对DF检验进行修正,推出ADF检验,ADF适用于AR(p)模型的平稳性检验

from statsmodels.tsa.stattools import adfuller

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%']

2.2. KPSS测试

KPSS 测试,不如ADF方法流行。KPSS检验的原假设和备择假设与ADF检验相反。

from statsmodels.tsa.stattools import kpss
def kpss_test(timeseries):
    print('Results of KPSS Test:')
    kpsstest = kpss(timeseries, regression='c')
    kpss_output = pd.Series(kpsstest[0:3], index=['Test Statistic', 'p-value', '#Lags Used'])
    for key, value in kpsstest[3].items():
        kpss_output['Critical Value (%s)' % key] = value
    print(kpss_output)
kpss_test(timeseries)  

#结果显示TS>cv, p <1% 表示拒绝数据是平稳的原假设,序列不是平稳的。

2.3 对数据平稳化

  • 平滑法(分析,预测),移动平均,加权移动平均法
  • 对数变化:当原序列的前后数值相差较大或者数量级相差较大时。主要是为了减小数据的振动幅度,使其线性规律更加明显
  • 差分

一阶差分:t(n)-t(n-1)
二阶差分:一阶差分上再做一阶差分t(n)-2t(n-1)+t(n-2)

3. 白噪声检验

Ljung-Box检验 (LB检验) 是时间序列分析中检验序列自相关性的方法。用来检验m阶滞后范围内序列的自相关性是否显著,或序列是否为白噪声。其原假设为序列是白噪声序列。

# 白噪声检验
from statsmodels.stats.diagnostic import acorr_ljungbox
print('LB test p-value:', acorr_ljungbox(df_train.sales_ln_diff12, lags=1)[1][0])
  • LB统计量小于选定置信水平下的临界值,或者 p 值大于显著性水平(如0.05),不能拒绝原假设,序列为白噪声;
  • LB统计量大于选定置信水平下的临界值,或者 p 值小于显著性水平(如0.05),拒绝原假设,序列非白噪声;

对于ARIMA模型,其残差被假定为高斯白噪声序列,所以当我们用ARIMA模型去拟合数据时,拟合后我们要对残差的估计序列进行LB检验,判断其是否是高斯白噪声,如果不是,那么就说明ARIMA模型也许并不是一个适合样本的模型。

4. 多元时间序列分析

4.1 协整

  • 单整:原序列非平稳,对原序列进行 d 阶差分后实现平稳,则称原序列为 d 阶单整序列
  • 协整:两个序列都是非平稳,但他们具有长期均衡关系,如果两个序列的回归残差序列平稳,那这两个序列具有协整关系

协整检验—Engle-Granger检验

实际上就是检验两个序列的回归残差序列是否平稳,Engle-Granger检验与ADF检验的原理一样

4.2 误差修正模型(ECM)

协整模型度量序列之间的长期均衡关系,ECM度量序列之间的短期均衡关系

II. 机器学习模型

  • AR模型认为通过时间序列过去时点的线性组合加上白噪声即可预测当前时点。
  • MA模型是历史白噪声的线性组合。与AR最大的不同之处在于,AR模型中历史白噪声的影响是间接影响当前预测值的(通过影响历史时序值)。金融模型中,MA常用来刻画冲击效应,例如预期之外的事件。

ARIMA模型

AutoRegressive Integrated Moving Average

  • AR: 自相关模型(AutoRegressive)
  • MA: 移动平均模型(Moving Average)
  • I:差分的逆过程(差分的逆过程)

ARIMA(p,d,q)的三个参数

  • p:自回归模型阶数
  • d:使之成为平稳序列所做的差分阶数
  • q:移动平均模型阶数

使用ARIMA模型预测数据的主要步骤包括:

  1. 序列平稳化
  2. 确定d参数
  3. 画出acf和pacf图,确定p参数和q参数
  4. 使用找到的参数拟合ARIMA模型
  5. 在验证集上进行预测
  6. 评估预测效果

序列平稳化

  1. 当原序列的前后数值相差较大或者数量级相差较大时,一般取对数将指数趋势转化为线性趋势,而且还不会改变变量之间的统计性质,同时得到较平稳的序列。
# 对数变换
df_train['sales_ln'] = np.log(df_train.sales)

# 取一阶差分
df_train['sales_ln_diff1'] = df_train.sales_ln.diff(periods=1)
df_train.dropna(subset=['sales_ln_diff1'], inplace=True)

# 二阶差分,取步长为12
df_train['sales_ln_diff12'] = df_train.sales_ln_diff1.diff(periods=12)
df_train.sales_ln_diff12.dropna(inplace=True)


# 定义一个差分还原函数
def diff_restore(arma):
    date_index = pd.date_range(start='2020-06-01', periods=24, freq='MS')
    arma_pred = arma.forecast(steps=24)[0]  # 预测未来24个月
    diff1_pred12 = pd.Series(df_train.sales_ln_diff1[-12:].values - arma_pred[:12], index = date_index[:12])
    diff1_pred24 = diff1_pred12.append(pd.Series(diff1_pred12.values - arma_pred[12:], index = date_index[12:]))  # 二阶差分还原
    sales_ln_pred = pd.Series([df_train.sales_ln[-1]], index=[df_train.index[-1]]).append(diff1_pred24).cumsum()[1:]  # 一阶差分还原
    sales_pred = np.power(np.e, sales_ln_pred)  # 因为取对数之后进行的差分操作,所以需要取自然底数还原
    return sales_pred

确认p参数和q参数

拖尾,顾名思义,就是序列缓慢衰减,“尾巴”慢慢拖着滑下来,或者震荡衰减。而截尾则是突然截断了,像个悬崖,指序列从某个时点变得非常小

(1)p 值可从偏自相关系数(PACF)图的最大滞后点来大致判断,q 值可从自相关系数(ACF)图的最大滞后点来大致判断

# 查看自相关系数与偏相关系数
from statsmodels.graphics.tsaplots import plot_pacf, plot_acf
fig, ax = plt.subplots(nrows=1, ncols=2, figsize=(12,4))
plot_acf(df_train.sales_ln_diff12, ax=ax[0]).show()
plot_pacf(df_train.sales_ln_diff12, ax=ax[1]).show()

#ACF:将有序的随机变量序列与其自身相比较,它反映了同一序列在不同时序的取值之间的相关性。
#PACF:PACF计算的是严格的两个变量之间的相关性,是剔除了中间变量的干扰之后所得到的两个变量之间的相关程度。

#预测时间序列
from statsmodels.tsa.stattools import acf,pacf
lag_acf=acf(ts_log_diff,nlags=30)
lag_pacf=pacf(ts_log_diff,nlags=30,method='ols')

在这里插入图片描述

(2)遍历搜索AIC和BIC最小的参数组合(因为一般通过拖尾和截尾对模型定阶,具有很强的主观性),通过比较不同差分阶数的AIC、BIC的值,取两者最小值p、q 

AIC(Akaike信息准则)和BIC(Bayes信息准则)

trend_evaluate = sm.tsa.arma_order_select_ic(train, ic=['aic', 'bic'], max_ar=6, max_ma=4)
print('train AIC', trend_evaluate.aic_min_order)
print('train BIC', trend_evaluate.bic_min_order)

模型拟合

#模型拟合
from statsmodels.tsa.arima_model import ARIMA

model = ARIMA(data, order=(2,1,2)).fit()

模型诊断

# 诊断
results.plot_diagnostics(figsize=(15, 10))
plt.show()

预测效果

fig,ax = plt.subplots(figsize=(15,6))
ax.plot(df_train.sales[-36:])
ax.plot(sales_pred_bic, color = 'green', label = 'forecast', alpha=0.7)
ax.plot(sales_pred_bic.index[:12], df_test.values, color = 'yellow', label = 'observed', alpha=0.9)

ax.set_title("ARMA - Forecast of Car Sales")
ax.legend(loc=1)
plt.show()

在这里插入图片描述

预测结果评估

from sklearn.metrics import mean_absolute_error
mean_absolute_error(true, predict)

from sklearn.metrics import mean_absolute_percentage_error as mape
mape(true, predict)

官方文档:statsmodels.tsa.arima.model.ARIMA — statsmodels

Auto ARIMA

Auto ARIMA可以绕过使序列平稳化、定阶等步骤

from statsmodels.tsa.arima_model import ARIMA
import pmdarima as pm

'''
start_p: p的起始值,自回归(“AR”)模型的阶数(或滞后时间的数量),必须是正整数。
start_q: q的初始值,移动平均(MA)模型的阶数。必须是正整数。
max_p: p的最大值,必须是大于或等于start_p的正整数。
max_q: q的最大值,必须是一个大于start_q的正整数。
seasonal: 是否适合季节性ARIMA。默认是正确的。注意,如果season为真,而m == 1,则season将设置为False。
stationary: 时间序列是否平稳,d是否为零。
information_criterion:信息准则用于选择最佳的ARIMA模型。(‘aic’,‘bic’,‘hqic’,‘oob’)之一
alpha:检验水平的检验显著性,默认0.05
test: 如果stationary为假且d为None,用来检测平稳性的单位根检验的类型。默认为‘kpss’;可设置为adf
n_jobs :网格搜索中并行拟合的模型数(逐步=False)。默认值是1,-1为使用电脑所有核心。
suppress_warnings:statsmodel中可能会抛出许多警告。如果suppress_warnings为真,那么来自ARIMA的所有警告都将被压制
error_action: 如果由于某种原因无法匹配ARIMA,则可以控制错误处理行为 (warn,raise,ignore,trace)
max_d: d的最大值,即非季节差异的最大数量。必须是大于或等于d的正整数。
trace: 是否打印适合的状态。如果值为False,则不会打印任何调试信息。值为真会打印一些
'''

smodel = pm.auto_arima(df_train.sales_ln, start_p=1, start_q=1,
                         test='adf',
                         max_p=3, max_q=3, m=12,
                         start_P=0, seasonal=True,
                         stationary=True,
                         information_criterion='aic',
                         error_action='ignore',  
                         suppress_warnings=True, 
                         stepwise=False)

smodel.summary()

pred_ln, confint_ln = smodel.predict(n_periods=24, return_conf_int=True)

SARIMAX模型

SARIMAX是在ARIMA的基础上加上季节(S, Seasonal)和外部因素(X, eXogenous)。也就是说以ARIMA基础加上周期性和季节性,适用于时间序列中带有明显周期性和季节性特征的数据。

网格搜索最佳参数

%%time
import statsmodels.api as sm
from joblib import Parallel, delayed
import itertools
from tqdm import tqdm

p = d = q = [0, 1, 2]
pdq = list(itertools.product(p, d, q))
seasonal_pdq = [(x[0], x[1], x[2], 12) for x in pdq]

def sarima(param, param_seasonal):
    mod = sm.tsa.statespace.SARIMAX(df_train.sales_ln,
                                    order=param,
                                    seasonal_order=param_seasonal)
    res = mod.fit()
    return param, param_seasonal, res
    
# 调用所有核心并发运行,并添加进度条
res_list = Parallel(n_jobs=-1)(delayed(sarima)(i, j) for i in tqdm(pdq) for j in seasonal_pdq)  
data = [[i, j, k.aic] for i, j, k in res_list]  
sarima_res = pd.DataFrame(data, columns=['param', 'param_seasonal', 'aic'])
sarima_res
# 查看aic最小值参数
sarima_res.loc[sarima_res.aic == sarima_res.aic.min()]

模型拟合

best_mod = sm.tsa.statespace.SARIMAX(df_train.sales_ln, 
                                order=(1,1,0), 
                                seasonal_order=(1,0,2,12))
results = best_mod.fit()
print(results.summary())

模型预测

# 预测未来24个月的销量
pred_uc = results.get_forecast(steps=24, alpha=0.05)
pred_pr = pred_uc.predicted_mean

# 获取预测的置信区间
pred_ci = pred_uc.conf_int()

#预测图
fig,ax = plt.subplots(figsize=(15,6))
ax.plot(df_train.sales[-24:])
ax.plot(pred_data.forecast, color = 'green', label = 'forecast', alpha=0.7)
ax.plot(pred_data.index[:12], df_test.values, color = 'yellow', label = 'observed', alpha=0.7)
ax.fill_between(pred_data.index, 
                 pred_data.lower_ci_95, 
                 pred_data.upper_ci_95, 
                 color='grey', alpha=0.5,label = '95% confidence interval')

ax.set_title("SARIMA - Forecast of Car Sales")
ax.legend()
plt.show()

Prophet模型

Prophet由Facebook开源的基于python和R语言的数据预测工具,是一种基于时间和变量值结合时间序列分解和机器学习的拟合来做的时序模型;Prophet模型简单、容易上手、并且在建模过程中考虑了趋势线季节性周期性、以及外生变量等因素的影响,预测效果好,相对于传统时序模型有很大优势。

ARIMA模型只适合短期预测,而且在模型中没有考虑周期性、节假日以及外生回归量等因素。虽然ARIMA的升级版ARIMAX和SARIMA模型考虑了这些因素,但是从长期预测效果来看,仍然不如Prophet。

Prophet模型的基本原理如下图所示,在构建时间序列模型的时候,综合考虑了趋势、周期、节假日及外生回归项等因素:

from fbprophet import Prophet

m = Prophet(yearly_seasonality=True,growth='logistic',holidays=holidays_df)
#growth是时序变化趋势,有线性(linear)和非线性(logistic)两种
#holidays设置节假日的日期,我们令其等于上文中设置的holidays_df

#我们增加行业另外竞品数据作为回归项
for i in data_prophet_hist.columns[1:-3]:
    m.add_regressor(i)
m.fit(data_prophet_hist) # 放入历史数据训练

III. 时间序列预测的评价指标

时间序列预测的评价指标可以分为两类,一类是scale无关的(如smape、rmsle、mape等),一类是scale相关的(如mse、rmse、mae、nd等)。Scale无关的,即不管每个样本点的取值多大,对最终loss的贡献都是差不多的,因为这些指标计算的都是预测值相对于真实值的偏差百分比。而scale相关的指标,数值越大对loss的贡献就越大,因为它们直接计算预测值和真实值的差值。

c1679a059e6248bc723db6c202e91dd8.png

 在选择指标时,如果更关注大值样本的效果,可以用scale相关的指标;如果更关注全局所有样本的效果,可以用scale无关的指标。对于scale无关的指标还要注意一点,在一些场景中,小值样本比大值样本多得多,数据呈现长尾部分。这种情况下使用scale无关指标,则更偏向于看小值样本效果。同时,小值样本可能存在更大的误差,比如真实值是1,预测值是2,这偏差就是100%了,小样本本来就噪声大。如果用scale无关指标在这类数据上评估,很可能反映的是拟合噪声的效果。因此更合适的做法是对测试集做一个采样,小值样本、大值样本保留差不多的数量,才能更科学的评价模型效果。

IV. Python库

ForecastingClasssificationAnomaly DetectionSegmentationTSFeature
Prophet
Kats
GluonTS
NeuralProphet
arch
AtsPy
banpei
cesium
darts
PaddleTS

模型

ModelUnivariateMultivariateProbabilisticMultiple-series training
ARIMA
VARIMA
AutoARIMA
ExponentialSmoothing
Theta and FourTheta
Prophet
FFT (Fast Fourier Transform)
RegressionModel (incl RandomForestLinearRegressionModel and LightGBMModel)
RNNModel (incl. LSTM and GRU); equivalent to DeepAR in its probabilistic version
BlockRNNModel (incl. LSTM and GRU)
NBEATSModel
TCNModel
TransformerModel
TFTModel (Temporal Fusion Transformer)
Naive Baselines

References

容易上手的时间序列分析2:Prophet模型 - 知乎

Python数据分析案例-分别使用时间序列ARIMA、SARIMAX模型与Auto ARIMA预测国内汽车月销量_吴下阿泽的博客-CSDN博客

  • 6
    点赞
  • 91
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
第1章 贝叶斯定理 1 1.1 条件概率 1 1.2 联合概率 2 1.3 曲奇饼问题 2 1.4 贝叶斯定理 3 1.5 历时诠释 4 1.6 M&M豆问题 5 1.7 Monty Hall难题 6 1.8 讨论 8 第2章 统计计算 9 2.1 分布 9 2.2 曲奇饼问题 10 2.3 贝叶斯框架 11 2.4 Monty Hall难题 12 2.5 封装框架 13 2.6 M&M豆问题 14 2.7 讨论 15 2.8 练习 16 第3章 估计 17 3.1 骰子问题 17 3.2 火车头问题 18 3.3 怎样看待先验概率? 20 3.4 其他先验概率 21 3.5 置信区间 23 3.6 累积分布函数 23 3.7 德军坦克问题 24 3.8 讨论 24 3.9 练习 25 第4章 估计进阶 27 4.1 欧元问题 27 4.2 后验概率的概述 28 4.3 先验概率的湮没 29 4.4 优化 31 4.5 Beta分布 32 4.6 讨论 34 4.7 练习 34 第5章 胜率和加数 37 5.1 胜率 37 5.2 贝叶斯定理的胜率形式 38 5.3 奥利弗的血迹 39 5.4 加数 40 5.5 最大化 42 5.6 混合分布 45 5.7 讨论 47 第6章 决策分析 49 6.1 “正确的价格”问题 49 6.2 先验概率 50 6.3 概率密度函数 50 6.4 PDF的表示 51 6.5 选手建模 53 6.6 似然度 55 6.7 更新 55 6.8 最优出价 57 6.9 讨论 59 第7章 预测 61 7.1 波士顿棕熊队问题 61 7.2 泊松过程 62 7.3 后验 63 7.4 进球分布 64 7.5 获胜的概率 66 7.6 突然死亡法则 66 7.7 讨论 68 7.8 练习 69 第8章 观察者的偏差 71 8.1 红线问题 71 8.2 模型 71 8.3 等待时间 73 8.4 预测等待时间 75 8.5 估计到达率 78 8.6 消除不确定性 80 8.7 决策分析 81 8.8 讨论 83 8.9 练习 84 第9章 二维问题 85 9.1 彩弹 85 9.2 Suite对象 85 9.3 三角学 87 9.4 似然度 88 9.5 联合分布 89 9.6 条件分布 90 9.7 置信区间 91 9.8 讨论 93 9.9 练习 94 第10章 贝叶斯近似计算 95 10.1 变异性假说 95 10.2 均值和标准差 96 10.3 更新 98 10.4 CV的后验分布 98 10.5 数据下溢 99 10.6 对数似然 100 10.7 一个小的优化 101 10.8 ABC(近似贝叶斯计算) 102 10.9 估计的可靠性 104 10.10 谁的变异性更大? 105 10.11 讨论 107 10.12 练习 108 第11章 假设检验 109 11.1 回到欧元问题 109 11.2 来一个公平的对比 110 11.3 三角前验 111 11.4 讨论 112 11.5 练习 113 第12章 证据 115 12.1 解读SAT成绩 115 12.2 比例得分SAT 115 12.3 先验 116 12.4 后验 117 12.5 一个更好的模型 119 12.6 校准 121 12.7 效率的后验分布 122 12.8 预测分布 123 12.9 讨论 124 第13章 模拟 127 13.1 肾肿瘤的问题 127 13.2 一个简化模型 128 13.3 更普遍的模型 130 13.4 实现 131 13.5 缓存联合分布 132 13.6 条件分布 133 13.7 序列相关性 135 13.8 讨论 138 第14章 层次化模型 139 14.1 盖革计数器问题 139 14.2 从简单的开始 140 14.3 分层模型 141 14.4 一个小优化 142 14.5 抽取后验 142 14.6 讨论 144 14.7 练习 144 第15章 处理多维问题 145 15.1 脐部细菌 145 15.2 狮子,老虎和熊 145 15.3 分层版本 148 15.4 随机抽样 149 15.5 优化 150 15.6 堆叠的层次结构 151 15.7 另一个问题 153 15.8 还有工作要做 154 15.9 肚脐数据 156 15.10 预测分布 158 15.11 联合后验 161 15.12 覆盖 162 15.13 讨论 164

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值