MAPE Near Zero: Inspect actual values, Check relative scale, Report zero handling

Why scikit-learn MAPE Explodes When Actual Values Are Zero

Understand why scikit-learn MAPE can become enormous at zero targets, verify the calculation and choose an evaluation rule without hiding difficult rows.

If scikit-learn reports a huge mean absolute percentage error even though prediction differences look small, inspect the actual target values. A zero or near-zero actual value makes a relative-error denominator extremely small. This is not necessarily a broken estimator or a printing problem: the metric may be poorly matched to the task.

This tutorial isolates that calculation with synthetic values. It does not train a model, change a dataset or establish which metric is appropriate for a production decision.

Read the output as a relative error, not an already formatted percent

The official mean_absolute_percentage_error documentation explains that scikit-learn returns a relative value. A result of 0.25 corresponds to 25%, and 2.0 corresponds to 200%. Results are non-negative but are not capped at one.

For a nonzero actual value, the individual contribution is the absolute prediction difference divided by the absolute actual value. The mean combines these contributions. Consequently, the same absolute miss can have a very different effect depending on the target’s magnitude. Do not interpret MAPE as the fraction of predictions that were incorrect.

Run a small denominator experiment

Run the following in a disposable Python environment with NumPy and scikit-learn installed. The fixtures deliberately use float64 values, avoiding ambiguity about floating-point precision in this demonstration. No files are read or written.

import numpy as np
from sklearn.metrics import mean_absolute_percentage_error

y_true = np.array([100.0, 1.0], dtype=np.float64)
y_pred = np.array([90.0, 0.9], dtype=np.float64)
score = mean_absolute_percentage_error(y_true, y_pred)
assert np.isclose(score, 0.1)
print(f"Ordinary MAPE: {score:.3f} ({score * 100:.1f}%)")

small_actual = np.array([0.001], dtype=np.float64)
small_prediction = np.array([0.101], dtype=np.float64)
small_score = mean_absolute_percentage_error(small_actual, small_prediction)
assert np.isclose(small_score, 100.0)
print(f"Near-zero MAPE: {small_score:.1f}")

zero_actual = np.array([0.0], dtype=np.float64)
zero_prediction = np.array([0.1], dtype=np.float64)
zero_score = mean_absolute_percentage_error(zero_actual, zero_prediction)
assert np.isfinite(zero_score) and zero_score > 1e12
print(f"Zero-target MAPE: {zero_score:.3e}")

perfect_zero = mean_absolute_percentage_error([0.0], [0.0])
assert perfect_zero == 0.0
print(f"Perfect zero prediction: {perfect_zero:.1f}")

The first pair has a 10% relative miss on both rows. The second fixture has an absolute difference of only 0.1, yet its relative error is 100, meaning 10,000%. The zero-target fixture returns a very large finite number rather than infinity. The documentation attributes that behaviour to division by epsilon. A correctly predicted zero still contributes zero; a zero target does not automatically imply a large error.

Inspect the rows before changing the metric

Count zero targets and inspect the distribution of small magnitudes. Then check whether zero means a genuine absence, a rounded measurement, a missing-value placeholder or a data-processing mistake. These are different problems and should not receive an automatic shared fix.

If zero is a legitimate outcome, deleting those rows can hide operational failures. A demand forecast that predicts sales when none occurred still deserves evaluation. If zero is a missing-data marker, correct the data interpretation through a documented preprocessing rule instead of quietly dropping inconvenient results after evaluation.

Do not add an arbitrary constant merely to produce a pleasant score. Changing the denominator changes the question and can make scores incomparable across reports. Any domain-specific floor needs a stated unit, rationale and consistent evaluation protocol.

Choose and document an evaluation rule

Consider reporting an absolute-error metric alongside MAPE. Mean absolute error expresses the average miss in the target’s original units, so readers can interpret the practical size without dividing by each actual value. It does not solve every evaluation problem, and comparing targets with different units still needs care.

If stakeholders specifically require percentage reporting, agree in advance how zero and near-zero targets will be handled. Report any excluded population and its separate errors. Keep the rule fixed across baseline and candidate models; do not choose it after seeing which version makes a preferred model win.

For multi-output predictions, also inspect the aggregation setting. The documented raw_values option reports an error for each output, while uniform_average combines outputs. A combined number can hide which output contains the problematic denominators.

Quick FAQ and reporting checklist

Is MAPE above one invalid? No. Relative errors can exceed 100%, particularly near zero.

Should I clip the score to one? No. That would discard information and misrepresent this metric.

Does this diagnose classification performance? No. For a separate classification evaluation task, see checking classifier accuracy against a DummyClassifier baseline.

  • State whether numbers are relative values or percentages.
  • Record zero and near-zero handling before model comparison.
  • Keep a unit-based error measure and an appropriate baseline.
  • Preserve the evaluation population and aggregation settings.

Educational use only. Test examples and evaluation changes before production use. The site owner is not responsible for misuse, damage, data loss or production issues.

Leave a Reply

Your email address will not be published. Required fields are marked *