基于ARIMA+SARIMA的航空公司 RPM 时间序列预测模型

news2024/12/21 13:59:47

 

🤵‍♂️ 个人主页:@艾派森的个人主页

✍🏻作者简介:Python学习者
🐋 希望大家多多支持,我们一起进步!😄
如果文章对你有帮助的话,
欢迎评论 💬点赞👍🏻 收藏 📂加关注+


目录

1.项目背景

2.数据集介绍

3.技术工具

4.实验过程

4.1导入数据

4.2数据预处理

4.3探索性分析

4.4特征工程

4.5构建模型


1.项目背景

        评估航空公司的运输量和运输需求。因此,对航空公司 RPM 的时间序列预测具有重要的商业意义,可以帮助航空公司进行运输规划、航班安排和市场营销决策。

        在航空业中,因素如季节性、节假日、燃油价格、宏观经济状况等都会对乘客需求产生影响,这些影响因素使得航空公司 RPM 的时间序列数据呈现出一定的复杂性和波动性。为了更准确地预测航空公司 RPM,传统的统计方法往往无法很好地处理这些复杂的时间序列特征,因此需要更加先进和灵活的预测模型。

        ARIMA (AutoRegressive Integrated Moving Average) 模型是一种经典的时间序列分析方法,可以用于捕捉时间序列数据的自相关和趋势性。SARIMA (Seasonal AutoRegressive Integrated Moving Average) 则是在 ARIMA 模型基础上加入季节性因素的模型,能够更好地处理具有季节性变动的时间序列数据。

        基于ARIMA+SARIMA的航空公司 RPM 时间序列预测模型,将结合ARIMA和SARIMA模型的优势,综合考虑航空公司 RPM 时间序列数据的趋势性和季节性变动,从而提高预测的准确性和可靠性。这种模型可以帮助航空公司更好地了解和预测未来乘客需求,有助于他们进行合理的运输资源配置和市场策略制定。

2.数据集介绍

        数据集来源于Kaggle,原始数据集共有249条,17个变量。

关于此文件

2003 年 1 月至 2023 年 9 月美国所有商业航空公司的非季节性调整每月航空交通数据。

注:

收入乘客里程 = 乘客数量和飞行距离,以千 (000) 为单位

可用座位里程 = 座位数和飞行距离,以千 (000) 为单位

负载系数 = 乘客里程占可用座位的比例- 英里数百分比 (%)

3.技术工具

Python版本:3.9

代码编辑器:jupyter notebook

4.实验过程

4.1导入数据

导入第三方库并加载数据集

import pandas as pd
import matplotlib.pyplot as plt 
import matplotlib.dates as mdates
import seaborn as sns
import numpy as np
import statsmodels.api as sm
import warnings
warnings.filterwarnings("ignore")

df= pd.read_csv('air traffic.csv')
df.head()

查看数据大小

查看数据基本信息

4.2数据预处理

将非数值型变量转换为数值型变量

# 数据类型转换
for col in df.columns:
    if df[col].dtype == 'object': 
        df[col] = pd.to_numeric(df[col].str.replace(',', ''), errors='coerce')
df.info()

# 由于我们正在做时间序列预测,现在让我们处理月份和年份列
# 这里我们将合并月份和年份,同时将日期设置为每月的第一天
df['Date'] = pd.to_datetime({'year': df['Year'], 'month': df['Month'], 'day': 1})
# 我们把日期设为索引
df.set_index('Date')

4.3探索性分析

# 让我们看看所有变量相对于日期的趋势
all_columns = [col for col in df.columns if col != 'Date']
for column in all_columns:
    plt.figure(figsize=(10, 4))  
    sns.lineplot(data=df, x='Date', y=column)
    plt.title(column)
    plt.xticks(rotation=45)
    plt.tight_layout()
    plt.show()

新冠疫情的影响非常明显。

对于这个时间序列项目,我们将预测Dom_RPM:国内收入乘客里程数,这是航空公司流量的度量,计算付费乘客在国内航班上飞行的里程数。这是航空公司的一项关键绩效指标,显示了国内付费旅客的数量。

4.4特征工程

