Зачем она нужна
Отдел продаж спрашивает: «насколько точен прогноз?». Ответ «MAE равна 37 штукам» мало что скажет: для хлеба это отлично, для автомобилей — катастрофа. Ответ «в среднем ошибаемся на 12%» понятен без пояснений и одинаково читается для хлеба и автомобилей. Поэтому MAPE (mean absolute percentage error) — одна из самых популярных метрик в прогнозировании спроса, финансах и энергетике.
Где она встречается:
- прогноз спроса и продаж — розница, логистика, планирование закупок; часто это главный KPI отдела прогнозирования;
- финансы и экономика — точность прогнозов выручки, цен, макропоказателей;
- энергетика — прогноз нагрузки на сеть, где процент ошибки прямо пересчитывается в стоимость резерва;
- сравнение рядов разного масштаба — MAPE безразмерна, поэтому точность можно усреднять по тысячам товаров;
- соревнования по прогнозированию — в соревнованиях Макридакиса M3 одной из главных метрик был её «симметричный» вариант sMAPE, а в M4 методы ранжировали по sMAPE вместе с MASE.
MAPE — средняя абсолютная ошибка, измеренная в долях факта. Она не зависит от масштаба, но не определена при $y_i=0$ и взрывается возле нуля. Для положительного факта недопрогноз стоит не больше $100\%$, а перепрогноз — сколько угодно. MAPE — это MAE с весами $1/|y_i|$, поэтому лучшая по MAPE константа — взвешенная медиана, смещённая вниз, а модель, обученная на MAPE, занижает прогнозы.
Интуиция: ошибка в долях от факта
Промахнуться на 1 штуку, когда продано 3, — ошибиться на треть. Промахнуться на ту же штуку, когда продано 100, — почти точное попадание. MAPE измеряет каждую ошибку относительно своего факта и усредняет получившиеся проценты.
Потяните синие точки — прогнозы. Справа — процентная ошибка каждого объекта (APE, absolute percentage error) и их среднее — MAPE.
Абсолютная ошибка третьего объекта вчетверо больше, чем первого ($2$ против $0{,}5$), а процентная — лишь в $1{,}5$ раза ($25\%$ против $16{,}7\%$): большой факт «прощает» большие ошибки. MAPE равнодушна к масштабу и очень чувствительна к малым фактам.
Формула по косточкам
Разберём формулу изнутри наружу.
- $y_i$
- факт; должен быть ненулевым;
- $\hat y_i$
- прогноз модели;
- $|y_i-\hat y_i|$
- абсолютная ошибка, как в MAE;
- $\frac{|y_i-\hat y_i|}{|y_i|}$
- относительная ошибка APE — доля факта, на которую мы промахнулись; не зависит от единиц измерения;
- $\frac{100\%}{n}\sum_{i=1}^n$
- среднее по объектам, переведённое в проценты.
Сквозной пример по шагам:
| $i$ | $y_i$ | $\hat y_i$ | $|y_i-\hat y_i|$ | $\mathrm{APE}_i$ |
|---|---|---|---|---|
| 1 | 3 | 2,5 | 0,5 | 16,7% |
| 2 | 5 | 5 | 0 | 0% |
| 3 | 8 | 10 | 2 | 25,0% |
| среднее | 0,833 | 13,9% |
Две эквивалентные записи раскрывают устройство метрики:
Первая: MAPE — это взвешенная MAE с весами $w_i=1/|y_i|$; объекты с малым фактом получают огромный вес. Вторая: для положительных фактов APE зависит только от отношения $q_i=\hat y_i/y_i$, $\mathrm{APE}_i=|1-q_i|$. Поэтому MAPE не меняется, если умножить все факты и прогнозы на одно и то же число.
Библиотеки часто возвращают MAPE долей, без умножения на 100: sklearn.metrics.mean_absolute_percentage_error на сквозном примере даёт $0{,}139$, а не $13{,}9$. Проверяйте, что именно вы сравниваете.
Свойства и асимметрия
- Безразмерность: $\mathrm{MAPE}(c\,y,\,c\,\hat y)=\mathrm{MAPE}(y,\hat y)$ при любом $c\ne0$. Рубли или тысячи рублей — всё равно.
- Нет инвариантности к сдвигу: прибавьте 1000 к фактам и прогнозам — абсолютные ошибки те же, а MAPE упадёт в разы. Поэтому MAPE бессмысленна для температуры в °C и других шкал с условным нулём.
- Не определена при $y_i=0$ и неограниченно растёт при $y_i\to0$: прогноз 1 при факте $0{,}01$ — это ошибка $9900\%$.
- Нулевой прогноз стоит ровно $100\%$: при $\hat y_i=0$ каждая $\mathrm{APE}_i=1$. Модель «всегда ноль» имеет $\mathrm{MAPE}=100\%$ на любых ненулевых данных.
- Асимметрия: для положительного факта и неотрицательного прогноза недопрогноз даёт $\mathrm{APE}\le100\%$, а перепрогноз не ограничен.
- Выпуклость: MAPE — сумма модулей линейных функций прогнозов, поэтому она выпукла по прогнозам (и по параметрам линейной модели); равна нулю только при идеальном прогнозе.
В штуках симметрична, в разах — нет
Если считать промах в единицах, MAPE симметрична: прогнозы $y-d$ и $y+d$ стоят одинаково, $d/y$. Но в бизнесе промахи часто меряют в разах: «завысили в полтора раза», «занизили вдвое». Тут MAPE несимметрична: занизить вдвое ($\hat y=y/2$) стоит $50\%$, завысить вдвое ($\hat y=2y$) — $100\%$. Из двух прогнозов, ошибающихся в одно и то же число раз, MAPE всегда предпочтёт заниженный.
Почему sMAPE не такая уж симметричная
sMAPE делит ошибку на среднее факта и прогноза: $\mathrm{sAPE}=2|y-\hat y|/(|y|+|\hat y|)$. В разах она симметрична: при $\hat y=k\,y$ и при $\hat y=y/k$ (с $k>0$, $y>0$) получается одно и то же:
Но в штуках — нет: при $\hat y=y\pm d$ знаменатели $2y-d$ и $2y+d$ различаются, и недопрогноз штрафуется сильнее. Симметрию «в разах» и «в штуках» одновременно не даёт ни одна из этих метрик; строго симметрична в разах логарифмическая ошибка $|\ln(\hat y/y)|$.
Производная и лучшая константа
Для одного объекта APE — модуль линейной функции прогноза, поэтому её производная — ступенька:
Вывод и градиент по параметрам
При $\hat y_i>y_i$ имеем $\mathrm{APE}_i=(\hat y_i-y_i)/|y_i|$ — прямая с наклоном $1/|y_i|$; при $\hat y_i<y_i$ — прямая $(y_i-\hat y_i)/|y_i|$ с наклоном $-1/|y_i|$. В точке $\hat y_i=y_i$ производной нет (излом); субградиент — любое число из $[-1/|y_i|;\,1/|y_i|]$, библиотеки обычно берут 0. Для параметров модели по цепному правилу:
Модуль производной не зависит от размера ошибки — как у MAE, — но умножен на $1/|y_i|$: объект с фактом 1 тянет модель в 100 раз сильнее объекта с фактом 100. В сквозном примере $\partial\,\mathrm{MAPE}/\partial\hat y=\tfrac{100\%}{3}\,\bigl(-\tfrac13;\;0;\;\tfrac18\bigr)\approx(-11{,}1\%;\;0;\;4{,}2\%)$ на единицу прогноза: первый объект с вчетверо меньшей ошибкой тянет в $2{,}7$ раза сильнее третьего.
Лучшая константа — взвешенная медиана, смещённая вниз
Какой один прогноз $c$ для всех объектов минимизирует MAPE? Функция $\mathrm{MAPE}(c)=\frac{100\%}{n}\sum_i|y_i-c|/y_i$ кусочно-линейна и выпукла; между соседними точками данных её наклон равен $\frac{100\%}{n}\bigl(\sum_{y_i<c}\tfrac1{y_i}-\sum_{y_i>c}\tfrac1{y_i}\bigr)$. Минимум там, где наклон меняет знак, — где суммарный вес $1/y$ слева сравнивается с весом справа. Это взвешенная медиана с весами $1/y_i$:
Веса убывают с ростом $y$, поэтому взвешенная медиана не больше обычной: MAPE систематически тянет прогноз вниз. Для логнормального спроса это считается точно: если $\ln y\sim N(\mu,\sigma^2)$, то $c^*=e^{\mu-\sigma^2}$ — медиана $e^{\mu}$, умноженная на $e^{-\sigma^2}$.
Откуда множитель e^(−σ²)
Взвешенная медиана — медиана распределения с плотностью, пропорциональной $f(y)/y$. Для логнормальной плотности $f$, обозначив $t=\ln y$:
Это снова логнормальная плотность, но с параметром $\mu-\sigma^2$; её медиана $e^{\mu-\sigma^2}$. Для сравнения: среднее исходного распределения $e^{\mu+\sigma^2/2}$ выше медианы. При $\sigma=0{,}6$ оптимум MAPE на $1-e^{-0{,}36}\approx30\%$ ниже медианы.
Модель, обученная минимизировать MAPE, наследует это смещение: её прогнозы систематически ниже фактов. В рознице это означает пустые полки, а потерянные продажи не попадут ни в одну метрику: продано ровно столько, сколько было на складе.
Карта ошибки: APE над плоскостью (y, ŷ)
Посмотрим на ошибку одного объекта как на функцию двух переменных — факта $y$ и прогноза $\hat y$. Линии уровня APE — это лучи из начала координат: условие $|y-\hat y|/y=a$ равносильно $\hat y=(1\pm a)\,y$. Линии уровня абсолютной ошибки, наоборот, — параллельные прямые $\hat y=y\pm e$. Лучи сходятся в нуле, поэтому вблизи $y=0$ любая фиксированная абсолютная ошибка пересекает все уровни APE — отсюда и «взрыв».
Для $n$ объектов MAPE — среднее таких функций. В пространстве прогнозов $(\hat y_1,\dots,\hat y_n)$ её линии уровня — многогранники (ромбы в 2D) с центром в $y$ и полуосями, пропорциональными $y_i$: вдоль осей с малыми $y_i$ далеко не отойдёшь без большого штрафа.
Обучение на MAPE: веса 1/y и недопрогноз
Раз MAPE — это MAE с весами $1/|y_i|$, обучить модель на MAPE можно любым алгоритмом, который минимизирует MAE с весами объектов: передайте sample_weight=1/|y|. В LightGBM есть готовая цель objective="mape", в PyTorch потеря пишется в одну строку (см. раздел с кодом).
Обучим простейшую модель $\hat y=w\,x$ на 40 объектах, у которых $y=10\,x\cdot e^{0{,}35\,\varepsilon}$, $\varepsilon\sim N(0,1)$: истинный наклон равен 10, шум мультипликативный — его размер растёт вместе с $y$, как у реальных продаж.
Почему так: точки с малыми $y$ получают большой вес и тянут прямую вниз. В терминах отношений $q_i=y_i/x_i$ имеем $\mathrm{MAPE}(w)=\frac{100\%}{n}\sum_i|q_i-w|/q_i$, так что оптимум — взвешенная медиана $q_i$ с весами $1/q_i$. При логнормальном шуме это медиана, умноженная на $e^{-\sigma^2}=e^{-0{,}1225}\approx0{,}885$, то есть на большой выборке около $8{,}85$ вместо 10 (на 400 точках листинга scikit-learn ниже получается $8{,}85$). На 40 точках рисунка случайный разброс заметнее, и оптимум равен $9{,}10$.
1) Обучайте на MAE или MSE от $\ln y$, а MAPE используйте только для отчёта. 2) Если KPI — именно MAPE, а недопрогноз дорог (дефицит), корректируйте прогнозы множителем, подобранным на валидации, или выберите метрику, отражающую реальные издержки (WAPE, квантильная потеря). 3) Не обучайте на MAPE, если в данных есть нули или почти нули.
MAPE, sMAPE, WAPE и MASE
Из-за перечисленных проблем у MAPE есть несколько популярных родственников ($e_i=y_i-\hat y_i$):
| Метрика | Формула | Нули в $y$ | Особенность |
|---|---|---|---|
| MAPE | $\frac{100\%}{n}\sum\frac{|e_i|}{|y_i|}$ | не определена | доля факта; асимметрична в разах; взрывается возле нуля |
| sMAPE | $\frac{100\%}{n}\sum\frac{2|e_i|}{|y_i|+|\hat y_i|}$ | допустимы, если $\hat y_i\ne0$ (тогда $\mathrm{sAPE}_i=200\%$) | ограничена $200\%$; в штуках строже к недопрогнозу |
| WAPE | $100\%\cdot\frac{\sum|e_i|}{\sum|y_i|}$ | допустимы (нужна ненулевая сумма) | MAE, делённая на средний факт; крупные объекты весят больше |
| MASE | $\frac{\frac1n\sum|e_i|}{\frac{1}{T-1}\sum_t|y_t-y_{t-1}|}$ | допустимы (ряд не постоянен) | MAE относительно наивного прогноза «как в прошлый период»; $<1$ — лучше наивного |
В сквозном примере $\mathrm{MAPE}\approx13{,}9\%$, $\mathrm{sMAPE}\approx13{,}5\%$, $\mathrm{WAPE}=2{,}5/16\approx15{,}6\%$, а MASE с масштабом $\tfrac12\bigl(|5-3|+|8-5|\bigr)=2{,}5$ равна $0{,}833/2{,}5\approx0{,}33$ (для простоты масштаб посчитан по тем же трём точкам).
WAPE (её ещё называют MAD/Mean ratio) — это MAE, делённая на средний факт: объекты с большими продажами весят больше, и общий итог не ломается от одного товара с почти нулевым спросом. MASE (Хайндман и Кёлер, 2006) сравнивает MAE модели с MAE наивного прогноза «как в прошлый период», посчитанной на обучающей части ряда (для сезонных рядов — сезонного наивного прогноза), и годится даже для рядов с нулями. У sMAPE вариантов несколько: здесь используется $2|e_i|/(|y_i|+|\hat y_i|)$ с пределом $200\%$, как в M4; в M3 знаменатель брали без модулей, $y_i+\hat y_i$, а встречается и версия без двойки с пределом $100\%$ — прежде чем сравнивать числа, уточните формулу. На одних и тех же данных WAPE и MASE отличаются лишь постоянным множителем, поэтому у них один и тот же оптимум.
Бизнес-пример: ассортимент магазина
Сеть прогнозирует недельные продажи шести товаров. Пять из них продаются десятками и сотнями штук и прогнозируются с ошибкой от $7{,}5\%$ до $16{,}7\%$. Шестой, F, — редкий товар: прогноз 10 штук, а продано 4.
Что делать на практике:
- отчитываться WAPE (или MAPE, взвешенной по выручке), если важна общая точность в штуках или деньгах;
- считать MAPE по группам — быстрые и медленные товары отдельно — или исключать позиции с продажами ниже порога, явно указав порог;
- для медленных товаров использовать MASE или специальные метрики для прерывистого спроса;
- отдельно следить за знаком ошибки: смещение суммы прогнозов (bias) — самостоятельный KPI, MAPE его не показывает.
MAPE понятна без статистического образования, поэтому давно стала стандартом отраслевых отчётов. Критика тоже давняя: на смещение в пользу заниженных прогнозов и проблему малых фактов указывали ещё в 1980–1990-х (например, Армстронг и Коллопи, 1992), а Хайндман и Кёлер (2006) предложили MASE как масштабно-независимую альтернативу без этих недостатков.
В коде
В NumPy MAPE — одна строка; ниже заодно sMAPE, WAPE и проверка формул на сквозном примере.
pythonimport numpy as np
y = np.array([3.0, 5.0, 8.0])
y_hat = np.array([2.5, 5.0, 10.0])
ape = np.abs((y - y_hat) / y) # [0.16666667 0. 0.25 ]
mape = 100 * ape.mean() # 13.888888888888888
# То же как взвешенная MAE с весами 1/|y|
w = 1 / np.abs(y)
print(100 * np.mean(w * np.abs(y - y_hat))) # 13.888888888888888
def smape(y, f):
return 100 * np.mean(2 * np.abs(f - y) / (np.abs(y) + np.abs(f)))
def wape(y, f):
return 100 * np.sum(np.abs(y - f)) / np.sum(np.abs(y))
print(smape(y, y_hat), wape(y, y_hat)) # 13.468013468013467 15.625
scikit-learn возвращает долю, а знаменатели меньше машинного эпсилона ($\approx2{,}2\cdot10^{-16}$) заменяет на эпсилон — поэтому вместо ошибки деления на ноль получается огромное число. Для обучения «на MAPE» подходит медианная регрессия с весами $1/y$:
pythonimport numpy as np
from sklearn.metrics import mean_absolute_percentage_error
from sklearn.linear_model import LinearRegression, QuantileRegressor
# y, y_hat — из листинга выше
print(mean_absolute_percentage_error(y, y_hat)) # 0.13888888888888887 — доля, а не проценты!
print(mean_absolute_percentage_error([0.0, 5.0], [1.0, 5.0])) # 2251799813685248.0: деление на eps вместо нуля
# Обучение «на MAPE»: медианная регрессия (MAE) с весами 1/y
rng = np.random.default_rng(0)
x = rng.uniform(1, 10, 400)
t = 10 * x * np.exp(0.35 * rng.standard_normal(400))
X = x[:, None]
ols = LinearRegression(fit_intercept=False).fit(X, t)
fit = QuantileRegressor(quantile=0.5, alpha=0, fit_intercept=False).fit(X, t, sample_weight=1 / t)
print(ols.coef_, fit.coef_) # [10.57549043] [8.85148171] — модель по MAPE занижает сумму на 16%
В PyTorch MAPE как функция потерь:
pythonimport torch
def mape_loss(pred, target, eps=1e-8):
"""MAPE как функция потерь (доля). eps спасает от деления на 0, но не от огромных весов возле нуля."""
return torch.mean(torch.abs(target - pred) / target.abs().clamp_min(eps))
y = torch.tensor([3.0, 5.0, 8.0])
y_hat = torch.tensor([2.5, 5.0, 10.0], requires_grad=True)
loss = mape_loss(y_hat, y)
loss.backward()
print(loss.item(), y_hat.grad) # 0.1388888955116272 tensor([-0.1111, -0.0000, 0.0417])
Перед тем как считать MAPE, посмотрите на минимум $|y|$ в данных. Если там нули или значения, несопоставимо малые по сравнению с типичными, — отчитывайтесь WAPE или MASE и не используйте MAPE как функцию потерь.
Частые ошибки
- MAPE на данных с нулями. Деление на ноль даёт бесконечность или NaN, а «защита» через $\varepsilon$ — астрономические числа: scikit-learn вернёт $2{,}25\cdot10^{15}$. Фильтруйте нули явно и сообщайте об этом или берите WAPE и MASE.
- MAPE для шкал с условным нулём — температуры в °C, индексов, дат. Ошибка в 1° при 2° и при 30° одна и та же, а MAPE различается в 15 раз.
- Обучение на MAPE без учёта смещения. Модель систематически занижает прогноз, и в рознице это превращается в дефицит на полках.
- Сравнение MAPE между наборами с разной долей малых значений. Одна и та же модель покажет 12% на быстрых товарах и 60% на медленных — дело в данных, а не в качестве.
- Путаница долей и процентов: scikit-learn возвращает $0{,}139$, а не $13{,}9$.
- «MAPE меньше — значит, план точнее». MAPE не видит знака ошибок: прогноз с меньшей MAPE может в сумме занижать спрос на 16%, как на рисунке 5.
Связи с другими формулами
- MAE: MAPE — это MAE с весами $1/|y_i|$; модуль градиента тоже не зависит от размера ошибки, но масштабирован на $1/|y_i|$.
- MSE и RMSE: абсолютные квадратичные ошибки; их относительный родственник — RMSLE, RMSE в логарифмической шкале.
- Huber: сглаживает излом в нуле; ту же идею можно применить к относительной ошибке.
- SGD: обучение на MAPE — субградиентный спуск, шаг которого нужно уменьшать (на рисунке 5 — как $1/\sqrt t$).
Итоги
1) $\mathrm{MAPE}=\frac{100\%}{n}\sum|y_i-\hat y_i|/|y_i|$ — средняя ошибка в процентах от факта; не зависит от масштаба и понятна бизнесу. 2) Не определена при $y=0$ и взрывается возле нуля; нулевой прогноз стоит ровно $100\%$. 3) Асимметрична в разах: занизить вдвое — $50\%$, завысить вдвое — $100\%$. 4) MAPE — MAE с весами $1/|y|$: производная $\operatorname{sign}(\hat y-y)/|y|$, лучшая константа — взвешенная медиана ниже обычной, обучение на MAPE даёт недопрогноз. 5) Для отчётов по ассортименту обычно надёжнее WAPE и MASE.