销量预测模型评估进阶:从 MAPE 到库存周转率与缺货损失金额

MAPE 降到 10% 就够了吗?不一定。我们用一个真实案例证明:低 MAPE 的模型可能导致更严重的缺货损失。本文引入业务导向的评估指标,并给出离线模拟测试方案。

一、MAPE 的局限性

平均绝对百分比误差(MAPE)是最常用的回归指标,但在零售库存场景中它有三个硬伤:

  1. 对零值敏感:实际销量为 0 时,MAPE 无穷大(但缺货导致的零值正是我们要处理的)。
  2. 对称惩罚:预测 100 实际 50 与预测 50 实际 100 的 MAPE 相同,但在业务上,低估导致缺货损失往往比高估导致的积压成本更严重。
  3. 不直接反映库存成本:库存管理的核心目标是在满足需求的前提下最小化总成本(持有成本 + 缺货成本 + 订货成本)。MAPE 无法直接映射到这些成本。

例如:某 SKU 日均销量 100 件,单价 10 元,毛利率 30%。

· 模型 A:MAPE 12%,但经常在促销日低估销量,导致缺货损失每月 2000 元。

· 模型 B:MAPE 15%,但对促销捕捉准确,缺货损失仅 500 元,且库存周转更快。

显然模型 B 更优,但 MAPE 却认为 A 更好。因此我们需要一套面向业务的评估体系。

二、业务导向的评估指标

2.1 加权绝对百分比误差(WMAPE)

引入销量权重,让高销量 SKU 的误差权重更大,低销量 SKU 影响减小。

python 复制代码
def wmape(actual, forecast):
    return np.sum(np.abs(actual - forecast)) / np.sum(actual) * 100

WMAPE 避免了零值问题,且更能反映总体业务影响。

2.2 缺货损失金额(Stockout Cost)

模拟库存策略后,计算因预测不足导致的缺货损失。

假设:

· 每日补货,补货提前期 L 天

· 安全库存系数 z(如 1.65 对应 95% 服务水平)

· 缺货损失 = 缺货数量 × 单件毛利

公式:

python 复制代码
# 简化模拟:预测为 f,实际为 a,可用库存初始为 I0
def simulate_stockout(forecast_series, actual_series, lead_time=2, initial_inventory=100):
    inventory = initial_inventory
    stockout_quantity = 0
    for t in range(len(forecast_series)):
        # 提前期内的总预测需求
        demand_forecast = sum(forecast_series[t:t+lead_time])
        if inventory < demand_forecast:
            shortage = demand_forecast - inventory
            stockout_quantity += shortage
            inventory = 0
        else:
            inventory -= demand_forecast
        # 补货(这里简化为按预测补货,实际可根据策略调整)
        inventory += forecast_series[t]
    return stockout_quantity

实际使用中,我们采用周期性盘点 (R, S) 策略,用预测值驱动补货量,再用真实销量回测缺货次数和金额。

2.3 库存周转率(Inventory Turnover)

周转率 = 年销售成本 / 平均库存成本。预测偏大会导致库存积压,周转率下降。

在离线模拟中,我们可以追踪模拟库存水平,计算平均库存天数:

python 复制代码
def avg_inventory_days(forecast_series, actual_series, lead_time=2):
    inventory_levels = []
    inv = 100  # 初始库存
    for t in range(len(actual_series)):
        inv = max(0, inv - actual_series[t])   # 消耗
        inv += forecast_series[t]              # 补货(按预测)
        inventory_levels.append(inv)
    avg_inv = np.mean(inventory_levels)
    avg_daily_sales = np.mean(actual_series)
    return avg_inv / avg_daily_sales if avg_daily_sales > 0 else 999

2.4 综合成本指标(Total Supply Chain Cost)

将库存持有成本、缺货成本、订货成本相加,形成一个单一数值,直接比较不同预测模型带来的总成本差异。

· 持有成本 = 平均库存 × 单价 × 年持有率(通常 20-30%)

· 缺货成本 = 缺货数量 × 单件毛利

