"); //-->
下面我们开始使用三种不同的时间序列算法:SARIMA、XGBoost和CNN-LSTM,进行建模并比较。
对于所有三个模型,都使用预测下一个数据点进行预测。Walk-forward验证是一种用于时间序列建模的技术,因为随着时间的推移,预测会变得不那么准确,因此更实用的方法是在实际数据可用时,用实际数据重新训练模型。
在建模之前需要更详细地研究数据。图8显示了SP2数据集中所有特征的相关热图。热图显示了因变量直流功率,与模块温度、辐照和环境温度的强相关性。这些特征可能在预测中发挥重要作用。
在下面的热图中,交流功率显示皮尔森相关系数为1。为了防止数据泄漏问题,我们将直流功率从数据中删除。
SARIMA
季节自回归综合移动平均(SARIMA)是一种单变量时间序列预测方法。由于目标变量显示出24小时循环周期的迹象,SARIMA是一个有效的建模选项,因为它考虑了季节影响。这可以从下面的季节分解图中观察到。
SARIMA算法要求数据是平稳的。有多种方法来检验数据是否平稳,例如统计检验(增强迪基-福勒检验),汇总统计(比较数据的不同部分的均值/方差)和可视化分析数据。在建模之前进行多次测试是很重要的。
增强迪基-富勒(ADF)检验是一种“单位根检验”,用于确定时间序列是否平稳。从根本上说,这是一个统计显著性检验,其中存在一个零假设和替代假设,并根据得出的p值得出结论。
零假设:时间序列数据是非平稳的。
替代假设:时间序列数据是平稳的。
在我们的例子中,如果p值≤0.05,我们可以拒绝原假设,并确认数据没有单位根。
from statsmodels.tsa.stattools import adfuller
result = adfuller(plant2_dcpower.values)
print('ADF Statistic: %f' % result[0]) print('p-value: %f' % result[1]) print('Critical Values:') for key, value in result[4].items(): print('\t%s: %.3f' % (key, value))
从ADF检验来看,p值为0.000553,< 0.05。根据这一统计数据,可以认为该数据是稳定的。然而,查看图2(最上面的图),有明显的季节性迹象(对于被认为是平稳的时间序列数据,不应该有季节性和趋势的迹象),这说明数据是非平稳的。因此,运行多个测试非常重要。
为了用SARIMA对因变量建模,时间序列需要是平稳的。如图9(第一个和第三个图)所示,直流电有明显的季节性迹象。取第一个差值[t-(t-1)]去除季节性成分,如图10所示,因为它看起来类似于正态分布。数据现在是平稳的,适用于SARIMA算法。
SARIMA的超参数包括p(自回归阶数)、d(差阶数)、q(移动平均阶数)、p(季节自回归阶数)、d(季节差阶数)、q(季节移动平均阶数)、m(季节周期的时间步长)、trend(确定性趋势)。
图11显示了自相关(ACF)、部分自相关(PACF)和季节性ACF/PACF图。ACF图显示了时间序列与其延迟版本之间的相关性。PACF显示了时间序列与其滞后版本之间的直接相关性。蓝色阴影区域表示置信区间。SACF和SPACF可以通过从原始数据中取季节差(m)来计算,在本例中为24,因为在ACF图中有一个明显的24小时的季节效应。
根据我们的直觉,超参数的起点可以从ACF和PACF图中推导出来。如ACF和PACF均呈逐渐下降的趋势,即自回归阶数(p)和移动平均阶数(q)均大于0。p和p可以通过分别观察PCF和SPCF图,并计算滞后值不显著之前具有统计学显著性的滞后数来确定。同样,q和q可以在ACF和SACF图中找到。
差阶(d)可以通过使数据平稳的差的数量来确定。季节差异阶数(D)是根据从时间序列中去除季节性成分所需的差异数来估计的。
这些超参数选择可以看这篇文章:https://arauto.readthedocs.io/en/latest/how_to_choose_terms.html
也可以采用网格搜索方法进行超参数优化,根据最小均方误差(MSE)选择最优超参数,包括p = 2, d = 0, q = 4, p = 2, d = 1, q = 6, m = 24, trend = ' n '(无趋势)。
from time import time from sklearn.metrics import mean_squared_error from statsmodels.tsa.statespace.sarimax import SARIMAX
configg = [(2, 1, 4), (2, 1, 6, 24), 'n']
def train_test_split(data, test_len=48): """ Split data into training and testing. """ train, test = data[:-test_len], data[-test_len:] return train, test
def sarima_model(data, cfg, test_len, i): """ SARIMA model which outputs prediction and model. """ order, s_order, t = cfg[0], cfg[1], cfg[2] model = SARIMAX(data, order=order, seasonal_order=s_order, trend=t, enforce_stationarity=False, enfore_invertibility=False) model_fit = model.fit(disp=False) yhat = model_fit.predict(len(data))
if i + 1 == test_len: return yhat, model_fit else: return yhat
def walk_forward_val(data, cfg): """ A walk forward validation technique used for time series data. Takes current value of x_test and predicts value. x_test is then fed back into history for the next prediction. """ train, test = train_test_split(data) pred = [] history = [i for i in train] test_len = len(test)
for i in range(test_len): if i + 1 == test_len: yhat, s_model = sarima_model(history, cfg, test_len, i) pred.append(yhat) mse = mean_squared_error(test, pred) return pred, mse, s_model else: yhat = sarima_model(history, cfg, test_len, i) pred.append(yhat) history.append(test[i]) pass
if __name__ == '__main__': start_time = time() sarima_pred_plant2, sarima_mse, s_model = walk_forward_val(plant2_dcpower, configg) time_len = time() - start_time
print(f'SARIMA runtime: {round(time_len/60,2)} mins')
图12显示了SARIMA模型的预测值与SP2 2天内记录的直流功率的比较。
为了分析模型的性能,图13显示了模型诊断。相关图显示在第一个滞后后几乎没有相关性,下面的直方图显示在平均值为零附近的正态分布。由此我们可以说模型无法从数据中收集到进一步的信息。
*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。