Measuring Utility Loss in Differentially Private Heatmaps

Quantify heatmap degradation with a small suite of complementary metrics — MAE and RMSE for cell-count magnitude, Spearman rank correlation and top-kk overlap for hotspot structure, KL divergence for distribution shape, and Moran’s I preservation for spatial autocorrelation — each checked against an explicit threshold.

Core Calculation permalink

A differentially private heatmap replaces each true cell count tit_i with a noisy count nin_i. Utility loss is not one number: magnitude error, rank structure, and spatial structure fail independently, so measure all three.

Magnitude error. Root mean squared error penalises large per-cell deviations:

RMSE=1mi=1m(niti)2,MAE=1mi=1mniti\text{RMSE} = \sqrt{\frac{1}{m}\sum_{i=1}^{m}(n_i - t_i)^2}, \qquad \text{MAE} = \frac{1}{m}\sum_{i=1}^{m}\lvert n_i - t_i\rvert

For the Gaussian mechanism with per-cell standard deviation σ\sigma, the expected RMSE is exactly σ\sigma, giving a theoretical baseline to compare against.

Rank / hotspot structure. Spearman’s rank correlation ρs\rho_s is Pearson correlation on the rank-transformed counts:

ρs=16idi2m(m21)\rho_s = 1 - \frac{6 \sum_i d_i^2}{m(m^2 - 1)}

where did_i is the difference in rank of cell ii between the true and noisy grids. The top-kk overlap is the Jaccard-style fraction of shared cells among the kk highest-count cells:

overlapk=TkNkk\text{overlap}_k = \frac{\lvert T_k \cap N_k \rvert}{k}

with Tk,NkT_k, N_k the top-kk cell sets of the true and noisy grids.

Distributional divergence. Normalise each grid to a probability distribution pi=ti/tp_i = t_i / \sum t, qi=ni/nq_i = n_i / \sum n, and compute the Kullback–Leibler divergence:

DKL(pq)=ipilogpiqiD_{\mathrm{KL}}(p \parallel q) = \sum_{i} p_i \log \frac{p_i}{q_i}

Spatial autocorrelation. Track global Moran’s I before and after masking; the dedicated method is covered in computing Moran’s I on masked spatial data.

Metric Measures Target threshold
RMSE / MAE Per-cell magnitude error RMSE σ\approx \sigma; MAE small vs. mean count
Spearman ρs\rho_s Rank preservation 0.9\ge 0.9 good, 0.8\ge 0.8 acceptable
Top-kk overlap Hotspot survival 0.8\ge 0.8 for k=1020k = 10\text{–}20
DKLD_{\mathrm{KL}} Distribution shape 0.05\le 0.05 nats good
Moran’s I ratio Spatial structure within ±10%\pm 10\% of true

Worked numeric example permalink

A 3-cell toy grid, true counts t=(100,40,10)t = (100, 40, 10), noisy counts n=(108,35,18)n = (108, 35, 18):

MAE=13(8+5+8)=7.0,RMSE=13(64+25+64)=517.14\text{MAE} = \tfrac{1}{3}(8 + 5 + 8) = 7.0, \qquad \text{RMSE} = \sqrt{\tfrac{1}{3}(64 + 25 + 64)} = \sqrt{51} \approx 7.14

Ranks are unchanged (both order cell 1 > cell 2 > cell 3), so di2=0\sum d_i^2 = 0 and ρs=1.0\rho_s = 1.0. The top-1 hotspot (cell 1) survives, so overlap1=1.0\text{overlap}_1 = 1.0. Normalising: p=(0.667,0.267,0.067)p = (0.667, 0.267, 0.067), q=(0.671,0.217,0.112)q = (0.671, 0.217, 0.112), giving DKL(pq)0.667ln0.6670.671+0.267ln0.2670.217+0.067ln0.0670.1120.015D_{\mathrm{KL}}(p \parallel q) \approx 0.667\ln\frac{0.667}{0.671} + 0.267\ln\frac{0.267}{0.217} + 0.067\ln\frac{0.067}{0.112} \approx 0.015 nats — a low, healthy divergence. Magnitude moved but structure held: exactly the distinction the suite exists to expose.

Three families of heatmap utility metrics Utility loss is measured along three independent axes: magnitude error via MAE and RMSE, rank structure via Spearman correlation and top-k overlap, and spatial structure via KL divergence and Moran's I. Each can fail while the others pass. True grid vs. private grid: three independent failure modes Magnitude MAE RMSE "how far off is each cell?" Rank structure Spearman rho top-k overlap "do the hotspots survive?" Spatial structure KL divergence Moran's I "is clustering preserved?" Report one metric from each column — they fail independently
A complete utility report samples all three families; a heatmap can pass magnitude checks yet fail hotspot and spatial-structure checks.

Python Implementation permalink

The suite below takes aligned true and noisy grids (same cell ordering, same CRS — here EPSG:3857 web-Mercator tiles) and returns every metric plus a pass/fail verdict against thresholds.

import numpy as np
from numpy.typing import NDArray
from scipy.stats import spearmanr, entropy


