时间序列
时间序列数据
时间序列是按时间顺序排列的、随时间变化且相互关联的数据序列。
构成要素
时间序列可以分为长期趋势(trend)、季节变动(seasonal)、循环变动(cycling)和随机波动(irregular)四个部分。
- 长期趋势( T )现象在较长时期内受某种根本性因素作用而形成的总的变动趋势
- 季节变动( S )现象在一年内随着季节的变化而发生的有规律的周期性变动
- 循环变动( C )现象以若干年为周期所呈现出的波浪起伏形态的有规律的变动
- 不规则变动(I )是一种无规律可循的变动,包括严格的随机变动和不规则的突发性影响很大的变动两种类型
可以根据模型输入变量数将其分为两类:
第一类:允许单变量输入的时间序列统计模型【Time series statistical model】
代表算法:Holt-Winters、ARIMA、fbprophet
第二类:允许多变量输入的时间序列监督模型【Time series supervised learning model】
代表算法:XGBoost、LSTM,convLstm,attention model
第一类时间序列统计模型
ARIMA模型
ARIMA,全称自回归整合移动平均模型,(Autoregressive Integrated Moving Average Model)。
原理
将非平稳时间序列转化为平稳时间序列,然后将因变量仅对它的滞后值以及随机误差项的现值和滞后值进行回归所建立的模型。
须知这是一个大家庭
- 自回归(AR)模型;
- 移动平均(MA)模型;
- 自回归移动平均(ARMA)模型;
- 自回归整合移动平均模型(ARIMA);
- 季节性整合自回归移动平均模型(SARIMA)模型。
ARIMA要求输入是平稳的时间序列
平稳性就是要求经由样本时间序列所得到的拟合曲线在未来的一段期间内仍能顺着现有的形态“惯性”地延续下去。
严平稳与弱平稳:
- 严平稳:严平稳表示的分布不随时间的改变而改变;
如:白噪声(正态),无论怎么取,都是期望为0,方差为1 - 弱平稳:期望与相关系数(依赖性)不变;
未来某时刻的t的值Xt就要依赖于它的过去信息,所以需要依赖性
输入
单变量,按照时间戳排列好的有序变量
输出
未来一段时间戳序列的有序量。
为啥叫自回归
传统的回归模型,都是有自变量X和因变量Y组成的(X,Y)来做模型训练,但是时间序列是利用自身历史数据预测未来数据的单变量时间序列模型。用自己历史数据预测未来就是自回归。
模型3个超参数
ARIMA(p,d,q)-p,d,q数值越大模型越复杂
- p–自回归项系数;代表预测模型中采用的时序数据本身的滞后数(lags) ,也称AR/Auto-Regressive项
- d–差分系数;代表时序数据需要进行几阶差分化,才是稳定的,也叫Integrated项。
- q–移动平均系数;代表预测模型中采用的预测误差的滞后数(lags),也叫MA/Moving Average项
ARIMA建模过程
核心过程
1:序列白噪声检验:如果序列是纯随机的就不需要在做预测了,都随机了还预测个毛线啊,有没有上帝之眼。这一步没过下面工作就不要做了。。。方法:acorr_ljungbox
2:平稳性检验:ARIMA要求输入的序列是平稳的,所以使用之间要检查模型的平稳性;方法:ADF检验;
3:定阶:p,q;方法:图示法:PACF,ACF;统计量:AIC,BIC统计量。
4:残差检验: 检验残差是否是白噪声过程。
5:预测: 利用模型预测。
白噪声检验acorr_ljungbox
白噪声检验也称为纯随机性检验, 当数据是纯随机数据时,再对数据进行分析就没有任何意义了, 所以拿到数据后最好对数据进行一个纯随机性检验。
原假设:数据是随机的;给定显著性水平a:
-
如果 p <= a, 则在显著性水平a 下拒绝H0;
-
如果p > a,则在显著性水平a下接受H0
-
a通常是0.05、0.01等。
python方法
from statsmodels.stats.diagnostic import acorr_ljungbox
acorr_ljungbox(b.salesVolume, lags = [6, 12],boxpierce=True)
-
lags为延迟期数,如果为整数,则是包含在内的延迟期数,如果是一个列表或数组,那么所有时滞都包含在列表中最大的时滞中
-
boxpierce为True时表示除开返回LB统计量还会返回Box和Pierce的Q统计量
返回值:
-
lbvalue:测试的统计量
-
pvalue:基于卡方分布的p统计量
-
bpvalue:((optionsal), float or array) 基于 Box-Pierce 的检验的p统计量
-
bppvalue:((optional), float or array) 基于卡方分布下的Box-Pierce检验的p统计量
平稳性检验-ADF检验
白噪声检验通过,说明序列时非随机的,可以尝试用来做预测;
ADF检验的原假设是存在单位根。注意,ADF值一般是负的,也有正的,但是它只有小于1%水平下的才能认为是及其显著的拒绝原假设 。
python 的ADF检验方法adfuller的返回值
- Test statistic:代表检验统计量
- p-value:代表p值检验的概率
- Lags used:使用的滞后k,autolag=AIC时会自动选择滞后
- Number of Observations Used:样本数量
- Critical Value(5%) : 显著性水平为5%的临界值。
(1) 假设是存在单位根,即不平稳;
(2) 显著性水平,1%:严格拒绝原假设;5%:拒绝原假设,10%类推。
(3) 看P值和显著性水平a的大小,p值越小,小于显著性水平的话,就拒绝原假设,认为序列是平稳的;大于的话,不能拒绝,认为是不平稳的
(4) 看检验统计量和临界值,检验统计量小于临界值的话,就拒绝原假设,认为序列是平稳的;大于的话,不能拒绝,认为是不平稳的
P值和T统计量的关系
P值是t统计量对应的概率值,所以t和p两者是等效的,看p就够了。
P值要求小于给定的显著性水平,一般是0.05、0.01等,p越接近于0越好;
这三个水平值内部自己设定的,它表示拒绝原假设的不同程度。
一般在原序列条件下,如果存在非平稳状态,按以下步骤进行:
一阶差分是否具有单位根,就是比较一届差分的ADF检验值与5%临界值的大小,否则再看二阶差分的。
如果二阶都不单整,就要重新处理一下数据了
ADF检验
3个超参数选择方法
图示法-PACF、ACF
python绘制的效果图:
选择p,q的原则:
截尾:落在置信区间内(95%的点都符合该规则)
p阶自回归过程的公式定义:
PACF,偏自相关函数(决定p值),剔除了中间k-1个随机变量x(t-1)、x(t-2)、……、x(t-k+1)的干扰之后x(t-k)对x(t)影响的相关程度。
q阶自回归过程的公式定义
ACF,自相关函数(决定q值)反映了同一序列在不同时序取值之间的相关性。x(t)同时还会受到中间k-1个随机变量x(t-1)、x(t-2)、……、x(t-k+1)的影响;而这k-1个随机变量又都和x(t-k)具有相关关系,所以自相关系数p(k)里实际掺杂了其他变量对x(t)与x(t-k)的影响。
取值在-1到1之间。
AIC和BIC统计量
AIC和BIC选择更简单的模型,所以统计量的值越小越好。
AIC:赤池信息准则(AkaikeInformation Criterion,AIC)
BIC:贝叶斯信息准则(Bayesian Information Criterion,BIC)
k为模型参数个数,n为样本数量,L为似然函数;
我们常用的是AIC准则,AIC鼓励数据拟合的优良性但是尽量避免出现过度拟合(Overfitting)的情况。所以优先考虑的模型应是AIC值最小的那一个模型。
为了控制计算量,我们限制AR最大阶不超过5,MA最大阶不超过5。 但是这样带来的坏处是可能为局部最优。
timeseries是待输入的时间序列,是pandas.Series类型,max_ar、max_ma是p、q值的最大备选值。
order.bic_min_order返回以BIC准则确定的阶数,是一个tuple类型。
残差检验
为什么要做残差检验
- 残差(Residual)在检查预测模型是否完全捕捉数据中的信息时很有用。一个好的预测方法的残差有以下特点:
(1)Residual之间是无相关性的:
如果Residual之间是有相关性的,那么残差中还有信息可以用到预测中。
(2)Residual的均值为0:
如果Residual均值非0,那么预测存在偏差(bias)。
不满足上述两条的预测模型都可以改进来提升效果。当然,并不是意味着满足这两条的模型不可以改进。
ARIMA的优缺点
-
优点: 模型十分简单,只需要内生变量而不需要借助其他外生变量。
-
缺点:
1.要求时序数据是稳定的(stationary),或者是通过差分化(differencing)后是稳定的。
2.本质上只能捕捉线性关系,而不能捕捉非线性关系。
注意,采用ARIMA模型预测时序数据,必须是稳定的,如果不稳定的数据,是无法捕捉到规律的。比如股票数据用ARIMA无法预测的原因就是股票数据是非稳定的,常常受政策和新闻的影响而波动。
来个代码实战
import sys
import os
import pandas as pd
import numpy as np
# TSA from Statsmodels
import statsmodels.api as sm
import statsmodels.formula.api as smf
import statsmodels.tsa.api as smt
# Display and Plotting
import matplotlib.pylab as plt
import seaborn as sns
filename_ts = 'data/sentiment.csv'
ts_df = pd.read_csv(filename_ts, index_col=0, parse_dates=[0])
n_sample = ts_df.shape[0]
print(ts_df.shape)
print(ts_df.head())
# Create a training sample and testing sample before analyzing the series
n_train=int(0.95*n_sample)+1
n_forecast=n_sample-n_train
#ts_df
ts_train = ts_df.iloc[:n_train]['value']
ts_test = ts_df.iloc[n_train:]['value']
print(ts_train.shape)
print(ts_test.shape)
print("Training Series:", "\n", ts_train.tail(), "\n")
print("Testing Series:", "\n", ts_test.head())
def tsplot(y, lags=None, title='', figsize=(14, 8)):
fig = plt.figure(figsize=figsize)
layout = (2, 2)
ts_ax = plt.subplot2grid(layout, (0, 0))
hist_ax = plt.subplot2grid(layout, (0, 1))
acf_ax = plt.subplot2grid(layout, (1, 0))
pacf_ax = plt.subplot2grid(layout, (1, 1))
y.plot(ax=ts_ax) # 折线图
ts_ax.set_title(title)
y.plot(ax=hist_ax, kind='hist', bins=25) #直方图
hist_ax.set_title('Histogram')
smt.graphics.plot_acf(y, lags=lags, ax=acf_ax) # ACF自相关系数
smt.graphics.plot_pacf(y, lags=lags, ax=pacf_ax) # 偏自相关系数
[ax.set_xlim(0) for ax in [acf_ax, pacf_ax]]
sns.despine()
fig.tight_layout()
return ts_ax, acf_ax, pacf_ax
tsplot(ts_train, title='A Given Training Series', lags=20);
# Fit the model
arima200 = sm.tsa.SARIMAX(ts_train, order=(2,0,0)) # ARIMA季节性模型,至于p,d,q需要按照下面的方法选择
model_results = arima200.fit()
# 此处运用BIC(贝叶斯信息准则)进行模型参数选择
# 另外还可以利用AIC(赤池信息准则),视具体情况而定
import itertools
p_min = 0
d_min = 0
q_min = 0
p_max = 4
d_max = 0
q_max = 4
# Initialize a DataFrame to store the results
results_bic = pd.DataFrame(index=['AR{}'.format(i) for i in range(p_min,p_max+1)],
columns=['MA{}'.format(i) for i in range(q_min,q_max+1)])
for p,d,q in itertools.product(range(p_min,p_max+1),
range(d_min,d_max+1),
range(q_min,q_max+1)):
if p==0 and d==0 and q==0:
results_bic.loc['AR{}'.format(p), 'MA{}'.format(q)] = np.nan
continue
try:
model = sm.tsa.SARIMAX(ts_train, order=(p, d, q),
#enforce_stationarity=False,
#enforce_invertibility=False,
)
results = model.fit() 此处的result包含了很多信息,具体如果用到需要自己去查询
# http://www.statsmodels.org/stable/tsa.html
# print("results.bic",results.bic)
# print("results.aic",results.aic)
results_bic.loc['AR{}'.format(p), 'MA{}'.format(q)] = results.bic
except:
continue
results_bic = results_bic[results_bic.columns].astype(float)
fig, ax = plt.subplots(figsize=(10, 8))
ax = sns.heatmap(results_bic,
mask=results_bic.isnull(),
ax=ax,
annot=True,
fmt='.2f',
);
ax.set_title('BIC');
//annot
//annotate的缩写,annot默认为False,当annot为True时,在heatmap中每个方格写入数据
//annot_kws,当annot为True时,可设置各个参数,包括大小,颜色,加粗,斜体字等
# annot_kws={'size':9,'weight':'bold', 'color':'blue'}
#具体查看:https://blog.csdn.net/m0_38103546/article/details/79935671
# Alternative model selection method, limited to only searching AR and MA parameters
train_results = sm.tsa.arma_order_select_ic(ts_train, ic=['aic', 'bic'], trend='nc', max_ar=4, max_ma=4)
print('AIC', train_results.aic_min_order)
print('BIC', train_results.bic_min_order)
#残差分析 正态分布 QQ图线性
model_results.plot_diagnostics(figsize=(16, 12));
过程中的显示
-
PACF,ACF
-
AIC,BIC热度图
AIC和BIC统计量值越小越好,热度图呈黑色的。 -
残差检验图
QQ图是线性的说明残差白噪声检验通过了。
开始预测
model = ARIMA(stock_train, order=(1, 1, 1),freq='W-MON')
result = model.fit()
pred = result.predict('20140609', '20160701',dynamic=True, typ='levels')
# 此处注意,2014060必须能在训练集数据中能够找到,后边的20160701则不用
print (pred)
plt.figure(figsize=(6, 6))
plt.xticks(rotation=45)
plt.plot(pred)
plt.plot(stock_train)
参考资料
时间序列金融偏
fbprophet
时间序列ARIMA小栗子
ARIMA的p,d,q定阶方法