10个SKU批量时间序列预测问题排查:仅用24个月数据生成预测
问题诊断与解决方案
核心问题点
- 训练数据未充分利用:代码硬编码
train_size=24,仅用前24个月数据训练,而非全部36个月历史数据生成未来预测。 - 预测目标错误:当前预测的是25-36月的测试集数据(共12个月),而非需求的未来3个月。
- SKU数据丢失:循环中每次迭代会覆盖
naive_forecast_values等变量,最终仅保留最后一个SKU的预测结果,其余9个SKU的数据全部丢失。 - MA模型实现错误:用
ExponentialSmoothing模拟移动平均是错误的,需改用合适的移动平均计算方式。
修正后的完整代码
import pandas as pd import numpy as np from statsmodels.tsa.api import SimpleExpSmoothing, ExponentialSmoothing, SARIMAX from sklearn.metrics import mean_squared_error # 加载数据 data = pd.read_csv('sales_data.csv', index_col=0) # 初始化存储所有SKU预测结果的字典 all_forecasts = { 'SKU': [], 'Naive_Month1': [], 'Naive_Month2': [], 'Naive_Month3': [], 'ARIMA_Month1': [], 'ARIMA_Month2': [], 'ARIMA_Month3': [], 'Holt_Month1': [], 'Holt_Month2': [], 'Holt_Month3': [], 'SES_Month1': [], 'SES_Month2': [], 'SES_Month3': [], 'MA_Month1': [], 'MA_Month2': [], 'MA_Month3': [] } # 定义未来需要预测的月份数 forecast_steps = 3 # 遍历每个SKU for sku in data.index: print(f"处理SKU: {sku}") # 获取当前SKU的全部36个月销售数据 sales_data = data.loc[sku].values # ---------------------- # 1. 简单朴素法 (SNaive) # ---------------------- # 朴素法用最后一个观测值作为未来预测 naive_forecast = np.repeat(sales_data[-1], forecast_steps) # ---------------------- # 2. ARIMA模型 # ---------------------- arima_model = SARIMAX(sales_data, order=(1, 0, 1), seasonal_order=(1, 1, 1, 12), enforce_stationarity=False, enforce_invertibility=False) arima_results = arima_model.fit(disp=False) arima_forecast = arima_results.forecast(steps=forecast_steps) # ---------------------- # 3. Holt's 指数平滑法 # ---------------------- holt_model = ExponentialSmoothing(sales_data, trend='add', seasonal='add', seasonal_periods=12) holt_results = holt_model.fit() holt_forecast = holt_results.forecast(steps=forecast_steps) # ---------------------- # 4. 简单指数平滑法 (SES) # ---------------------- ses_model = SimpleExpSmoothing(sales_data) ses_results = ses_model.fit() ses_forecast = ses_results.forecast(steps=forecast_steps) # ---------------------- # 5. 移动平均法 (MA) # ---------------------- # 使用最近12个月的移动平均值作为预测(可根据需求调整窗口大小) ma_window = 12 ma_forecast = np.repeat(np.mean(sales_data[-ma_window:]), forecast_steps) # 将当前SKU的预测结果存入字典 all_forecasts['SKU'].append(sku) # 朴素法 all_forecasts['Naive_Month1'].append(naive_forecast[0]) all_forecasts['Naive_Month2'].append(naive_forecast[1]) all_forecasts['Naive_Month3'].append(naive_forecast[2]) # ARIMA all_forecasts['ARIMA_Month1'].append(arima_forecast[0]) all_forecasts['ARIMA_Month2'].append(arima_forecast[1]) all_forecasts['ARIMA_Month3'].append(arima_forecast[2]) # Holt's all_forecasts['Holt_Month1'].append(holt_forecast[0]) all_forecasts['Holt_Month2'].append(holt_forecast[1]) all_forecasts['Holt_Month3'].append(holt_forecast[2]) # SES all_forecasts['SES_Month1'].append(ses_forecast[0]) all_forecasts['SES_Month2'].append(ses_forecast[1]) all_forecasts['SES_Month3'].append(ses_forecast[2]) # MA all_forecasts['MA_Month1'].append(ma_forecast[0]) all_forecasts['MA_Month2'].append(ma_forecast[1]) all_forecasts['MA_Month3'].append(ma_forecast[2]) # 打印当前SKU的预测结果(可选) print(f"{sku} 未来3个月预测完成") # 转换为DataFrame forecast_df = pd.DataFrame(all_forecasts) # 设置SKU为索引 forecast_df.set_index('SKU', inplace=True) # 四舍五入为整数(销售数据通常为整数) forecast_df = forecast_df.round().astype(int) # 导出到Excel forecast_df.to_excel('sku_forecasts.xlsx', index_label='SKU') print("所有SKU预测结果已导出到sku_forecasts.xlsx")
关键修正说明
- 全量数据训练:移除训练/测试拆分,直接使用全部36个月数据训练模型,确保预测基于完整历史信息。
- 目标预测调整:设置
forecast_steps=3,明确生成未来3个月的预测值。 - 多SKU结果存储:用结构化字典存储每个SKU的所有预测结果,避免变量覆盖导致的数据丢失。
- MA模型修正:改用最近N个月的平均值作为移动平均预测(示例用12个月窗口,可按需调整)。
- 结果格式化:将预测结果按SKU+月份+方法的结构整理,导出的Excel更易阅读和分析。
内容的提问来源于stack exchange,提问作者Red Eye
相关产品推荐
相关产品推荐