拆分数据集为训练集和测试集

# 我们来做一个新的更简单的df
new_df = df[['Date', 'Dom_RPM']].copy()
new_df['Date'] = pd.to_datetime(new_df['Date'])
new_df.set_index('Date', inplace=True)
# 将数据分成训练集和测试集
split_date = pd.to_datetime('2023-01-01')  
train = new_df.loc[:split_date]  
test = new_df.loc[split_date:]   
plt.figure(figsize=(12,6))
plt.plot(new_df.index, new_df['Dom_RPM'], label='Dom_RPM')
plt.axvline(x=split_date, color='red', linestyle='--', label='Train-Test Split')
plt.legend()
plt.show()

平稳性检验

# 平稳性检验
from statsmodels.tsa.stattools import adfuller
st_train= adfuller(train['Dom_RPM'], autolag='AIC')
print(st_train)

预差分结果表明,在5%显著性水平下,时间序列可能是平稳的,因为ADF统计量(-3.4227)更接近5%临界值(-2.8744),p值(0.0102)小于0.05,表明在该水平下可以拒绝单位根的原假设。

plt.figure(figsize=(12, 6))
plt.subplot(2, 1, 1)
pd.plotting.autocorrelation_plot(train['Dom_RPM'])
plt.title(f"Autocorrelation Plot for 'Training Set'")
plt.show()

# 差分训练数据
train['Dom_RPM_diff'] = train['Dom_RPM'].diff().shift(-1)
train.dropna(inplace=True)
# 检查差分后的ADF结果
diff_st_train= adfuller(train['Dom_RPM'], autolag='AIC')
print(diff_st_train)

差异后,ADF统计量略负(-3.5346),p值进一步下降至0.0071,增强了非平稳性原假设的证据。差异后的ADF统计量仍然比5%临界值更负,并且非常接近1%临界值,这表明即使在更严格的显著性水平下,也有更强的平稳性证据。

from statsmodels.tsa.arima.model import ARIMA
import statsmodels.api as sm
plt.plot(train.index, train['Dom_RPM_diff'])
plt.xlabel('Date')
plt.ylabel('Domestic RPM')
plt.xticks(rotation=45)
plt.show()

4.5构建模型

这里我做了一个基本的ARIMA模型

order = (1, 1, 1)
arima_model = sm.tsa.arima.ARIMA(train['Dom_RPM_diff'].dropna(), order=order)  
fitted = arima_model.fit()
print(fitted.summary())

        -4058.061的对数似然和AIC(8122.122)、BIC(8132.552)和HQIC(8126.325)等选择标准表明,该模型在捕获动态方面相对有效。自回归项(ar.L1)在-0.0813处没有统计学意义(p值:0.116),这意味着它可能对模型没有意义,而移动平均项(ma.L1)在-0.9967处非常显著(p值:0.000),表明对模型有很强的影响。误差方差(sigma2)很大,为4.056e+13,表明存在大量无法解释的变异。

        Ljung-Box检验(p值:0.92)表明不存在自相关问题,但Jarque-Bera检验表明残差不遵循正态分布(p值:0.00),异方差检验指向不同的残差方差(p值:0.00),表明潜在的模型规范问题。此外,残差的偏度(-0.82)和高峰度(7.85)进一步质疑了模型的假设。

# 分解时间序列以观察季节模式
decomposition = sm.tsa.seasonal_decompose(train['Dom_RPM'], model='additive', period=12)  
decomposition.plot()
plt.show()

# ACF和PACF图
fig, (ax1, ax2) = plt.subplots(2,1, figsize=(12,8))
sm.graphics.tsa.plot_acf(train['Dom_RPM'], lags=40, ax=ax1)  
sm.graphics.tsa.plot_pacf(train['Dom_RPM'], lags=40, ax=ax2)  
plt.show()

现在准备好运行SARIMA模型,我们必须指定季节性和非季节性组件。

# 非季节性组件 
p = 1 # number of lag observations in the model (AR term)
d = 1 # the number of times that the raw observations are differenced (I term)
q = 0  # the size of the moving average window (MA term)