· 订货成本 = 订货次数 × 单次固定成本

三、离线模拟测试:如何科学对比两个模型

我们不需要真实上线就能评估模型。方法:

  1. 取一段历史数据(比如 90 天)作为"验证期"。
  2. 用模型在这段时期每天做预测(只使用截至当天的历史数据,模拟真实环境)。
  3. 将预测值输入库存仿真引擎,记录成本指标。
  4. 对比不同模型(或同一模型不同参数)的总成本。

代码框架(使用 inventory_simulator 自定义类):

python 复制代码
class InventorySimulator:
    def __init__(self, unit_cost, holding_rate, stockout_cost_per_unit, order_fixed_cost):
        self.unit_cost = unit_cost
        self.holding_rate = holding_rate
        self.stockout_cost = stockout_cost_per_unit
        self.order_fixed_cost = order_fixed_cost
        self.inventory = 0
        self.total_holding_cost = 0
        self.total_stockout_cost = 0
        self.total_order_cost = 0

    def step(self, demand, forecast, order_quantity=None):
        # 根据预测确定补货量(简单版:订单上限 = forecast)
        if order_quantity is None:
            order_quantity = max(0, forecast - self.inventory)
        self.inventory += order_quantity
        self.total_order_cost += self.order_fixed_cost * (1 if order_quantity > 0 else 0)
        # 满足需求
        satisfied = min(self.inventory, demand)
        shortage = demand - satisfied
        self.inventory -= satisfied
        self.total_stockout_cost += shortage * self.stockout_cost
        # 持有成本(每日)
        self.total_holding_cost += self.inventory * self.unit_cost * self.holding_rate / 365

    def total_cost(self):
        return self.total_holding_cost + self.total_stockout_cost + self.total_order_cost

将模型A和模型B的预测分别输入仿真,运行完整周期,对比最终总成本。

四、真实案例:MAPE 12% 模型 vs MAPE 15% 模型

数据:某便利店 50 个 SKU,6 个月历史。

指标 模型A(MAPE 12%) 模型B(MAPE 15%)

平均库存天数 18 天 12 天

缺货次数 23 次 7 次

缺货损失金额 ¥3,420 ¥840

持有成本 ¥1,200 ¥800

总成本 ¥4,620 ¥1,640

模型B 虽然 MAPE 更高,但总成本仅为模型A 的 35%。原因是模型A 为追求低误差,过于保守,导致高估安全库存,同时低估了促销日的需求(造成缺货)。

五、将这些指标集成到 API 评估中

我的销量预测 API 目前以 MAPE 为主要优化目标,但对于付费企业用户,我们提供定制化评估报告,包括:

· 基于你历史数据的离线模拟

· 对比现有预测方法(如简单移动平均)的成本节约

· 推荐最优安全库存系数

本文模拟代码已上传 GitHub。欢迎交流你在实际业务中遇到的评估难题。

相关推荐
火山引擎开发者社区19 分钟前
Agent Plan、Coding Plan限时优惠:2.5折畅享多模型!
人工智能
冬奇Lab39 分钟前
AI Workflow 定义的四次演进:从 Markdown 到 JS 脚本,再到分布式多 Agent
javascript·人工智能·agent
冬奇Lab1 小时前
每日一个开源项目(第136篇):OpenMemory - 给 AI Agent 真正的认知记忆引擎
人工智能
黄啊码2 小时前
【黄啊码】微信 AI 把聊天功能和 Vibe Coding打通了,创业者:我又白干了
人工智能
IT_陈寒2 小时前
React的useState居然还有这种坑?我差点删库跑路
前端·人工智能·后端
用户413062258293 小时前
给AI回答加引用角标citation:RAG前端实现
人工智能
米小虾4 小时前
WAIC 2026 倒计时30天:300+ AI 产品全球首发,今年看点全解析
人工智能
码上天下4 小时前
多模态Agent上传图片:前端压缩格式与预览实战
人工智能
姗姗来迟了4 小时前
Vue3封装可复用AI对话组件:一次抽象复盘
人工智能