Python中带置信区间的指数时间序列预测方法求助
背景
我有一组来自随机指数增长过程的短时间序列数据,希望将最后几个观测值与基于前期观测的合理预测值进行对比。这可通过对增长率拟合正态分布来实现,拟合过程如下:
import pandas as pd import numpy as np import scipy import scipy.stats data = np.asarray([292, 291, 289, 295, 294, 313, 305, 308]) ds = pd.DataFrame({"data": data}) growth = (data[1:] - data[:-1])/data[:-1] norm_mu, norm_sigma = scipy.stats.norm.fit(growth[:-2]) print("2.1%: {0:f}, mean: {1:f}, 97.9%: {2:f}, std: {3:f}".format(norm_mu - 2 * norm_sigma, norm_mu, norm_mu + 2 * norm_sigma, norm_sigma))
拟合结果约为均值=0.014,标准差=0.027,因此第一期预测的95.8%置信区间(2倍标准差)为(-0.04, 0.068),转换到时间序列上为(313*(1-0.04)=300.5, 313*(1+0.068)=334.3)
问题
第一期预测较为简单,可通过增长率的正态分布得到置信区间并转换到时间序列上。但后续期数的预测存在问题:第二期的期望分布(两个同分布正态随机变量的乘积)不再是正态分布,而是两个卡方分布的和,如相关数理结论所述,后期情况会更复杂。
我希望能找到Python中已有的工具库,计算上述需求的置信区间,或是采用类似合理方法实现指数增长过程的预测。
尝试使用statsmodels的解决方案
Statsmodels为线性时间序列提供了AutoReg和ARIMA模型,可轻松生成并绘制置信区间,但由于是线性模型,预测结果不符合指数增长过程,且置信区间过窄,与第一期估计的(300.5, 334.3)相比尤为明显。
from statsmodels.tsa.ar_model import AutoReg import matplotlib.pyplot as plt future_length = 2 future = {} model = AutoReg(ds.iloc[:-2], lags=1) model_fit = model.fit() prediction = model_fit.get_prediction(len(ds)-2, len(ds)-3+future_length) future['mean'] = list(ds.iloc[-3]) + list(np.asarray(prediction.predicted_mean)) future['95_low'] = list(ds.iloc[-3]) + list(np.asarray(prediction.conf_int(alpha=0.95).loc[:, 'lower'])) future['95_high'] = list(ds.iloc[-3]) + list(np.asarray(prediction.conf_int(alpha=0.95).loc[:, 'upper'])) future['50_low'] = list(ds.iloc[-3]) + list(np.asarray(prediction.conf_int(alpha=0.5).loc[:, 'lower'])) future['50_high'] = list(ds.iloc[-3]) + list(np.asarray(prediction.conf_int(alpha=0.5).loc[:, 'upper'])) future['time'] = np.arange(len(ds)-3, len(ds)-3 + len(future['mean'])) fig, ax = plt.subplots(1, 1) ax.plot(ds.index, ds["data"], color="k") ax.fill_between(future['time'], future['50_low'], future['50_high'], color="b", alpha=0.4) ax.fill_between(future['time'], future['95_low'], future['95_high'], color="b", alpha=0.4) ax.plot(future['time'], future['mean'], color="b") plt.show()

内容的提问来源于stack exchange,提问作者0range
相关产品推荐
相关产品推荐