# 季节性组件
P = 0  # seasonal autoregressive order
D = 1  # essasonal differencing order
Q = 1  # seasonal moving average order
s = 12 # the number of periods in a season
seasonal_order = (P, D, Q, s)

sarima_model = sm.tsa.statespace.SARIMAX(train['Dom_RPM'],
                                          order=(p, d, q),
                                          seasonal_order=seasonal_order,
                                          enforce_stationarity=False,
                                          enforce_invertibility=False)

fitted_sarima = sarima_model.fit()
print(fitted_sarima.summary())

        使用L-BFGS-B算法对SARIMAX模型进行了成功的优化,经过8次迭代后,模型拟合得到了显著改善,最终函数值为14.78。该SARIMAX模型突出了数据中的非季节性和季节性动态,自回归项(0.3927)和季节移动平均项(-0.6053)的系数都很显著,表明存在显著的自回归效应和强烈的季节性影响。模型的拟合良好度指标,包括对数似然值为-3547.654,以及AIC(7101.307)、BIC(7111.405)和HQIC(7105.388)等标准,为评估模型性能提供了依据,值越低通常表示拟合越好。然而,诊断试验显示残差分布的正态性和异方差的证据。

检查模型的残差

residuals = fitted_sarima.resid

# 绘制残差
plt.figure(figsize=(10,6))
plt.plot(residuals)
plt.title('Residuals from SARIMA Model')
plt.axhline(y=0, color='black', linestyle='--')
plt.show() # 绘制残差的ACF和PACF
fig, ax = plt.subplots(1,2,figsize=(15,4))
sm.graphics.tsa.plot_acf(residuals, lags=40, ax=ax[0])
sm.graphics.tsa.plot_pacf(residuals, lags=40, ax=ax[1])
plt.show()

# 直方图和核密度估计
residuals.plot(kind='hist', density=True, bins=30, alpha=0.5)
residuals.plot(kind='kde')
plt.title('Histogram and Density Plot of Residuals')
plt.show()

# Q-Q图检查正态性
sm.qqplot(residuals, line='s')
plt.title('Q-Q Plot of Residuals')
plt.show()

# 正态性的统计检验
from scipy import stats
jb_test = stats.jarque_bera(residuals)
print(f'Jarque-Bera test statistics: {jb_test[0]}, p-value: {jb_test[1]}')

JB检验统计量非常高,p值为0,说明数据不服从正态分布。

# 零均值的统计检验
mean_test = stats.ttest_1samp(residuals, 0)
print(f'Test Statistic: {mean_test.statistic}, p-value: {mean_test.pvalue}')

        由于检验统计量非常接近于0,p值非常高(0.919),因此有强有力的证据表明残差的平均值与0没有显著差异。实际上,这意味着在模型的残差中没有显著的偏差;也就是说,模型没有系统地高估或低估观测值。

# 自相关的统计检验
ljung_box_test = sm.stats.acorr_ljungbox(residuals, lags=[40], return_df=True)
print(ljung_box_test)

Ljung-Box检验检查所有滞后至40的自相关,并检验数据中没有自相关的零假设。相对较低的统计量和较高的p值表明,在40个滞后的模型残差中没有显著的自相关证据。

将假数据纳入SARIMA模型,以考虑COVID-19大流行对时间序列数据的影响。

covid_start = '2020-03-01'  
covid_end = '2021-09-01'    

# 为covid周期创建虚拟变量
train['covid_dummy'] = np.where((train.index >= covid_start) & (train.index <= covid_end), 1, 0)
# 带有外生变量(哑变量)的SARIMA模型
sarimax_model1 = sm.tsa.statespace.SARIMAX(train['Dom_RPM'],
                                           exog=train['covid_dummy'],
                                           order=(p, d, q),
                                           seasonal_order=(P, D, Q, s),
                                           enforce_stationarity=False,
                                           enforce_invertibility=False)

