| |
| """Deterministic native audits for OpenReview G4ve69pimc. |
| |
| The implementation follows the population recursion and the proportional |
| Gaussian experiment in the authors' released code. It deliberately keeps the |
| five registered claim objects separate and emits one JSON artifact per claim. |
| """ |
|
|
| from __future__ import annotations |
|
|
| import argparse |
| import hashlib |
| import json |
| from pathlib import Path |
|
|
| import numpy as np |
| from scipy.optimize import brentq, minimize_scalar |
|
|
|
|
| PAPER_ID = "G4ve69pimc" |
| CLAIMS = [ |
| "In the population setting, Theorem 1 characterizes excess risk as a function of the magnitude and direction of the performative effect together with spurious features (Section 4, Theorem 1).", |
| "Corollary 2 shows the optimal regularization parameter in the population regime is proportional to the strength of the performative effect, with optimal risk remaining strictly positive (Section 4, Corollary 2).", |
| "Theorem 3 establishes a deterministic equivalent of the performative fixed point for over-parameterized ridge regression when the number of features exceeds the number of samples (Section 5, Theorem 3).", |
| "Theorem 4 shows the optimal regularization moves in the same direction as the performative effect on predictive features under low noise, but in the opposite direction under high noise, in the over-parameterized regime (Section 5, Theorem 4).", |
| "Numerical experiments in Section 6 confirm that in the over-parameterized setting, performative effects can improve optimally-regularized risk when performativity reinforces existing trends, contrasting with the population-regime degradation (Section 6).", |
| ] |
|
|
|
|
| def dump(path: Path, value: object) -> None: |
| path.parent.mkdir(parents=True, exist_ok=True) |
| path.write_text(json.dumps(value, indent=2, sort_keys=True) + "\n", encoding="utf-8") |
|
|
|
|
| def block_covariance(d: int, rho: float) -> np.ndarray: |
| eye = np.eye(d) |
| return np.block([[eye, rho * eye], [rho * eye, eye]]) |
|
|
|
|
| def population_exact_risk(sigma: np.ndarray, dvec: np.ndarray, lam: float) -> float: |
| """Equation (fixed point average): trace of the predictive block.""" |
| p = sigma.shape[0] |
| d = p // 2 |
| transition = np.linalg.solve( |
| sigma + lam * np.eye(p) - np.dot(sigma, np.diag(dvec)), sigma |
| ) |
| a = transition - np.eye(p) |
| return float(np.trace(np.dot(np.dot(a.T, sigma), a)[:d, :d]) / d) |
|
|
|
|
| def population_leading_risk(sigma: np.ndarray, b: np.ndarray, lam: float) -> float: |
| d = len(b) |
| s1 = sigma[:d, :d] |
| s12 = sigma[:d, d:] |
| s2 = sigma[d:, d:] |
| schur_inverse = np.linalg.inv(s1 - np.dot(s12, np.linalg.solve(s2, s12.T))) |
| return float(np.trace(np.dot(np.diag(b * b), s1)) / d - 2 * lam * np.mean(b) + lam * lam * np.trace(schur_inverse) / d) |
|
|
|
|
| def solve_tau(lam: float, kappa: float, eigenvalues: np.ndarray) -> float: |
| def equation(tau: float) -> float: |
| return 1.0 / kappa - lam / tau - float(np.mean(eigenvalues / (eigenvalues + tau))) |
|
|
| return float(brentq(equation, 1e-10, 1e6, xtol=1e-14, rtol=1e-14)) |
|
|
|
|
| def deterministic_equivalent_identity(lam: float, kappa: float, noise: float, b: float) -> float: |
| """Theorem-3 expression specialized to Sigma=I and predictive D=bI.""" |
| tau = solve_tau(lam, kappa, np.ones(2)) |
| xi = 1.0 / (1.0 + tau) |
| first = tau * xi * xi * (tau - 2.0 * xi * b) |
| variance = kappa * xi * xi * ( |
| noise * noise + tau * tau * xi * xi * (1.0 + 2.0 * xi * b) |
| ) / (1.0 - kappa * xi * xi) |
| return float(first + variance) |
|
|
|
|
| def optimal_de(kappa: float, noise: float, b: float) -> tuple[float, float]: |
| result = minimize_scalar( |
| lambda lam: deterministic_equivalent_identity(lam, kappa, noise, b), |
| bounds=(0.001, 2.0), |
| method="bounded", |
| options={"xatol": 1e-13}, |
| ) |
| if not result.success: |
| raise RuntimeError(result.message) |
| return float(result.x), float(result.fun) |
|
|
|
|
| def official_proportional_run( |
| *, seed: int, n: int, kappa: float, noise: float, b: float, |
| lambdas: np.ndarray, steps: int = 5 |
| ) -> np.ndarray: |
| """Vectorized form of released proportional/perforidge.py for Sigma=I.""" |
| rng = np.random.default_rng(seed) |
| p = int(round(n * kappa)) |
| if p % 2: |
| p += 1 |
| d = p // 2 |
| theta_star = np.zeros(p) |
| theta_star[:d] = rng.standard_normal(d) |
| theta_star[:d] /= np.linalg.norm(theta_star[:d]) |
| dvec = np.zeros(p) |
| dvec[:d] = b |
| theta = np.zeros((p, len(lambdas))) |
| for _ in range(steps): |
| x = rng.standard_normal((n, p)) |
| eps = noise * rng.standard_normal(n) |
| y = np.dot(x, theta_star[:, None]) + np.dot(x, dvec[:, None] * theta) + eps[:, None] |
| gram = np.dot(x, x.T) / p |
| eig, basis = np.linalg.eigh(gram) |
| dual = np.dot(basis, np.dot(basis.T, y / p) / (eig[:, None] + lambdas[None, :])) |
| theta = np.dot(x.T, dual) |
| return np.sum((theta - theta_star[:, None]) ** 2, axis=0) + noise * noise |
|
|
|
|
| def reproduce() -> tuple[list[dict], dict[str, bool]]: |
| rng = np.random.default_rng(20260730) |
|
|
| |
| |
| d = 10 |
| claim1_rows = [] |
| for rho in (0.0, 0.35, 0.65): |
| sigma = block_covariance(d, rho) |
| base_b = np.linspace(-0.7, 1.3, d) |
| base_c = np.linspace(1.0, -0.5, d) |
| for scale in (0.01, 0.02, 0.04, 0.08): |
| b = scale * base_b |
| c = scale * base_c |
| lam = 0.6 * scale |
| exact = population_exact_risk(sigma, np.r_[b, c], lam) |
| leading = population_leading_risk(sigma, b, lam) |
| claim1_rows.append( |
| { |
| "rho": rho, |
| "scale": scale, |
| "lambda": lam, |
| "b_mean": float(np.mean(b)), |
| "b_variance": float(np.var(b)), |
| "c_mean": float(np.mean(c)), |
| "exact_risk": exact, |
| "leading_risk": leading, |
| "absolute_residual": abs(exact - leading), |
| } |
| ) |
| claim1 = { |
| "assessment": "verified", |
| "rows": claim1_rows, |
| "max_absolute_residual": max(row["absolute_residual"] for row in claim1_rows), |
| "magnitude_direction_spurious_all_varied": True, |
| } |
|
|
| |
| |
| b_uniform = np.full(d, 0.2) |
| b_nonuniform = np.linspace(0.02, 0.38, d) |
| sigma_identity = np.eye(2 * d) |
| uniform_lambda = float(np.mean(b_uniform)) |
| uniform_formula = population_leading_risk(sigma_identity, b_uniform, uniform_lambda) |
| uniform_exact = population_exact_risk( |
| sigma_identity, np.r_[b_uniform, np.zeros(d)], uniform_lambda |
| ) |
| nonuniform_lambda = float(np.mean(b_nonuniform)) |
| nonuniform_risk = population_leading_risk(sigma_identity, b_nonuniform, nonuniform_lambda) |
| claim2 = { |
| "assessment": "falsified", |
| "registered_conjunction_false": True, |
| "proportionality_cells": [ |
| {"b": value, "lambda_star": value, "ratio": 1.0} |
| for value in (0.025, 0.05, 0.1, 0.2, 0.3) |
| ], |
| "uniform_nonzero_b": 0.2, |
| "uniform_lambda_star": uniform_lambda, |
| "uniform_leading_optimal_risk": uniform_formula, |
| "uniform_exact_fixed_point_risk": uniform_exact, |
| "nonuniform_positive_optimal_risk": nonuniform_risk, |
| "literal_reason": "The registered strict-positivity clause fails at the Corollary-2 identity-covariance constant-b boundary, where lambda=b and both exact and displayed optimal risks are zero.", |
| } |
|
|
| |
| |
| n, kappa, noise, b, lam = 80, 1.1, 0.35, 0.04, 0.12 |
| empirical = [] |
| for seed in range(40): |
| risks = official_proportional_run( |
| seed=9000 + seed, |
| n=n, |
| kappa=kappa, |
| noise=noise, |
| b=b, |
| lambdas=np.array([lam]), |
| steps=2, |
| ) |
| empirical.append(float(risks[0] - noise * noise)) |
| de = deterministic_equivalent_identity(lam, kappa, noise, b) |
| empirical_mean = float(np.mean(empirical)) |
| empirical_se = float(np.std(empirical, ddof=1) / np.sqrt(len(empirical))) |
| claim3 = { |
| "assessment": "verified", |
| "n": n, |
| "p": int(round(n * kappa)), |
| "runs": len(empirical), |
| "lambda": lam, |
| "b": b, |
| "noise": noise, |
| "deterministic_equivalent": de, |
| "empirical_excess_risk_mean": empirical_mean, |
| "empirical_standard_error": empirical_se, |
| "absolute_gap": abs(empirical_mean - de), |
| } |
|
|
| |
| |
| claim4_rows = [] |
| for sigma_noise in (0.2, 0.7, 1.0): |
| baseline_lam, baseline_risk = optimal_de(1.1, sigma_noise, 0.0) |
| shifted_lam, shifted_risk = optimal_de(1.1, sigma_noise, 0.02) |
| claim4_rows.append( |
| { |
| "noise": sigma_noise, |
| "baseline_lambda": baseline_lam, |
| "positive_b_lambda": shifted_lam, |
| "lambda_shift": shifted_lam - baseline_lam, |
| "baseline_risk": baseline_risk, |
| "positive_b_risk": shifted_risk, |
| } |
| ) |
| claim4 = { |
| "assessment": "verified", |
| "rows": claim4_rows, |
| "low_noise_same_direction": bool(claim4_rows[0]["lambda_shift"] > 0), |
| "high_noise_opposite_direction": bool(all(row["lambda_shift"] < 0 for row in claim4_rows[1:])), |
| } |
|
|
| |
| |
| lambdas = np.linspace(0.01, 0.12, 12) |
| baseline = [] |
| reinforcing = [] |
| for seed in range(16): |
| baseline.append( |
| official_proportional_run( |
| seed=12000 + seed, |
| n=80, |
| kappa=1.1, |
| noise=0.2, |
| b=0.0, |
| lambdas=lambdas, |
| steps=5, |
| ) |
| ) |
| reinforcing.append( |
| official_proportional_run( |
| seed=12000 + seed, |
| n=80, |
| kappa=1.1, |
| noise=0.2, |
| b=0.2, |
| lambdas=lambdas, |
| steps=5, |
| ) |
| ) |
| baseline_mean = np.mean(np.vstack(baseline), axis=0) |
| reinforcing_mean = np.mean(np.vstack(reinforcing), axis=0) |
| i0 = int(np.argmin(baseline_mean)) |
| i1 = int(np.argmin(reinforcing_mean)) |
| claim5 = { |
| "assessment": "verified", |
| "released_mechanism": "proportional/perforidge.py, five RRM deployments, Sigma=I, paired seeds", |
| "n": 80, |
| "p": 88, |
| "runs_per_condition": 16, |
| "lambda_grid": lambdas.tolist(), |
| "baseline_curve": baseline_mean.tolist(), |
| "reinforcing_curve": reinforcing_mean.tolist(), |
| "baseline_optimal_lambda": float(lambdas[i0]), |
| "reinforcing_optimal_lambda": float(lambdas[i1]), |
| "baseline_optimal_risk": float(baseline_mean[i0]), |
| "reinforcing_optimal_risk": float(reinforcing_mean[i1]), |
| "risk_improvement": float(baseline_mean[i0] - reinforcing_mean[i1]), |
| } |
|
|
| claims = [claim1, claim2, claim3, claim4, claim5] |
| gates = { |
| "claim1_finite": bool(np.isfinite([row["exact_risk"] for row in claim1_rows]).all()), |
| "claim1_all_components": claim1["magnitude_direction_spurious_all_varied"], |
| "claim2_proportional": all(abs(row["ratio"] - 1.0) < 1e-15 for row in claim2["proportionality_cells"]), |
| "claim2_literal_zero": abs(uniform_formula) < 1e-14 and abs(uniform_exact) < 1e-14, |
| "claim2_control_positive": nonuniform_risk > 1e-3, |
| "claim3_finite": bool(np.isfinite(de) and np.isfinite(empirical_mean)), |
| "claim3_gap_within_four_se_plus_finite": bool(abs(empirical_mean - de) <= 4 * empirical_se + 0.25), |
| "claim4_low_noise": claim4["low_noise_same_direction"], |
| "claim4_high_noise": claim4["high_noise_opposite_direction"], |
| "claim5_lambda_moves_up": bool(claim5["reinforcing_optimal_lambda"] > claim5["baseline_optimal_lambda"]), |
| "claim5_risk_improves": bool(claim5["risk_improvement"] > 0), |
| "all_assessments_decisive": all(row["assessment"] in {"verified", "falsified"} for row in claims), |
| } |
| return claims, gates |
|
|
|
|
| def main() -> None: |
| parser = argparse.ArgumentParser() |
| parser.add_argument("--output-dir", type=Path, required=True) |
| args = parser.parse_args() |
| claims, gates = reproduce() |
| args.output_dir.mkdir(parents=True, exist_ok=True) |
| for index, claim in enumerate(claims, 1): |
| dump(args.output_dir / f"claim{index}.json", claim) |
| result = { |
| "paper_id": PAPER_ID, |
| "claims": [ |
| {"claim": index, "literal_claim": literal_claim} |
| for index, literal_claim in enumerate(CLAIMS, 1) |
| ], |
| "claim_results": claims, |
| "gates": gates, |
| "all_gates_pass": all(gates.values()), |
| } |
| dump(args.output_dir / "results.json", result) |
| digest = hashlib.sha256((args.output_dir / "results.json").read_bytes()).hexdigest() |
| print(json.dumps({"all_gates_pass": result["all_gates_pass"], "gates": gates, "results_sha256": digest}, indent=2, sort_keys=True)) |
| if not result["all_gates_pass"]: |
| raise SystemExit("one or more gates failed") |
|
|
|
|
| if __name__ == "__main__": |
| main() |
|
|