Phase 2a Flavor-Comparison Summary#
This notebook summarises the Optuna hyperparameter-search results for the Phase 2a flavor study — comparing the four monotonic-layer flavors across the five ICML 2023 benchmark datasets. A flavor is a mode × residual combination:
Axis |
Values |
|---|---|
mode |
|
residual |
|
The four flavors are switch-plain, switch-residual, absolute-plain, absolute-residual,
each tuned independently per dataset via Optuna.
For each dataset the table below shows:
One row per flavor (tuned best from Phase 2a search), with test mean ± std across seeds.
A
paper (CMNN) [prior protocol]row with the number reported in Table 1 / Table 2 of Runje & Shankaranarayana (ICML 2023) — included for like-for-like comparison. These paper numbers were obtained with a test-selected protocol and are not directly comparable to our held-out results — see Protocol.An
XGBoostrow as a non-monotonic gradient-boosting baseline (skipped gracefully when the raw data are not present in the render environment).
Blog dataset note: the paper and the search both optimise MSE internally, but the table displays RMSE for Blog to match the scale used in the paper’s Table 1.
Numbers come from the maintainer’s search run
(benchmarks/notebooks/search-*.ipynb), committed as
benchmarks/results/phase2/*.json. Until those runs are executed and
committed, this notebook renders a placeholder message.
import json
from pathlib import Path
import pandas as pd
from benchmarks.datasets.download import default_dest
from benchmarks.datasets.registry import load
from benchmarks.baselines.xgboost import run_xgboost
RESULTS = Path("../../benchmarks/results/phase2")
# Paper-quoted Table 1/2 numbers (tagged [prior protocol]). Blog is RMSE; others per dataset.
PAPER = {
"auto": ("mse", 8.37),
"heart": ("accuracy", 0.885),
"compas": ("accuracy", 0.692),
"loan": ("accuracy", 0.653),
"blog": ("rmse", None), # TODO(maintainer): transcribe paper Table 1 Blog RMSE
}
results = sorted(RESULTS.glob("*.json")) if RESULTS.exists() else []
if not results:
print("No Phase-2a results committed yet. Run tools/mononet-benchmark-search.")
else:
by_ds: dict[str, list[dict]] = {}
for f in results:
rec = json.loads(f.read_text())
by_ds.setdefault(rec["dataset"], []).append(rec)
for ds, recs in sorted(by_ds.items()):
metric = recs[0]["test_metric"]
rows = []
for rec in sorted(recs, key=lambda r: r["flavor"]):
mean = rec["test_mean"]
# Blog: study reports mse; show rmse for like-for-like paper comparison.
if ds == "blog" and metric == "mse":
mean = mean ** 0.5
rows.append({"method": rec["flavor"], "value": round(mean, 4),
"std": round(rec["test_std"], 4)})
pmetric, pval = PAPER.get(ds, (metric, None))
rows.append({"method": "paper (CMNN) [prior protocol]", "value": pval, "std": "-"})
try:
xgb = run_xgboost(load(ds, data_dir=default_dest()), seed=0)
key = "accuracy" if "accuracy" in xgb else ("rmse" if ds == "blog" else "mse")
rows.append({"method": "XGBoost", "value": round(xgb[key], 4), "std": "-"})
except Exception as exc: # data not downloaded in the render env
rows.append({"method": "XGBoost", "value": f"(skipped: {type(exc).__name__})", "std": "-"})
print(f"### {ds} (metric: {'rmse' if ds == 'blog' else metric})")
display(pd.DataFrame(rows).set_index("method"))
### auto (metric: mse)
| value | std | |
|---|---|---|
| method | ||
| absolute-plain | 9.5191 | 0.2601 |
| absolute-residual | 9.9428 | 0.1841 |
| switch-plain | 9.5581 | 0.2512 |
| switch-residual | 10.4385 | 0.5537 |
| paper (CMNN) [prior protocol] | 8.3700 | - |
| XGBoost | 12.7538 | - |