用Python搞定MathorCup C题货量预测从ARIMA到LSTM的实战对比附完整代码参加数学建模竞赛的同学都知道货量预测是物流类题目的经典问题。今年的MathorCup C题也不例外第一问就要求预测分拣中心的货量。与往届不同的是今年的数据中包含了双十一这样的异常波动这对传统时间序列模型提出了挑战。本文将带你用Python生态中的工具从基础的ARIMA到最新的LSTM一步步构建预测模型并附上可直接运行的完整代码。1. 数据准备与探索性分析在开始建模前我们需要先理解数据。假设我们已经获得了历史货量数据通常是一个包含日期和货量两列的CSV文件。让我们用pandas加载数据import pandas as pd import matplotlib.pyplot as plt # 加载数据 df pd.read_csv(cargo_data.csv, parse_dates[date], index_coldate) df.plot(figsize(12, 6)) plt.title(Historical Cargo Volume) plt.ylabel(Volume) plt.show()这段代码会生成一个时间序列图帮助我们直观地观察数据的趋势、季节性和异常点。在今年的题目中你可能会在11月11日附近看到一个明显的峰值这就是双十一效应。数据预处理的关键步骤处理缺失值用前后值的平均值填充标记异常点特别是双十一这样的特殊日期数据平稳化通过差分消除趋势# 标记双十一 df[is_double11] df.index.map(lambda x: 1 if x.month 11 and x.day 11 else 0) # 一阶差分 diff df[volume].diff().dropna()2. ARIMA模型经典时间序列预测ARIMA自回归综合移动平均是时间序列预测的经典方法。它包含三个参数(p,d,q)分别代表自回归阶数、差分阶数和移动平均阶数。构建ARIMA模型的步骤确定差分阶数d通过ADF检验判断序列是否平稳确定p和q通过自相关图(ACF)和偏自相关图(PACF)模型拟合与评估from statsmodels.tsa.arima.model import ARIMA from statsmodels.graphics.tsaplots import plot_acf, plot_pacf # 绘制ACF和PACF fig, (ax1, ax2) plt.subplots(2, 1, figsize(12, 8)) plot_acf(diff, axax1) plot_pacf(diff, axax2) plt.show() # 拟合ARIMA(1,1,1)模型 model ARIMA(df[volume], order(1,1,1)) result model.fit() print(result.summary())处理异常值双十一的技巧# 创建干预变量 df[intervention] (df.index 2023-11-01) (df.index 2023-11-15) # 带干预变量的ARIMA model ARIMA(df[volume], order(1,1,1), exogdf[[is_double11, intervention]]) result model.fit()3. ProphetFacebook的时间序列预测工具Prophet是Facebook开发的时间序列预测工具特别适合处理具有强烈季节性模式和节假日效应的数据。Prophet的优势自动处理节假日和特殊事件对缺失数据和异常值具有鲁棒性直观的参数调整from prophet import Prophet # 准备数据格式 prophet_df df.reset_index()[[date, volume]].rename(columns{date: ds, volume: y}) # 定义双十一为特殊节日 double11 pd.DataFrame({ holiday: double11, ds: pd.to_datetime([2022-11-11, 2023-11-11]), lower_window: -2, upper_window: 2, }) # 创建并拟合模型 model Prophet(holidaysdouble11, yearly_seasonalityTrue) model.add_seasonality(namemonthly, period30.5, fourier_order5) model.fit(prophet_df) # 预测未来30天 future model.make_future_dataframe(periods30) forecast model.predict(future) model.plot(forecast)4. LSTM神经网络捕捉复杂非线性关系长短期记忆网络LSTM是一种特殊的循环神经网络特别适合处理时间序列数据中的长期依赖关系。LSTM建模的关键步骤数据标准化创建时间序列样本构建网络架构训练与评估import numpy as np from tensorflow.keras.models import Sequential from tensorflow.keras.layers import LSTM, Dense from sklearn.preprocessing import MinMaxScaler # 数据标准化 scaler MinMaxScaler() scaled_data scaler.fit_transform(df[[volume]]) # 创建时间序列样本 def create_dataset(data, look_back1): X, y [], [] for i in range(len(data)-look_back-1): X.append(data[i:(ilook_back), 0]) y.append(data[i look_back, 0]) return np.array(X), np.array(y) look_back 7 X, y create_dataset(scaled_data, look_back) X np.reshape(X, (X.shape[0], X.shape[1], 1)) # 构建LSTM模型 model Sequential() model.add(LSTM(50, return_sequencesTrue, input_shape(look_back, 1))) model.add(LSTM(50)) model.add(Dense(1)) model.compile(lossmean_squared_error, optimizeradam) # 训练模型 model.fit(X, y, epochs100, batch_size32, verbose1) # 预测 train_predict model.predict(X) train_predict scaler.inverse_transform(train_predict)5. 模型对比与选择现在我们已经实现了三种不同的预测方法接下来需要评估它们的表现并选择最适合的模型。评估指标MAE平均绝对误差RMSE均方根误差MAPE平均绝对百分比误差from sklearn.metrics import mean_absolute_error, mean_squared_error def evaluate(actual, predicted): mae mean_absolute_error(actual, predicted) rmse np.sqrt(mean_squared_error(actual, predicted)) mape np.mean(np.abs((actual - predicted) / actual)) * 100 return {MAE: mae, RMSE: rmse, MAPE: mape} # 划分训练集和测试集 train_size int(len(df) * 0.8) test df[train_size:] # 评估ARIMA arima_eval evaluate(test[volume], arima_predictions) # 评估Prophet prophet_eval evaluate(test[volume], prophet_predictions) # 评估LSTM lstm_eval evaluate(test[volume], lstm_predictions) # 结果对比 results pd.DataFrame({ ARIMA: arima_eval, Prophet: prophet_eval, LSTM: lstm_eval }) print(results)模型选择建议场景推荐模型理由数据量小计算资源有限ARIMA简单快速解释性强有明显季节性和节假日效应Prophet自动处理节假日调参简单数据量大有复杂非线性关系LSTM捕捉复杂模式预测精度高6. 应对运输线路变化的策略题目第二问提到运输线路可能发生变化这会影响分拣中心的货量。我们需要在模型中考虑这种变化。处理线路变化的两种方法引入外部变量将线路变化作为外生变量加入模型模型集成当检测到线路变化时重新训练模型# 方法1在ARIMA中加入外生变量 # 假设我们有线路变化的数据 df[route_change] 0 # 0表示无变化 df.loc[2023-06-01:2023-06-30, route_change] 1 # 6月份有线路变化 model ARIMA(df[volume], order(1,1,1), exogdf[[route_change]]) result model.fit() # 方法2检测变化点并重新训练 from changepoint import Pelt algo Pelt() algo.fit(df[volume].values) change_points algo.predict(pen10) # 在变化点后重新训练模型 for cp in change_points: new_data df.iloc[cp:] # 重新训练模型...7. 完整代码实现与优化技巧最后我们整合所有代码并提供一些优化技巧。完整代码结构/project /data cargo_data.csv /utils preprocessing.py evaluation.py models.py main.py优化技巧特征工程添加星期几、月份等时间特征模型融合结合统计模型和机器学习的优势超参数调优使用GridSearch或贝叶斯优化# 模型融合示例ARIMA LSTM combined_pred 0.5*arima_predictions 0.5*lstm_predictions # 超参数调优示例 from sklearn.model_selection import GridSearchCV from tensorflow.keras.wrappers.scikit_learn import KerasRegressor def create_model(units50, learning_rate0.001): model Sequential() model.add(LSTM(units, input_shape(look_back, 1))) model.add(Dense(1)) model.compile(lossmse, optimizerAdam(learning_ratelearning_rate)) return model param_grid { units: [30, 50, 70], learning_rate: [0.001, 0.01, 0.1] } model KerasRegressor(build_fncreate_model, epochs100, batch_size32, verbose0) grid GridSearchCV(estimatormodel, param_gridparam_grid, cv3) grid_result grid.fit(X, y)在实际比赛中建议先尝试简单的ARIMA模型建立baseline然后逐步尝试更复杂的模型。记得保存所有实验结果这有助于撰写论文时的模型对比部分。