Python ARIMA模型设置500天预测步长仅返回2个有效结果求助
问题描述
大家好:
我正在使用Python构建ARIMA模型,我的数据集包含MasterDate、AREA和QTY三个字段。
代码起始阶段我先对导出的Excel文件做过滤:筛选指定AREA取值的数据,删除GRPCODE列,随后拆分了训练集和验证集。
训练集为MasterDate小于等于2020-12-01的所有历史数据,验证集为MasterDate大于等于2020-11-01的数据,两组数据均按MasterDate分组求和得到,相关核心代码如下:
X_train = df2[df2['MasterDate'] <= '01-12-2020'].groupby(by='MasterDate').sum()X_train.reset_index(inplace = True)X_valid = df2[df2['MasterDate'] >= '01-11-2020'].groupby(by='MasterDate').sum()X_valid.reset_index(inplace = True)
完整代码如下:
我设置ARIMA预测步长为500天,但运行后仅返回2天的有效预测值,其余预测点数值均为134.67,绘图后也只能看到2个预测点,请问是什么原因导致该问题?该如何排查修复?
######################################################################################################## ######################################### Packages / libraries ######################################### ######################################################################################################## import os #provides functions for interacting with the operating system import numpy as np import pandas as pd from matplotlib import pyplot as plt import seaborn as sns ######################################################################################################## ################################################ ARIMA ################################################# ######################################################################################################## # To change scientific numbers to float np.set_printoptions(formatter={'float_kind':'{:f}'.format}) # Increases the size of sns plots sns.set(rc={'figure.figsize':(8,6)}) from statsmodels.tsa.arima.model import ARIMA from statsmodels.tsa.api import ExponentialSmoothing, SimpleExpSmoothing, Holt from sklearn.metrics import mean_squared_error from sklearn.linear_model import LinearRegression from sklearn import linear_model import pmdarima as pm from pmdarima.model_selection import train_test_split from pandas import to_datetime import itertools import warnings import datetime from datetime import datetime warnings.filterwarnings('ignore') ######################################################################################################## ######################################### Read and Filter CSV ########################################## ######################################################################################################## #Read CSV from Boels shared folders (with check) df = pd.read_csv (r'\\nlstd116qvs01\QlikView\QDF\99.Shared_Folders\7.Export\B2-371\12098.csv',sep = ';') print (df) df=df.drop(columns=['GRPCODE']) ##Select only AREA's. Scope! df.loc[df['AREA'].isin(['NL Z5','NL Z1','NL Z2','NL Z3', 'NL Z4'])].to_csv(r'C:\Users\dassej\Documents\Analytics\Eindstage\export_dataframe.csv',index = False, header=True, encoding='utf8') #Read edited CSV from Boels df2 = pd.read_csv (r'C:\Users\dassej\Documents\Analytics\Eindstage\export_dataframe.csv',sep = ',') print (df2) df2['MasterDate'] = pd.to_datetime(df2['MasterDate'], format = '%d-%m-%Y') print(df2) X_train = df2[df2['MasterDate'] <= '01-12-2020'].groupby(by='MasterDate').sum() X_train.reset_index(inplace = True) X_valid = df2[df2['MasterDate'] >= '01-11-2020'].groupby(by='MasterDate').sum() X_valid.reset_index(inplace = True) print('X_train Shape', X_train.shape) print('X_Valid Shape', X_valid.shape) #X_train['MasterDate'].unique() # filtering the train data au = X_train au2 = au print(au) #filtering the valid data au_v = X_valid au_v2 = au_v # set the date into index au2.set_index('MasterDate', inplace=True) au_v2.set_index('MasterDate', inplace=True) # Setting the Index for 6 years index_3_years = pd.date_range(au_v2.index[-0], freq='D', periods = 500) #500 days # Running ARIMA with random numbers model = ARIMA(au2, order=(0,0,1)) model_fit = model.fit() # print summary of fit model print(model_fit.summary()) # The default is to get a one-step-ahead forecast: print(model_fit.forecast(steps=5)) fcast1 = model_fit.forecast(steps=500) #500 days forecast # Saving ARIMA predictions #fcast1 = model_fit.forecast(7)[0] #-> NOT working print(fcast1) # Passing the same index as the others fcast1 = pd.Series(fcast1, index=index_3_years) fcast1 = fcast1.rename("Arima") print(fcast1) # Ploting the predictions fig, ax = plt.subplots(figsize=(15,5)) chart = sns.lineplot(x='MasterDate', y='QTY', data = au) chart.set_title('AU') fcast1.plot(ax=ax, color='red', marker="o", legend=True) au_v2.plot(ax=ax, color='blue', marker="o", legend=True) plt.show() #Printing the AI print('The MSE of ARIMA is:', mean_squared_error(au_v['QTY'].values, fcast1.values, squared=False))
问题原因
- ARIMA阶数设置不合理:你手动指定的
order=(0,0,1)属于1阶移动平均模型(MA(1)),该模型的固有属性是仅能输出1步有效预测,超过1步的预测值会直接收敛到训练集序列的均值,也就是你看到的固定值134.67,这是模型特性,不是代码运行错误。 - 时间序列不连续:你对原始数据按MasterDate分组求和时,没有补全无数据的日期,训练集和验证集的时间序列都是非连续的,导致500个预测值中只有2个日期和实际的验证集日期匹配,绘图时自然只显示2个有效点。
- 预测索引对齐错误:你生成预测序列的索引起始是验证集的第一个日期,而训练集的结束日期是2020-12-01,预测的起始日期应该是训练集结束后的第一天,否则预测值和实际值的日期错位,也会导致有效匹配的点极少。
修复步骤
- 补全时间序列的连续日期,将索引设置为日度频率,缺失值填0:
# 在set_index之后添加该行,把au2转为连续日度序列 au2 = au2.asfreq('D', fill_value=0)
- 用pmdarima的auto_arima自动选择最优ARIMA阶数,代替手动指定的不合理阶数:
# 替换原来的ARIMA初始化代码 model = pm.auto_arima(au2['QTY'], seasonal=False, suppress_warnings=True) model_fit = model.fit(au2['QTY'])
- 修正预测索引的起始日期,和训练集的结束日期衔接:
# 替换原来的index_3_years生成逻辑 index_500_days = pd.date_range(start=au2.index.max() + pd.Timedelta(days=1), freq='D', periods=500)
- 计算MSE时只取预测值和验证集重叠的日期对应的值,避免维度不匹配:
# 取两个序列的交集日期计算误差 common_idx = fcast1.index.intersection(au_v2.index) rmse = mean_squared_error(au_v2.loc[common_idx, 'QTY'], fcast1.loc[common_idx], squared=False) print('The RMSE of ARIMA is:', rmse)
内容的提问来源于stack exchange,提问作者Jesse Boels
相关产品推荐
相关产品推荐

