基于ARIMA模型的旅游人数预测分析:从数据准备到预测评估的完整流程

发布时间:2026/10/12 3:13:14
基于ARIMA模型的旅游人数预测分析:从数据准备到预测评估的完整流程
简介这份毕业设计文档面向统计学、数据分析及旅游管理相关专业的本科生与研究人员围绕旅游人数预测这一实际问题以青岛市2000至2012年各季度旅游人数为样本系统比较多项式插值、拟合模型、余弦趋势拟合与ARIMA时间序列模型的预测效果最终验证ARIMA模型在刻画季节性波动与自相关性方面的优势。资源包内含1个doc文件约924KB完整收录摘要、绪论、数据收集与来源、传统预测方法介绍、ARIMA建模步骤、季节模型预测、结论及附录等章节并附有MATLAB与R软件的实现思路可作为时间序列分析课程设计或同类课题的参考范本。目前已有258人学习下载适合需要掌握ARIMA建模流程、理解旅游人数预测方法对比及撰写毕业设计的读者借鉴。1. 旅游人数预测这件事ARIMA 到底能解决什么做旅游人数预测的毕业设计最常见的翻车不是模型跑不出来而是数据一上来就套auto.arima结果预测曲线平得像一条直线答辩老师一句「你这预测跟均值有什么区别」直接把人问住。ARIMA差分自回归移动平均本质上是拿历史序列自己的滞后项和滞后误差来解释当前值它擅长的是有趋势、有季节、短期波动可被历史解释的序列——旅游人数恰好符合这个画像旺季淡季循环、节假日脉冲、逐年增长趋势。这篇笔记围绕「基于 ARIMA 模型的旅游人数预测分析」这个题目把数据从哪来、平稳性怎么判、阶数怎么定、R 和 MATLAB 两条路怎么落地、预测区间怎么给一步步讲清楚。适合正在做时间序列方向毕业设计、需要一套能跑通又能写进论文的完整流程的人也适合已经跑出结果但说不清参数含义、被追问就卡壳的熟手。2. 数据准备与平稳性检验ARIMA 能不能用的第一道关ARIMA 不是万能钥匙它对数据有个硬前提差分之后要近似平稳。很多人跳过这一步直接建模最后 AIC 挑出来的阶数毫无意义。这一章先把数据组织成时间序列对象再用单位根检验判断到底差几次分。2.1 旅游人数数据的组织方式与缺失值处理旅游人数数据通常有两种来源一是统计年鉴里的月度或年度接待人次二是景区票务系统导出的日度流水。毕业设计里最稳妥的是用月度数据因为日度数据噪声大、节假日效应复杂ARIMA 处理起来阶数会飙得很高。拿到数据后第一件事是检查时间轴是否连续——月度数据里缺一个月后面差分全错位。R 里用ts()构造时间序列对象关键是frequency参数月度数据填 12季度填 4年度填 1。这个参数决定了后面季节差分和分解的周期。# 读取旅游人数月度数据假设两列date(年月) 和 visitors raw - read.csv(tourism_monthly.csv, stringsAsFactors FALSE) # 转成 Date 类型注意月度数据补上日 raw$date - as.Date(paste0(raw$date, -01)) # 按时间排序防止原始文件乱序 raw - raw[order(raw$date), ] # 构造月度时间序列start 填起始年份和月份 ts_data - ts(raw$visitors, start c(2015, 1), frequency 12) # 检查缺失时间序列里 NA 会传染到差分 sum(is.na(ts_data)) # 若有缺失用线性插值补齐旅游人数季节性明显插值比均值填充合理 if (any(is.na(ts_data))) { ts_data - na.interp(ts_data) # 需 forecast 包 }逻辑说明frequency 12是月度数据的标准写法它让 R 知道每 12 个点构成一个周期后续stl()分解和季节差分都依赖这个设定。na.interp来自 forecast 包对季节性序列做线性插值比直接填均值更贴近真实走势。参数上start必须和真实起始年月一致写错了整条时间轴偏移后面所有检验都白做。MATLAB 这边对应的是timeseries对象或直接对向量操作但做 ARIMA 更常用 Econometrics Toolbox 的arima函数。数据导入后同样要确认无缺失% 读取数据假设第一列是序号第二列是人数 data readmatrix(tourism_monthly.csv); visitors data(:, 2); % 检查缺失 if any(isnan(visitors)) % 线性插值补齐 visitors fillmissing(visitors, linear); end % 构造时间序列月度数据 ts_data timeseries(visitors, 1:length(visitors));MATLAB 的fillmissing用linear对内部缺失做线性插值首尾缺失需要额外处理一般毕业设计数据首尾完整不用太担心。2.2 用 ADF 检验判断差分阶数 d平稳性检验的核心工具是 ADF增广迪基-福勒检验。原假设是「序列存在单位根即不平稳」p 值小于 0.05 才能拒绝原假设、认为平稳。旅游人数原始序列几乎不可能直接平稳因为年度增长趋势摆在那通常要做一阶差分甚至一阶季节差分。R 里用tseries包的adf.testlibrary(tseries) # 原始序列 ADF 检验 adf_original - adf.test(ts_data) print(paste(原始序列 p 值:, adf_original$p.value)) # 一阶差分 diff1 - diff(ts_data, differences 1) adf_diff1 - adf.test(diff1) print(paste(一阶差分 p 值:, adf_diff1$p.value)) # 若一阶差分仍不平稳考虑季节差分 diff_seasonal - diff(ts_data, lag 12) adf_seasonal - adf.test(diff_seasonal) print(paste(季节差分 p 值:, adf_seasonal$p.value))逻辑说明diff(ts_data, differences 1)做一阶普通差分消除线性趋势diff(ts_data, lag 12)做季节差分消除年度周期。ADF 检验的 p 值只是参考实际还要看差分后序列的时序图是否围绕零均值波动。参数上adf.test默认带截距不带趋势项如果序列有明显趋势要加alternative stationary并考虑k滞后阶数一般让函数自动选。MATLAB 用adftest% 原始序列 ADF 检验 [h_orig, p_orig] adftest(visitors); fprintf(原始序列 p 值: %.4f\n, p_orig); % 一阶差分 diff1 diff(visitors); [h_d1, p_d1] adftest(diff1); fprintf(一阶差分 p 值: %.4f\n, p_d1); % 季节差分月度 lag12 diff_s visitors(13:end) - visitors(1:end-12); [h_s, p_s] adftest(diff_s); fprintf(季节差分 p 值: %.4f\n, p_s);MATLAB 的adftest返回h为 1 表示拒绝单位根平稳0 表示不拒绝。p值同样以 0.05 为界。注意季节差分后序列长度减少 12后续建模要对齐。提示ADF 检验对滞后阶数敏感R 的adf.test默认用trunc((length(x)-1)^(1/3))选滞后MATLAB 默认用 0。如果结论模棱两可手动指定滞后阶数再跑一遍别只信一次结果。3. 定阶与建模p、d、q 怎么选才不玄学差分阶数 d 定了之后剩下 p自回归阶和 q移动平均阶的选取。这一步是 ARIMA 最容易被质疑的地方因为很多人直接auto.arima一把梭答辩时说不清为什么是 (2,1,1) 而不是 (1,1,1)。这一章把 ACF/PACF 定阶和自动定阶两条路都讲透再落到模型拟合和残差检验。3.1 看 ACF 和 PACF 图定 p 和 qACF自相关函数和 PACF偏自相关函数是定阶的经典工具。经验规则ACF 拖尾、PACF 截尾用 AR(p)p 取 PACF 最后一个显著非零的滞后ACF 截尾、PACF 拖尾用 MA(q)q 取 ACF 最后一个显著非零的滞后两者都拖尾用 ARMA(p,q)阶数靠 AIC 辅助。R 里画图# 对一阶差分后的序列画 ACF 和 PACF par(mfrow c(1, 2)) acf(diff1, lag.max 36, main ACF of 一阶差分) pacf(diff1, lag.max 36, main PACF of 一阶差分) par(mfrow c(1, 1))逻辑说明lag.max 36对月度数据够用看 3 个周期。ACF 图里蓝色虚线是 95% 置信区间超出虚线的滞后显著。如果 ACF 在 lag 12、24 处仍有明显尖峰说明季节效应没消干净要考虑 SARIMA 或加季节差分。参数上diff1是上一章得到的一阶差分序列别拿原始序列画。MATLAB 对应figure; subplot(1,2,1); autocorr(diff1, 36); title(ACF of 一阶差分); subplot(1,2,2); parcorr(diff1, 36); title(PACF of 一阶差分);MATLAB 的autocorr和parcorr默认画 20 个滞后第二个参数指定 36。图里同样有置信带判断逻辑一致。3.2 auto.arima 自动定阶与 AIC 准则手工看 ACF/PACF 容易主观auto.arima用 AICc 逐步搜索最优阶数是毕业设计里最省事的做法。但要注意自动定阶不是免死金牌它可能选出过拟合的复杂模型需要结合残差检验判断。library(forecast) # 自动定阶允许季节项d 和 D 让函数自己定 fit_auto - auto.arima(ts_data, seasonal TRUE, stepwise TRUE, approximation FALSE) summary(fit_auto) # 查看选出的阶数 print(paste(ARIMA 阶数:, fit_auto$arma[1], fit_auto$arma[6], fit_auto$arma[2]))逻辑说明seasonal TRUE允许函数考虑季节 ARIMASARIMA对月度旅游数据几乎必开。stepwise TRUE用逐步搜索加快速度approximation FALSE保证用精确似然毕业设计数据量不大没必要近似。fit_auto$arma返回一个向量第 1 位是 AR 阶 p第 6 位是差分阶 d第 2 位是 MA 阶 q第 3、4 位是季节 AR 和 MA 阶。MATLAB 没有直接的auto.arima但可以用arima函数配合循环遍历 p、q 组合比较 AICbestAIC Inf; bestModel []; for p 0:3 for q 0:3 try mdl arima(p, 1, q); est estimate(mdl, visitors, Display, off); if est.AIC bestAIC bestAIC est.AIC; bestModel est; bestPQ [p, q]; end catch continue; % 某些组合不收敛跳过 end end end fprintf(最优 p%d, q%d, AIC%.2f\n, bestPQ(1), bestPQ(2), bestAIC);逻辑说明arima(p, 1, q)构造 ARIMA 模型第二个参数 1 是差分阶 d。estimate做参数估计est.AIC取信息准则。循环里用try-catch是因为某些阶数组合会导致估计不收敛直接跳过。参数上p 和 q 遍历到 3 对月度数据通常够再高容易过拟合。3.3 残差白噪声检验模型合不合格的硬标准模型拟合完必须做残差检验。如果残差还有自相关说明模型没把信息提取干净预测不可信。Ljung-Box 检验是标准工具原假设是「残差为白噪声」p 值大于 0.05 才合格。# 残差 Ljung-Box 检验lag 取 12 或 24 checkresiduals(fit_auto) # 手动看 p 值 Box.test(residuals(fit_auto), lag 24, type Ljung-Box)逻辑说明checkresiduals一次性输出残差图、ACF 图和 Ljung-Box 结果非常直观。Box.test的lag 24对月度数据合适检验前 24 个滞后的自相关是否联合为零。如果 p 值小于 0.05说明残差还有结构要么加阶数要么检查是否漏了季节项。MATLAB 对应resid infer(bestModel, visitors); [h_lb, p_lb] lbqtest(resid, Lags, 24); fprintf(Ljung-Box p 值: %.4f\n, p_lb);infer从拟合好的模型里提取残差lbqtest做 Ljung-Box 检验。h_lb 0表示不拒绝白噪声假设模型合格。注意残差检验通过不代表预测一定准它只说明模型把历史信息用完了。旅游人数受突发事件疫情、极端天气影响大这些是 ARIMA 解释不了的论文里要如实写进局限性。4. 预测与评估把模型输出变成能写进论文的结论模型定好之后核心产出是未来若干期的预测值和预测区间。这一章讲预测函数怎么用、预测区间怎么解读、精度指标怎么算以及怎么把结果可视化到能直接放进论文。4.1 用 forecast 生成预测值和置信区间R 的forecast函数是标准工具h参数指定预测期数level指定置信水平。# 预测未来 12 个月95% 置信区间 fc - forecast(fit_auto, h 12, level c(80, 95)) # 查看预测值 print(fc) # 提取预测均值和区间 pred_mean - as.numeric(fc$mean) pred_lower - as.numeric(fc$lower[, 95%]) pred_upper - as.numeric(fc$upper[, 95%]) # 画图 plot(fc, main 旅游人数 ARIMA 预测, xlab 年份, ylab 人数)逻辑说明h 12预测未来一年level c(80, 95)同时给 80% 和 95% 区间论文里通常报 95%。fc$mean是点预测fc$lower和fc$upper是区间下上限列名对应置信水平。预测区间随预测步长变宽这是 ARIMA 的固有特性论文里可以解释为「不确定性随时间累积」。MATLAB 对应% 预测未来 12 期 [yF, yMSE] forecast(bestModel, 12, Y0, visitors); % 95% 置信区间 yLower yF - 1.96 * sqrt(yMSE); yUpper yF 1.96 * sqrt(yMSE); % 画图 figure; plot(visitors, b); hold on; plot(length(visitors)(1:12), yF, r, LineWidth, 1.5); plot(length(visitors)(1:12), yLower, r--); plot(length(visitors)(1:12), yUpper, r--); legend(历史数据, 预测值, 95% 下界, 95% 上界); title(旅游人数 ARIMA 预测);逻辑说明forecast返回预测均值yF和预测方差yMSE置信区间用正态近似1.96 * sqrt(MSE)算。Y0参数传入历史观测值保证预测从序列末尾接续。参数上1.96对应 95% 置信水平80% 用1.28。4.2 精度评估MAPE、RMSE 和 MAE 怎么选预测完要报精度指标。常用三个MAPE平均绝对百分比误差、RMSE均方根误差、MAE平均绝对误差。MAPE 最直观论文里报得最多但它对接近零的真实值敏感旅游人数不会接近零可以放心用。# 用训练集最后 12 个月做验证 train - window(ts_data, end c(2022, 12)) test - window(ts_data, start c(2023, 1)) fit_train - auto.arima(train, seasonal TRUE) fc_test - forecast(fit_train, h length(test)) # 计算精度 accuracy(fc_test, test)逻辑说明window切分训练集和测试集accuracy一次性输出 ME、RMSE、MAE、MAPE 等指标。参数上训练集和测试集的比例一般 8:2 或留最后一年做测试。accuracy的第一个参数是预测对象第二个是真实值顺序别反。MATLAB 手动算% 假设 test 是真实值yF 是预测值 mape mean(abs((test - yF) ./ test)) * 100; rmse sqrt(mean((test - yF).^2)); mae mean(abs(test - yF)); fprintf(MAPE%.2f%%, RMSE%.2f, MAE%.2f\n, mape, rmse, mae);逻辑说明MAPE 用绝对值除以真实值再平均乘 100 转百分比。RMSE 和 MAE 单位跟原始数据一致。参数上test和yF长度必须一致MATLAB 里向量减法要求维度匹配。4.3 把预测结果画成论文能用的图论文里的预测图要包含历史数据、预测均值、置信区间三部分最好再标出训练/测试分界。R 的forecast包自带autoplot或plot但默认样式偏素可以手动调。library(ggplot2) # 构造数据框 df_hist - data.frame(time time(ts_data), value as.numeric(ts_data)) df_pred - data.frame(time time(fc$mean), mean as.numeric(fc$mean), lower as.numeric(fc$lower[, 95%]), upper as.numeric(fc$upper[, 95%])) ggplot() geom_line(data df_hist, aes(x time, y value), color steelblue) geom_line(data df_pred, aes(x time, y mean), color red) geom_ribbon(data df_pred, aes(x time, ymin lower, ymax upper), fill red, alpha 0.2) labs(x 年份, y 旅游人数, title ARIMA 预测结果) theme_minimal()逻辑说明geom_ribbon画置信区间带alpha 0.2控制透明度。df_hist和df_pred的时间轴要能接上time(fc$mean)自动生成预测期的时间标签。参数上颜色和主题按论文要求调theme_minimal比默认主题干净。提示预测图里历史数据和预测数据的颜色要区分明显置信区间用浅色填充。答辩时老师最常问「这个区间为什么越来越宽」提前准备好解释ARIMA 的预测方差随步长线性增长反映长期不确定性。5. 避坑与排查ARIMA 旅游预测里最容易翻车的 5 个点这一章全是血泪经验。ARIMA 看起来公式简单实操里坑不少下面 5 条是毕业设计里出现频率最高的。5.1 现象预测曲线几乎水平跟均值差不多原因差分阶数 d 选大了或者模型退化成 MA(0) 即纯均值。常见于auto.arima在数据噪声大时选出 (0,1,0)预测值就是最后一个差分值的累积看起来像直线。解决先检查 ADF 检验是否真的需要差分。如果原始序列已经平稳p 0.05d 取 0。再看 ACF/PACF如果所有滞后都不显著说明序列接近白噪声ARIMA 本来就不适合考虑换 LSTM 或加外生变量如节假日哑变量。5.2 现象auto.arima 跑得极慢或报错原因approximation FALSE加seasonal TRUE在大数据量下搜索空间爆炸或者序列里有 NA 导致似然计算失败。解决先确认数据无 NA再设stepwise TRUE和approximation TRUE快速试一版确定大致阶数后再用精确似然重跑。数据量超过 500 个点考虑先做季节分解再建模。5.3 现象残差 Ljung-Box 检验 p 值小于 0.05原因模型没提取完信息常见于漏了季节项或阶数不够。解决先看残差 ACF 图如果 lag 12、24 处有尖峰加季节 AR/MA 阶SARIMA。如果低阶滞后显著加 p 或 q。每次加完重新检验别一次加太多导致过拟合。5.4 现象预测区间宽到没有参考价值原因预测步长太长或者模型参数估计不确定性大。解决缩短预测期毕业设计一般预测 6 到 12 个月足够。如果必须预测更长考虑用滚动预测每次预测一步把预测值加入历史再预测下一步但要注意误差累积。论文里如实写区间宽度别硬说预测很准。5.5 现象R 和 MATLAB 跑出不同阶数原因两个软件的定阶准则和搜索策略不同。R 的auto.arima默认用 AICcMATLAB 手动循环用 AIC且收敛判据不一样。解决以残差检验和预测精度为准别纠结阶数是否一致。论文里写清楚用的软件和准则附上 ACF/PACF 图和残差检验结果比报一个阶数更有说服力。6. 进阶技巧季节 ARIMA 与滚动预测的实操细节基础流程跑通后想让论文更有深度可以上 SARIMA 和滚动预测。SARIMA 在 ARIMA 基础上加了季节项(P,D,Q)mm 是周期长度月度数据 m12。R 里auto.arima已经支持但手动指定季节阶数有时更可控。# 手动指定 SARIMA(p,d,q)(P,D,Q)[12] fit_sarima - Arima(ts_data, order c(1, 1, 1), seasonal list(order c(1, 1, 1), period 12)) summary(fit_sarima) # 残差检验 Box.test(residuals(fit_sarima), lag 24, type Ljung-Box)逻辑说明order c(1,1,1)是非季节部分seasonal里order c(1,1,1)是季节部分period 12是月度周期。参数上季节阶数一般不超过 1再高容易过拟合。Arima函数来自 forecast 包和auto.arima同源但手动控制更强。滚动预测rolling forecast是另一个加分项。做法是用固定窗口的历史数据训练预测下一步然后把真实值加入窗口再预测下一步循环下去。这样能模拟真实预测场景评估更可靠。# 滚动预测窗口 60 个月预测未来 12 个月 window_size - 60 n - length(ts_data) predictions - numeric(12) for (i in 1:12) { train_end - n - 12 i - 1 train_data - window(ts_data, start time(ts_data)[train_end - window_size 1], end time(ts_data)[train_end]) fit_roll - auto.arima(train_data, seasonal TRUE) predictions[i] - forecast(fit_roll, h 1)$mean } # 对比真实值 actual - window(ts_data, start time(ts_data)[n - 11]) mape_roll - mean(abs((actual - predictions) / actual)) * 100 print(paste(滚动预测 MAPE:, round(mape_roll, 2), %))逻辑说明window_size 60用 5 年历史做训练窗口每次预测 1 步。train_end控制窗口右端逐步右移。参数上窗口大小影响模型稳定性太小欠拟合太大反应迟钝一般取 2 到 3 个季节周期。predictions存 12 步预测值最后和真实值算 MAPE。MATLAB 滚动预测思路一样用循环调estimate和forecast注意每次重新估计模型耗时较长可以固定阶数只更新参数。方法优点缺点适用场景一次性预测简单快速长期预测误差大短期 6 个月内滚动预测模拟真实场景评估可靠计算量大论文精度对比SARIMA捕捉季节周期阶数多易过拟合月度/季度数据最后说个我自己的习惯每次跑完 ARIMA我都会把残差图、ACF 图、预测图三张图并排存下来答辩前翻一遍比背公式管用。参数可以调图不会骗人。希望帮到你。本文还有配套的精品资源点击获取