The naive attack thresholds the loss and achieves respectable average accuracy while being useless — it flags easy examples. LiRA calibrates per example by fitting Gaussians to the model-confidence statistic under shadow models trained with and without that example, then runs a likelihood-ratio test.
Report TPR at low FPR, not accuracy or AUC. An attack that identifies 0.1% of the training set with near-certainty is a serious privacy failure and can sit at 51% average accuracy; the aggregate numbers hide exactly the regime that matters.
import numpy as np
from scipy.stats import norm
def logit_confidence(p_correct: np.ndarray) -> np.ndarray:
"""Map confidence to an approximately normal statistic."""
p = np.clip(p_correct, 1e-6, 1 - 1e-6)
return np.log(p) - np.log1p(-p)
def lira_score(phi_target: float,
phi_in: np.ndarray, phi_out: np.ndarray) -> float:
"""phi_in / phi_out: statistic from shadow models trained
with and without the target example."""
mu_in, sd_in = phi_in.mean(), phi_in.std() + 1e-8
mu_out, sd_out = phi_out.mean(), phi_out.std() + 1e-8
return (norm.logpdf(phi_target, mu_in, sd_in)
- norm.logpdf(phi_target, mu_out, sd_out))The logit transform is what makes the Gaussian assumption tenable; fitting normals directly to bounded confidences puts most of the mass against the boundary and the ratio becomes meaningless. Shadow models must match the target’s architecture and training recipe — a mismatched shadow calibrates against the wrong distribution and reads as a weaker attack than the data supports.