You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

单SKU列SARIMA模型RMSE结果异常的原因排查及参数调优建议咨询

单SKU列SARIMA模型RMSE结果异常的原因排查及参数调优建议咨询

碰到单个SKU的SARIMA模型RMSE结果异常确实挺闹心的,咱们一步步拆解问题根源,顺便看看你代码里藏着的几个关键问题,大概率能解决你的疑惑:

一、最可能的核心问题:参数范围的硬编码错误

你的代码里有两个致命的参数设置错误,极大概率是那个异常SKU的问题源头:

  1. 差分阶数d的范围被限制死了
    你设置了d = range(0, 1),也就是模型只能用d=0(不做差分)。如果那个异常SKU的时间序列是非平稳的(比如有明显的上升/下降趋势,或者ADF检验不通过),d=0的模型根本无法捕捉序列的趋势性,拟合和预测效果会极差,RMSE自然会异常。
    解决:把d的范围改成d = range(0, 2),允许模型使用d=1来处理非平稳序列。

  2. 季节性周期s硬编码为3完全不符合数据规律
    你构建季节性参数时写了[(x[0], x[1], x[2], 3) for x in ...],这里的第四个参数是SARIMA的季节性周期s,这个值必须严格匹配你的数据时间粒度:

    • 如果是月度数据,s应该设为12;
    • 周度数据设为52;
    • 日度数据设为7;
    • 季度数据设为4。
      硬编码成3的话,对于和这个周期完全不匹配的SKU(比如其他SKU刚好是季度性,但这个SKU是月度性,或者反过来),模型完全学不到季节性规律,预测必然崩盘,RMSE异常。

二、RMSE计算的潜在坑点

你没贴RMSE的具体计算代码,但这部分最容易出错,尤其是多SKU场景:

  • 是不是用训练集的拟合值算RMSE了?如果是用results_SARIMA.fittedvalues和训练集对比,RMSE会偏小,但如果是异常大的话,可能是反过来——用了测试集但预测范围没对齐;
  • 测试集和训练集的时间范围有没有重叠/缺失?比如那个SKU的测试集里有极端值、缺失值,或者预测时用了predict但指定的start/end范围不对,导致预测值和真实值完全错位;
  • 有没有考虑预测方式?SARIMA的get_forecast是向前滚动预测,而predict如果不指定dynamic=True的话是静态预测,不同的预测方式会影响RMSE结果,要确保你用的是符合业务场景的预测逻辑。

三、异常SKU本身的序列特性问题

排除代码问题后,要单独检查那个SKU的时间序列:

  1. 画时序图,看有没有极端值、突变点(比如突然的销量暴涨/暴跌,可能是促销、缺货、数据录入错误);
  2. 做ADF平稳性检验,确认它的平稳性和其他SKU是否有差异;
  3. 检查测试集里有没有特殊事件(比如该SKU在测试期内有新品上市、渠道调整),导致数据分布和训练集完全脱节,模型无法泛化。

四、模型拟合的收敛性问题

你的代码里只做了异常捕获,但有些模型虽然没报错,但根本没收敛,用这种模型的预测值算RMSE完全无效。你需要在拟合后增加收敛性检查:

results_SARIMA = mod.fit(random_state=42)
if not results_SARIMA.mle_retvals['converged']:
    print(f"Model didn't converge for params {param} and seasonal {param_seasonal}")
    continue

五、优化后的参考代码

我把你的代码做了关键修正,加入了正确的参数范围、RMSE计算、收敛性检查:

import itertools
import statsmodels.api as sm
from sklearn.metrics import mean_squared_error
import numpy as np

# 修正参数范围:允许d=1,处理非平稳序列
p = q = range(0, 3)
d = range(0, 2)  # 这里改成0-1,支持d=1差分

# 根据你的数据时间频率设置正确的季节性周期s
# 示例:月度数据设12,周度设52,日度设7,季度设4
data_freq = "monthly"
s = 12 if data_freq == "monthly" else 52 if data_freq == "weekly" else 7

# 非季节性参数组合
pdq = list(itertools.product(p, d, q))

# 季节性参数组合:单独定义P/D/Q,不和非季节性参数绑定
P = D = Q = range(0, 3)
seasonal_pdq = [(x[0], x[1], x[2], s) for x in itertools.product(P, D, Q)]

# 假设当前处理单个SKU(row_value是SKU的索引/标识)
current_sku = row_value
train_data = train_product_premium[current_sku]
test_data = test_product_premium[current_sku]  # 必须有对应的测试集

best_rmse = float('inf')
best_params = None
best_seasonal_params = None

for param in pdq:
    for param_seasonal in seasonal_pdq:
        try:
            mod = sm.tsa.statespace.SARIMAX(
                train_data,
                order=param,
                seasonal_order=param_seasonal,
                enforce_stationarity=False,
                enforce_invertibility=False
            )
            results_SARIMA = mod.fit(random_state=42, disp=False)  # 关闭拟合日志,减少输出
            
            # 检查模型是否收敛
            if not results_SARIMA.mle_retvals['converged']:
                print(f"⚠️  Model didn't converge: params {param}, seasonal {param_seasonal}")
                continue
            
            # 生成测试集的预测(对应测试集长度的步数)
            forecast = results_SARIMA.get_forecast(steps=len(test_data))
            pred_values = forecast.predicted_mean
            
            # 计算RMSE
            rmse = np.sqrt(mean_squared_error(test_data, pred_values))
            
            print(f"✅ Params: {param}, Seasonal: {param_seasonal} → RMSE: {rmse:.4f}")
            
            # 跟踪最优参数
            if rmse < best_rmse:
                best_rmse = rmse
                best_params = param
                best_seasonal_params = param_seasonal
                
        except Exception as e:
            print(f"❌ Error with params {param}, seasonal {param_seasonal}: {str(e)}")
            continue

# 输出当前SKU的最优结果
print(f"\n🏆 Best params for {current_sku}: {best_params}, seasonal {best_seasonal_params} | RMSE: {best_rmse:.4f}")

最后总结排查优先级

  1. 先改d的范围和季节性周期s,这两个是代码里最明显的硬编码错误;
  2. 核对RMSE的计算逻辑,确保用的是测试集真实值和对应预测值;
  3. 检查异常SKU的序列数据,看有没有特殊情况;
  4. 增加模型收敛性检查,排除无效模型的影响。

备注:内容来源于stack exchange,提问作者Nandhini Sasikumar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 12:08:08