fitted_sarimax1 = sarimax_model1.fit()
print(fitted_sarimax1.summary())

        采用L-BFGS-B算法进行优化,经过9次迭代后呈现收敛性,表明疫情对数据的负面影响显著,如covid dummy系数(-1.936e+07)。自回归分量和季节移动平均分量均具有显著的统计学意义,表明存在重要的时间动态。尽管各种统计指标(如AIC、BIC和对数似然)显示了成功的拟合,但诊断显示残差中没有显著的自相关,但突出了非正态分布和异方差的问题。

        这两个代码片段一起工作,构建了一种更复杂的方式来理解covid对数据的影响。在第一个代码片段中,我们计算了两件事:covid dummy,它告诉我们在特定时间是否发生了covid,以及covid impact,它衡量covid -19的影响如何随着时间的推移而减少。

        然后,在第二个代码片段中,我们使用这些计算来构建SARIMAX模型。该模型不仅考虑了COVID-19是否存在,还考虑了其影响如何随时间变化。

# 让我们再试一次,但要用衰变
covid_start = pd.to_datetime('2020-03-01')
covid_end = pd.to_datetime('2021-09-01')
# 计算自COVID-19开始以来的天数,并将其除以30转换为月份
train['months_since_covid'] = ((train.index - covid_start) / np.timedelta64(1, 'D') / 30).astype(int)
# 线性衰减
duration_in_months = ((covid_end - covid_start) / np.timedelta64(1, 'D') / 30)
train['covid_impact'] = train['months_since_covid'].apply(
    lambda x: max(1 - x / duration_in_months, 0) if x >= 0 else 0
)
sarimax_model_with_decay = sm.tsa.statespace.SARIMAX(
    train['Dom_RPM'],  
    exog=train[['covid_dummy', 'covid_impact']],
    order=(p, d, q),
    seasonal_order=(P, D, Q, s),
    enforce_stationarity=False,
    enforce_invertibility=False
)

fitted_sarimax_with_decay = sarimax_model_with_decay.fit()
print(fitted_sarimax_with_decay.summary())

        在解释中,带有这些系数的SARIMAX模型表明,covid -19时期对数据有很大的负面影响(显然……),covid - dummy表明显著降低。covid - 19影响系数表明,随着时间的推移,影响会减弱,这表明大流行的最初冲击正在逐步恢复。

        这是我们对未来12个月的预测。它首先生成一组未来日期,从训练数据中的最后一个日期开始,跨越未来12个月。然后,它创建两个数组,future_covid - dummy和future_covid - impact,来表示预测的外生变量。Future_covid_dummy假设未来不会有covid影响,因此在整个预测期内将所有值设置为0。而future_covid - impact则假设COVID-19的影响逐渐减弱,在12个月的预测期内从0.5下降到0。然后将这些数组组合成df future_exog,它将在进行预测时用作外生变量。

# 预测期数(未来12个月)
n_periods = 12
future_dates = pd.date_range(train.index[-1] + pd.offsets.MonthBegin(), periods=n_periods, freq='M')
# 假设新冠病毒开始消失,那么影响将从0.5降至0
future_covid_dummy = [0] * n_periods  
future_covid_impact = np.linspace(start=0.5, stop=0, num=n_periods)  #
# 组合成df
future_exog = pd.DataFrame({'covid_dummy': future_covid_dummy, 'covid_impact': future_covid_impact}, index=future_dates)
n_periods = 12  
forecast = fitted_sarimax_with_decay.get_forecast(steps=n_periods, exog=future_exog)
forecast_mean = forecast.predicted_mean
forecast_conf_int = forecast.conf_int()

下面是预测图

# 利用历史数据绘制预测图
plt.figure(figsize=(10, 6))
plt.plot(train.index, train['Dom_RPM'], label='Historical')
plt.plot(pd.date_range(train.index[-1], periods=n_periods, freq='M'), forecast_mean, label='Forecast')
plt.fill_between(pd.date_range(train.index[-1], periods=n_periods, freq='M'), forecast_conf_int.iloc[:, 0], forecast_conf_int.iloc[:, 1], color='red', alpha=0.3)
plt.legend()
plt.show()