def heatmap_utility_metrics(
    true_grid: NDArray[np.float64],
    noisy_grid: NDArray[np.float64],
    top_k: int = 10,
    eps_smoothing: float = 1e-9,
) -> dict:
    """
    Quantify utility loss between a true and a differentially private heatmap.

    Both grids must share the same cell ordering and coordinate reference
    system (e.g. EPSG:3857 tiles). Privacy note: only the noisy_grid is ever
    released; true_grid is used internally for offline utility evaluation and
    must not be published, since it would reveal the raw counts the DP
    mechanism was meant to protect.

    Args:
        true_grid: Flattened true cell counts, non-negative.
        noisy_grid: Flattened DP cell counts (may be clamped at 0).
        top_k: Number of highest cells to compare for hotspot overlap.
        eps_smoothing: Additive smoothing so KL divergence stays finite
            when a cell is zero in one grid.

    Returns:
        Dict of metric name -> value.
    """
    t = np.asarray(true_grid, dtype=float).ravel()
    n = np.asarray(noisy_grid, dtype=float).ravel()
    if t.shape != n.shape:
        raise ValueError("Grids must have identical shape and cell ordering.")

    # --- Magnitude error ---
    diff = n - t
    mae = np.mean(np.abs(diff))
    rmse = np.sqrt(np.mean(diff ** 2))

    # --- Rank / hotspot structure ---
    rho_s, _ = spearmanr(t, n)  # rank correlation across all cells
    true_top = set(np.argsort(t)[::-1][:top_k])
    noisy_top = set(np.argsort(n)[::-1][:top_k])
    top_k_overlap = len(true_top & noisy_top) / top_k

    # --- Distributional divergence (normalise to probability vectors) ---
    p = t + eps_smoothing
    q = n + eps_smoothing
    p /= p.sum()
    q /= q.sum()
    kl = float(entropy(p, q))  # KL(p || q) in nats

    return {
        "mae": round(float(mae), 3),
        "rmse": round(float(rmse), 3),
        "spearman_rho": round(float(rho_s), 4),
        "top_k_overlap": round(float(top_k_overlap), 3),
        "kl_divergence": round(kl, 5),
    }


# --- Example: 40x40 grid, Gaussian DP noise sigma = 21.2 (epsilon = 0.5) ---
rng = np.random.default_rng(0)
true_grid = rng.poisson(lam=60, size=1600).astype(float)
noisy_grid = np.maximum(true_grid + rng.normal(0, 21.2, size=1600), 0.0)
print(heatmap_utility_metrics(true_grid, noisy_grid, top_k=10))

Key decisions: the true grid is evaluation-only and must never be released; KL divergence uses additive smoothing so zero cells do not produce infinities; and spearmanr operates on ranks so it is insensitive to the absolute noise scale — isolating structural loss from magnitude loss.

Verification checklist permalink

Confirm the private heatmap meets utility targets before publishing:

def passes_utility_gate(metrics: dict, mean_true_count: float) -> dict:
    """Check each metric against its threshold; return per-check booleans."""
    checks = {
        "rmse_reasonable": metrics["rmse"] <= 0.5 * mean_true_count,
        "rank_preserved": metrics["spearman_rho"] >= 0.8,
        "hotspots_survive": metrics["top_k_overlap"] >= 0.8,
        "distribution_close": metrics["kl_divergence"] <= 0.05,
    }
    checks["all_passed"] = all(checks.values())
    return checks
  • RMSE close to the theoretical σ\sigma
  • Spearman ρs0.8\rho_s \ge 0.8
  • Top-kk overlap 0.8\ge 0.8
  • KL divergence 0.05\le 0.05
  • Moran’s I within ±10%\pm 10\%

If any check fails, raise the privacy budget (ε) or coarsen the grid so counts are larger relative to the noise.

Edge Cases & Adjustments permalink

  • Sparse grids dominated by zeros. When most cells are empty, RMSE looks tiny yet the hotspot overlap can still collapse. Weight your judgment toward top-kk overlap and Spearman correlation, or restrict metrics to cells above a minimum true count.
  • Clamping bias. Clamping negative noisy counts to zero inflates sparse-cell totals, biasing KL divergence and the grid sum. Normalise consistently and report the clamped fraction alongside the metrics.
  • Grid resolution mismatch. Utility depends heavily on cell size; a map that fails at fine resolution often passes when aggregated coarser. Evaluate at the resolution you will actually publish, and re-derive the accuracy vs. utility tradeoff at each candidate resolution.
  • Rank ties in flat regions. Large uniform low-count areas create many tied ranks, destabilising Spearman correlation. Break ties deterministically or exclude the flat background before computing rank metrics.

FAQ permalink

Which single metric best captures heatmap utility loss?

None — magnitude error and structural error are distinct failure modes. RMSE measures how far each cell moved but says nothing about whether hotspots are still ranked correctly; Spearman correlation and top-kk overlap measure hotspot survival but ignore absolute scale; KL divergence and Moran’s I capture distribution and clustering. Always report at least one metric from each family.

What is a reasonable top-k overlap threshold for a hotspot map?

For operational use, target top-kk overlap 0.8\ge 0.8 for kk around 10–20 — at least 8 of the top 10 hotspots preserved. Below roughly 0.6 the map can no longer be trusted to show where activity concentrates, and you should increase ε\varepsilon or coarsen the grid.

Why measure Moran’s I on a private heatmap?

Moran’s I measures spatial autocorrelation — whether neighbouring cells hold similar values. Independent per-cell noise attacks exactly that structure, so a sharp drop in Moran’s I reveals lost clustering even when per-cell error looks fine. Keeping it within about 10% of the true value confirms the spatial pattern survived; see computing Moran’s I on masked spatial data for the procedure.

How does epsilon affect these metrics?

Lower ε\varepsilon means larger noise: MAE and RMSE rise, Spearman correlation and top-kk overlap fall, and KL divergence grows. Running the suite across candidate ε\varepsilon values turns the privacy-utility tradeoff into a measurable search for the smallest budget that still clears every threshold.


Related

Back to Accuracy vs. Utility Tradeoffs in Geospatial DP