资讯动态

基于ARIMA模型的旅游人数预测分析方法与实践指南

发布时间:2026/9/19 18:59:53 来源:尧图企业网站定制
简介这份面向本科毕业设计的完整文档以青岛市2000—2012年季度旅游人数为样本系统展示ARIMA模型在旅游人数预测中的完整应用适合旅游管理、统计与数据分析方向学生参考建模流程。整个压缩包仅1个doc格式文档大小924KB包含摘要、关键词、目录与正文方便直接阅读使用。资源已有257人学习下载。文档详细梳理多项式插值、拟合模型、余弦趋势拟合与时间序列方法的差异并给出ARIMA建模步骤、季节模型预测以及MATLAB和R软件的实现思路与代码调用要点读者可据此复现青岛旅游人数预测实验。还针对数据质量、缺失值和模型选择等现实挑战作了说明并提及机器学习、深度学习的未来改进方向对完成毕业设计或课程报告有直接参考价值。1. ARIMA模型在旅游人数预测课题里的定位旅游人数数据几乎总是带着上升趋势和明显的周期波动用线性回归去硬拟合残差会留下大量自相关信息直接上LSTM小样本下又容易过拟合。ARIMA模型用差分消除趋势用自回归和移动平均项刻画动态依赖在月度粒度的旅游数据上往往能以很小的计算成本换来稳定输出的效果。这篇文把“基于ARIMA模型的旅游人数预测分析”这个毕业设计课题按真实工程路径拆开数据怎么清洗、平稳性怎么判、阶数怎么定、模型怎么诊断、结果怎么评估涉及的关键代码可以直接照搬复现。适合正在做课程设计或毕设的学生也适合想为后续做更好模型建立基线的数据分析师。2. 旅游人数数据预处理的完整流程日期索引、缺失值与平稳性旅游人数数据常见于Excel导出或数据库查询结果落到手里大多是“日期人数”两列。两列看着干净真正丢给ARIMA模型之前仍要过几个坎日期频率是否统一、有没有几个月缺失数据、序列是否平稳、方差是否稳定。这几个坎跨不过去后面定阶和拟合的结论都会有偏差。2.1 统一日期索引缺失月份要显式暴露出来原始记录可能按日流水存储也可能按景区分开存放第一步是把日期解析成datetime类型转为统一索引再重采样到按月频率。看一段可直接复用的准备代码import pandas as pd import numpy as np import matplotlib.pyplot as plt df pd.read_csv(tourism_data.csv, parse_dates[date]) df df[[date, tourists]].copy() df.set_index(date, inplaceTrue) df.sort_index(inplaceTrue) # 按月初对齐重采样缺失月份会暴露为NaN monthly df[tourists].resample(MS).sum() print(monthly[monthly.isnull()]) # 打印缺失月份位置 # 线性插值填补中间缺口bfill兜底首部缺失 monthly monthly.interpolate(methodlinear).fillna(methodbfill)resample(MS)把流水数据压缩成月度总量如果原始数据里某些月份根本没有记录压缩结果对应位置就是NaN。对旅游数据来说跳月通常是数据入库遗漏或平台切换造成用线性插值比用上个月的值回填更合理因为旅游人数在月份之间有连续的趋势关系插值能保留这种趋势。插值后检查一下describe()输出的最大值和最小值若某月人数突然是历史月均的十倍以上大概率是录入错误需要回到原始数据核实。异常值是否剔除没有标准答案但要在论文里记录下处理过程说明原因比悄悄删掉更有说服力。2.2 用ADF检验判平稳不要凭曲线形状下结论ARIMA模型的差分阶数d由平稳性检验决定。常规做法是ADF单位根检验p值小于0.05则拒绝“存在单位根”的原假设认为序列平稳。直接看原始折线图判平稳不严谨尤其旅游数据同时有趋势和季节波动时肉眼判断极易出错。代码上可以写一个小函数把原始序列和差分后序列各检验一次from statsmodels.tsa.stattools import adfuller def check_stationarity(series, name): result adfuller(series.dropna(), autolagAIC) print(f{name}: ADF统计量{result[0]:.4f}, p值{result[1]:.4f}) return result[1] p_raw check_stationarity(monthly, 原始序列) diff_series monthly.diff().dropna() p_diff check_stationarity(diff_series, 一阶差分后)autolagAIC让函数自动选择一个合适的滞后阶避免人为指定滞后数影响结果。当p_raw大于0.05而p_diff小于0.05时差分阶数d取1这是旅游数据最常见的情况。如果一阶差分后p值仍然大于0.05先尝试对数变换再差分通常可以解决方差非平稳问题。更长期的旅游数据不排除d等于2的可能但d超过2的序列要小心过度差分它会抹掉过多真实信息让模型预测区间过宽反而失去参考价值。数据现象处理动作预期结果长期上升趋势ADF p值接近1一阶差分p值降到0.05以下旺季淡季波动幅度差异巨大取对数后再差分方差趋于稳定ADF结论可信季节性强差分后ACF在滞后12仍显著使用SARIMA季节性信息被单独建模2.3 对数变换与数据长度的处理策略旅游人数的旺季和淡季可以差出数倍序列方差随水平变化属正常现象。取对数能让全年波动幅度更接近常数值帮助模型更平稳地估计参数。预测完成后用指数映射还原但要注意映射会放大原预测误差因此如果只是做趋势判断不取对数问题也不大。数据长度方面ARIMA模型对数据量要求不算苛刻60个月以上的月度数据基本够用但少于36个月时参数估计的置信区间会很宽。遇到数据不足时把绝对人数换成“较去年同期增长率”再建模平滑效果往往更好。预处理阶段随手做一张数据覆盖率表记下起止年月、缺失月数、有效样本数后面写论文和答辩都会用到。3. ARIMA模型定阶与参数选择ACF/PACF图谱和AIC网格搜索定阶是ARIMA模型使用中最容易卡壳的环节。模型的三个参数p、d、q各有分工d是差分数已经在上一章定了p是自回归阶数表达当前值和过去值的关系q是移动平均阶数表达当前值与过去预测误差的关系。p和q的确定方法业内习惯先看差分序列的自相关图与偏自相关图再用信息准则做二次筛选。3.1 图形的识别规则截尾与拖尾p和q的候选取自ACF和PACF的形状。PACF的截尾位置对应pACF的截尾位置对应q而拖尾意味着相关函数的衰减是缓慢且持续的无法直接截断。画图和观察要做的事如下from statsmodels.graphics.tsaplots import plot_acf, plot_pacf fig, axes plt.subplots(2, 1, figsize(12, 8)) plot_acf(diff_series, lags24, axaxes[0]) plot_pacf(diff_series, lags24, axaxes[1], methodywm) plt.tight_layout() plt.show()methodywm是偏自相关计算中一种比较可靠的估计方法小样本下比默认方法更不容易出现虚假尖峰。lags设为24对应24个月基本覆盖两年的月度数据。观察的重点是那些越过蓝色置信区间的柱子只出现在滞后1和滞后2图形就有向(1,1,1)或(2,1,1)收敛的迹象如果在多个滞后点都出现孤立尖峰就要考虑季节性未消除。落在置信区间内的柱子不要过度解读显著性判断本身允许5%左右的误报率。3.2 遍历p、q组合用AIC与BIC仲裁图形已经把候选项缩到三五组再用穷举法比较import itertools from statsmodels.tsa.arima.model import ARIMA best_aic float(inf) results [] for p, q in itertools.product(range(0, 4), range(0, 4)): try: model ARIMA(monthly, order(p, 1, q)) result model.fit() results.append((p, q, round(result.aic, 2))) if result.aic best_aic: best_aic result.aic best_order (p, 1, q) except Exception: continue print(pd.DataFrame(results, columns[p, q, AIC])) print(最优阶数:, best_order)try-except不是可有可无statsmodels在部分(p,q)组合下可能因矩阵奇异或收敛失败直接抛异常没有异常捕获整个循环会中断。results列表里会看到不同阶数的AIC排序最佳阶数通常落在(1,1,1)、(2,1,1)、(2,1,2)之间。BIC准则也可以一起打印BIC对参数数量惩罚更重倾向于选择更简洁的模型当AIC和BIC意见不一致时偏向BIC建议的模型通常更稳妥。候选阶数AIC值BIC值选择倾向(1,1,0)1342.611348.54过简可能残差有剩余信息(2,1,1)1331.871343.72备选(2,1,2)1329.241345.01推荐3.3 网格搜索的两个边界d固定和局部收敛网格搜索有一个容易犯的错把d也放进循环里比较AIC。不同d值下模型使用的样本量不同AIC不能跨样本量比较。正确方式是固定一个d值只搜索p和q。另外statsmodels默认的优化器可能收敛到局部最优假如某个阶数的AIC异常高可以换用model.fit(methodinnovations_mle)重跑一次看结果是否稳定。这两个细节在真实数据上遇到过很多次提前写到代码里可以避免白跑几个小时。4. ARIMA模型拟合、残差诊断与向前预测的完整实现阶数确定后模型的拟合在statsmodels里是简洁的真正的难点在拟合之后残差是否还剩信息、预测区间如何解读、原始量纲如何还原。这一章把这几个环节逐一处理掉。4.1 拟合摘要与残差白噪声检测from statsmodels.stats.diagnostic import acorr_ljungbox model ARIMA(monthly, orderbest_order) fitted model.fit() print(fitted.summary()) # 系数估计、标准误、AIC/BIC都在这里 residuals fitted.resid.dropna() lb acorr_ljungbox(residuals, lags[6, 12, 24], return_dfTrue) print(lb)Ljung-Box检验的原假设是残差不存在自相关p值大于0.05表示残差已接近白噪声。检查时有个细节各滞后阶的p值应全部大于0.05只要有一个滞后阶的p值小于0.05就要怀疑残差里还有周期性依赖存在。summary()中还可以看到每个系数的P值P值大于0.05的系数说明该参数对模型的贡献不显著。fit对象的plot_diagnostics()会把标准化残差、QQ图、直方图和残差ACF画成一张四联图QQ图两端有翘尾只表明残差偏态不影响主要预测结论做模型诊断报告时这张图直接放进附件即可。诊断项观察位置合格标准Ljung-Boxlb输出的p值lags6,12,24全部大于0.05系数显著性summary中的Pz残差ACF图plot_diagnostics右下角柱子大多在置信带内4.2 预测未来的月度人数及置信区间forecast fitted.get_forecast(steps3) mean_forecast forecast.predicted_mean conf_int forecast.conf_int(alpha0.05) for i, (m, low, high) in enumerate( zip(mean_forecast, conf_int.iloc[:, 0], conf_int.iloc[:, 1]), start1 ): print(f第{i}月预测: {m:.1f}万人, 95%置信区间: [{low:.1f}, {high:.1f}]万人)get_forecast(steps3)从训练序列末尾向后预测返回对象包含点预测和区间。多步预测的误差积累是正常现象置信区间随着步长扩大是模型表达不确定性的方式不要把区间扩大误判为模型不稳定。旅游数据的预测报告里建议总是同时给出点预测和区间官方口径也习惯用区间表示预测可信度。若区间太宽实质是历史数据信息量不足无法靠调参根本解决。4.3 对差分与对数变换做量纲还原fit对象内部完成差分的逆变换直接输出的预测值已在原始量纲。最容易出错的是手动差分又手动建模的场景预测出的是差分值必须先与最后一个观测值累加才能得到原始人数。多步预测时累加误差会传播一旦某一步算错后续全错。因此基本原则是能交给ARIMA模型内部处理的差分就不要手动做。对数变换同理如果预处理阶段用了np.log预测输出要做np.exp才能放到汇报材料里。5. 滚动预测与误差评估验证ARIMA模型的真实能力模型在训练集上的拟合优度没有参考价值大部分时间它在测试集上的表现要差得多。时间序列评估必须遵循顺序原则不能用随机划分。5.1 按时间顺序切分训练集与测试集把最近12到24个月划为测试集前面的作为训练集train_size int(len(monthly) * 0.8) train, test monthly.iloc[:train_size], monthly.iloc[train_size:]如果旅游数据经历了明显的结构断点比如某段时间出现异常波动导致序列形态发生不可逆变化按比例切分就不是好方案。此时以断点为界断点之前做训练断点之后做测试这样测试集内部是相对稳定的时期误差分布更均匀。测试集长度为12个月时可以覆盖完整的淡旺季循环评估结果更全面。5.2 逐步滚动预测代码滚动预测的每个时间点都用最新数据重新拟合模拟真实业务中“每月报表更新后预测下月”的节奏history list(train) predictions [] for t in range(len(test)): model ARIMA(history, orderbest_order) model_fit model.fit() y_pred model_fit.forecast(steps1).iloc[0] predictions.append(y_pred) history.append(test.iloc[t]) test_series list(test) mae np.mean(np.abs(np.array(test_series) - np.array(predictions))) rmse np.sqrt(np.mean((np.array(test_series) - np.array(predictions)) ** 2)) print(fMAE: {mae:.2f}万人) print(fRMSE: {rmse:.2f}万人)每次循环都重新实例化ARIMA模型并调用fit这是滚动预测区别于一次性多步预测的核心。代价是训练耗时增加换来的是预测结果更接近线上部署时的行为。如果要比较一次性多步预测和滚动预测的差异可以将两者各跑一遍分别记录误差论文里说明两种场景的使用差异即可。5.3 多维度误差指标与常见误差来源指标计算方式关注点MAE预测误差绝对值的平均平均偏了多少人RMSE均方误差的算术平方根大误差被显著放大MAPE百分比误差的平均消除景区规模影响MAPE计算时要特别注意真实值为0或接近0的时间点会放大误差。这也是旅游数据很少用MAPE做唯一指标的原因。误差分析环节有一个经验做法按月份把残差分组找出残差绝对值最大的几个月分析它们的共同点多半落在旺季或假期所在的月份此时可以在论文里提出引入节假日特征作为后续改进方向为答辩留一个言之有物的延伸点。RMSE显著高于MAE时说明某个月份的预测偏离非常大要把该月数据单独拿出来检查。6. 从ARIMA模型到SARIMA季节性建模的扩展和实战技巧基础ARIMA模型的完整流程已经走通最后补三个在旅游预测里绕不开的进阶点。6.1 旅游数据默认适合SARIMAARIMA适合做对比基线当ACF在滞后12或24处依然显著说明季节性没有被ARIMA模型消化这时应改用SARIMA。SARIMA在p,d,q之外增加了一组季节性参数P,D,Q和季节周期S月度数据取S12sarima_model ARIMA(train, order(1, 1, 1), seasonal_order(1, 1, 1, 12)) sarima_fit sarima_model.fit() print(sarima_fit.summary())SARIMA相当于同时建立了相邻月和相邻年之间的依赖。旅游人数与节假日和气候周期高度相关相邻年的同一月份存在强关联SARIMA把这种关联纳入模型多步预测曲线不会出现相位漂移。因此旅游项目里ARIMA通常作为基线模型SARIMA才是主模型两者对比出结论是毕业设计里最常见的写法。6.2 定阶策略在SARIMA中同样适用但搜索空间更大SARIMA的季节性参数P、D、Q仍可用ACF观察但季节性滞后处的截尾/拖尾模式对应P、Q的取值。搜索空间会从几十组膨胀到几百组跑一遍网格耗时可观。建议分两步走先用固定季节参数(1,1,1,12)搜索p、q再固定p、q搜索P、Q最后微调。搜索代码可以复用第三章的模板加上seasonal_order参数即可。6.3 打印预测对比表是答辩现场最直接的交付物最后不管用哪种模型把测试集的预测值、真实值、残差按月份对齐输出为一张表格。这张表比任何指标都有说服力评委能一眼看出模型在哪几个月偏差最大。表格里顺带标上当月是否有长假或重大活动帮助解释误差成因。模型调参到这一步已经具备完整的交付场景。若还想深入可从残差序列的方差结构入手试GARCH做残差建模但对旅游人数预测的提升已经比较有限。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价