# 让我们把我们的预测和测试进行比较
plt.figure(figsize=(10, 6))
plt.plot(train.index, train['Dom_RPM'], label='Historical', color='blue')
plt.plot(forecast_mean.index, forecast_mean, label='Forecast', color='red')
plt.fill_between(forecast_conf_int.index, forecast_conf_int.iloc[:, 0], forecast_conf_int.iloc[:, 1], color='red', alpha=0.3)
plt.plot(test.index, test['Dom_RPM'], label='Actual Test Set', color='green')

plt.title('Comparison between the Test and Forecast')
plt.xlabel('Date')
plt.ylabel('Dom_RPM (in millions)')
plt.legend()
plt.show()

预测结果与实际测试数据有些接近。虽然与测试集相比,预测似乎被低估了。

资料获取,更多粉丝福利,关注下方公众号获取

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1487606.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++入门全集(4):类与对象【下】

一、再谈构造函数 1.1 构造函数体内赋值 我们知道&#xff0c;在创建对象时&#xff0c;编译器会自动调用构造函数给对象中的各个成员变量一个合适的初始值 class Date { public:Date(int year, int month, int day){_year year;_month month;_day day;}private:int _yea…

leetcode 长度最小的子数组

在本题中&#xff0c;我们可以知道&#xff0c;是要求数组中组成和为target的最小子数组的长度。所以&#xff0c;我们肯定可以想到用两层for循环进行遍历&#xff0c;然后枚举所有的结果进行挑选&#xff0c;但这样时间复杂度过高。 我们可以采用滑动窗口&#xff0c;其实就是…

网络加速CDN详细介绍

1、为什么要有网络加速 互联网从逻辑上看是一张大网&#xff0c;但实际上是由许多小网络组成的&#xff0c;这其中就有小网络“互连互通”的问题&#xff0c;典型的就是各个电信运营商的网络&#xff0c;比如国内的电信、联通、移动三大家。 这些小网络内部的沟通很顺畅&#…

c++之通讯录管理系统

1&#xff0c;系统需求 通讯录是一个记录亲人&#xff0c;好友信息的工具 系统中需要实现的功能如下&#xff1a; 1&#xff0c;添加联系人&#xff1a;向通讯录中添加新人&#xff0c;信息包括&#xff08;姓名&#xff0c;性别&#xff0c;年龄&#xff0c;联系电话&#…

计算机网络-第2章 物理层

本章内容&#xff1a;物理层和数据通信的概念、传输媒体特点&#xff08;不属于物理层&#xff09;、信道复用、数字传输系统、宽带接入 2.1-2.2 物理层和数据通信的概念 物理层解决的问题&#xff1a;如何在传输媒体上传输数据比特流&#xff0c;屏蔽掉传输媒体和通信手段的差…

Java:三种代理模式示例

什么是代理模式&#xff1f; 代理&#xff08;Proxy&#xff09;是一种设计模式&#xff0c;为其他对象提供一种代理以控制对这个对象的访问。 代理模式的组成 抽象角色&#xff1a;通过接口或抽象类声明真实角色实现的业务方法。代理角色&#xff1a;实现抽象角色&#xff…

kibana自动补全功能失效的几个原因

文章目录 不能自动补全index&#xff1f;不能自动补全field&#xff1f; 不能自动补全index&#xff1f; 当用户在 kibana 的 Dev Tools 页面手写查询时&#xff0c;理应可以自动补全 index 的名称&#xff0c;如下图&#xff1a; 如果不能自动补全&#xff0c;则点击 Settin…

【网站项目】295演唱会购票系统

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

在线绘图利器:支持在线使用的电脑画图软件推荐!

计算机绘图软件是现代设计师和创作者必不可少的工具之一。伴随着技术的不断发展&#xff0c;越来越多的在线计算机绘图软件应运而生&#xff0c;为用户提供了更加便捷、高效的创作方法。对初学者而言&#xff0c;选择一款易于使用、功能强大的计算机绘图软件至关重要。本文将介…

Tomcat服务部署优化

目录 一.Tomcat的基本内容 1.概念 2.构成 &#xff08;1&#xff09;web容器 &#xff08;2&#xff09;servlet容器&#xff08;catalina&#xff09; &#xff08;3&#xff09;JSP容器 3.Tomcat顶层架构 &#xff08;1&#xff09;Tomcat中最顶层的容器是Server&…

DCFL: for Oriented Tiny Object Detection

文章目录 AbstractIntroductionContributionRelated Work定向目标检测微小目标检测多尺度学习标签分配上下文信息特征增强MethodOverview动态先验Coarse Prior MatchingFiner Dynamic Posterior MatchingAblation StudyAnalysis不平衡问题的调解可视化速度Conclusionhh 源代码 …

麒麟KYLINSOS服务器操作系统SP3安装

原文链接&#xff1a;安装麒麟服务器操作系统V10 SP3 在当今的IT环境中&#xff0c;内网仓库的部署对于确保网络安全、加快本地访问速度以及保持软件包的一致性至关重要。特别是对于企业和组织而言&#xff0c;内网仓库可以极大地提升工作效率和系统稳定性。今天&#xff0c;我…

ArmSoM Rockchip系列产品 通用教程 之 CAN 使用

CAN 使用 1. CAN 简介 CAN (controller Area Network)&#xff1a;控制器局域网络总线&#xff0c;是一种有效支持分布式控制或实时控制的串行通信网络。 目前世界上绝大多数汽车制造厂商都采用CAN总线来实现汽车内部控制系统之间的数据通信。 RK3568/RK3588的CAN驱动文件&a…

Effective objective-c-- 内存管理

Effective objective-c-- 内存管理 前言理解引用计数引用计数工作原理属性存取方法中的内存管理自动释放池保留环要点 以ARC简化引用计数使用ARC时必须遵循的方法和命名规则变量的内存管理语义ARC如何清理实例变量覆写内存管理方法要点 在dealloc方法中只释放引用并解除监听要点…

品牌与时间函数:在时间的长河中铸造品牌

品牌推广是一个与时间紧密相连的复杂过程。时间不仅是品牌推广的见证者&#xff0c;更是其推动者和塑造者。迅腾文化深刻理解品牌推广与时间之间的微妙关系&#xff0c;提出的“显”的原则&#xff0c;旨在通过巧妙的策略&#xff0c;使品牌在时间的流转中逐渐显现出其特别的魅…

Less is More: Generating Grounded Navigation Instructions from Landmarks

摘要 我们研究根据室内路线捕获的 360 图像自动生成导航指令。现有的生成器视觉基础较差&#xff0c;导致它们依赖语言先验并对物体产生幻觉。我们的 MARKY-MT5 系统通过关注视觉地标来解决这个问题&#xff1b;它包括第一级地标检测器和第二级生成器——多模式、多语言、多任…

基于springboot实现计算机类考研交流平台系统项目【项目源码+论文说明】

基于springboot实现计算机类考研交流平台系统演示 摘要 高校的大学生考研是继高校的高等教育更上一层的表现形式&#xff0c;教育的发展是我们社会的根本&#xff0c;那么信息技术的发展又是改变我们生活的重要因素&#xff0c;生活当中各种各样的场景都存在着信息技术的发展。…

U盘遇阻?解决“位置不可用”的困扰

U盘遇阻&#xff1a;当“位置不可用”成为难题 在数字化时代&#xff0c;U盘已成为我们存储和传输数据的重要工具。然而&#xff0c;当U盘突然提示“位置不可用”时&#xff0c;这无疑是一个令人头疼的问题。这不仅意味着我们无法访问存储在U盘中的文件&#xff0c;而且可能还…

PlantUML - 时序图

时序图主要内容 下面是一个简单的时序图&#xff0c;我们可以很容易并且美观的表达我们的交互流程&#xff0c;只需要在箭头的两边指定一个名字&#xff0c;加上描述即可&#xff1a; startuml bkloanapply -> bkloanapprove : request bkloanapprove --> bkloanapply :…

信息系统安全与对抗-作业2

目录 1、使用自己姓名拼音创建一个账户&#xff0c; 并使用命令和图形化查看 2、使用自己拼音打头字母创建一个隐藏账户 &#xff0c;并使用命令和图形化查看 3、使用命令启动 telnet 服务 4、使用命令打开防火墙 23 端口 5、熟悉LINUX系统&#xff0c;使用命令行创建用户…