diff options
| author | haoyuren <13851610112@163.com> | 2026-07-28 21:17:38 +0800 |
|---|---|---|
| committer | haoyuren <13851610112@163.com> | 2026-07-28 21:17:38 +0800 |
| commit | 3b5f01cb4db9efc4ceb2ba17709bbfc82a63e660 (patch) | |
| tree | ad4e2321373fc9e551ffeb2ca27f5533ca9e9bdb | |
| parent | 18bf25f34f6d352605086aa8fe63977baacc315b (diff) | |
Add appendix table generator and generated LaTeX fragments
generate_paper_tables.py reads the row-level CSVs and emits the four
appendix tables (initialization calibration rows, finite-time cells,
CNN calibration rows, learning-rate regimes) with the paper's nested
uncertainty convention. The fragments are included by the manuscript
via \input; no table value is transcribed manually.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
| -rw-r--r-- | outputs/tables/cnn_initialization_rows.tex | 14 | ||||
| -rw-r--r-- | outputs/tables/finite_time_cells.tex | 21 | ||||
| -rw-r--r-- | outputs/tables/initialization_rows.tex | 36 | ||||
| -rw-r--r-- | outputs/tables/learning_rate_regimes.tex | 21 | ||||
| -rw-r--r-- | scripts/generate_paper_tables.py | 177 |
5 files changed, 269 insertions, 0 deletions
diff --git a/outputs/tables/cnn_initialization_rows.tex b/outputs/tables/cnn_initialization_rows.tex new file mode 100644 index 0000000..9066ce0 --- /dev/null +++ b/outputs/tables/cnn_initialization_rows.tex @@ -0,0 +1,14 @@ +\begin{tabular}{@{}lrccc@{}} +\toprule +Rule & Init & Prediction & Measured & SE \\ +\midrule +DFA & 0 & 0.647613 & 0.652511 & 0.0051 \\ +DFA & 1 & 0.591587 & 0.587769 & 0.0066 \\ +DFA & 2 & 0.771871 & 0.776294 & 0.0053 \\ +DFA & 3 & 0.815630 & 0.814164 & 0.0052 \\ +FA & 0 & 0.647613 & 0.648186 & 0.005 \\ +FA & 1 & 0.591587 & 0.599896 & 0.0064 \\ +FA & 2 & 0.771871 & 0.777543 & 0.0055 \\ +FA & 3 & 0.815630 & 0.814227 & 0.0052 \\ +\bottomrule +\end{tabular} diff --git a/outputs/tables/finite_time_cells.tex b/outputs/tables/finite_time_cells.tex new file mode 100644 index 0000000..20f76be --- /dev/null +++ b/outputs/tables/finite_time_cells.tex @@ -0,0 +1,21 @@ +\begin{tabular}{@{}rrccccc@{}} +\toprule +Depth & Width & Measured & SE & Frozen & Linear & Relinearized \\ +\midrule +1 & 32 & 0.051369 & 0.0079 & 0.057429 & 0.051108 & 0.053289 \\ +1 & 64 & 0.042081 & 0.0026 & 0.046148 & 0.041747 & 0.043214 \\ +1 & 96 & 0.040667 & 0.0041 & 0.044705 & 0.040255 & 0.041735 \\ +2 & 32 & 0.199114 & 0.015 & 0.245567 & 0.196161 & 0.213008 \\ +2 & 64 & 0.152697 & 0.0082 & 0.176001 & 0.150869 & 0.159079 \\ +2 & 96 & 0.218336 & 0.022 & 0.247394 & 0.216029 & 0.225711 \\ +3 & 32 & 0.206504 & 0.037 & 0.278753 & 0.196695 & 0.226089 \\ +3 & 64 & 0.252548 & 0.035 & 0.301208 & 0.246641 & 0.263831 \\ +3 & 96 & 0.312576 & 0.029 & 0.376889 & 0.306903 & 0.326215 \\ +4 & 32 & 0.222365 & 0.061 & 0.285694 & 0.212004 & 0.236205 \\ +4 & 64 & 0.281210 & 0.013 & 0.360586 & 0.274093 & 0.302059 \\ +4 & 96 & 0.451119 & 0.02 & 0.554664 & 0.441827 & 0.473896 \\ +6 & 32 & 0.202818 & 0.0058 & 0.291825 & 0.206767 & 0.221531 \\ +6 & 64 & 0.346053 & 0.042 & 0.518519 & 0.312131 & 0.371649 \\ +6 & 96 & 0.535727 & 0.032 & 0.733133 & 0.501304 & 0.565975 \\ +\bottomrule +\end{tabular} diff --git a/outputs/tables/initialization_rows.tex b/outputs/tables/initialization_rows.tex new file mode 100644 index 0000000..0654013 --- /dev/null +++ b/outputs/tables/initialization_rows.tex @@ -0,0 +1,36 @@ +\begin{tabular}{@{}rrccc@{}} +\toprule +Depth & Init & Prediction & FA measured (SE) & DFA measured (SE) \\ +\midrule +1 & 0 & 0.053588 & 0.052887 (0.00037) & 0.053807 (0.00041) \\ +1 & 1 & 0.062410 & 0.062244 (0.00048) & 0.062625 (0.00048) \\ +1 & 2 & 0.028953 & 0.029159 (0.00023) & 0.029212 (0.00023) \\ +1 & 3 & 0.040257 & 0.040253 (0.00028) & 0.040521 (0.00028) \\ +1 & 4 & 0.038773 & 0.038649 (0.00032) & 0.039119 (0.00031) \\ +1 & 5 & 0.078297 & 0.078008 (0.0006) & 0.078183 (0.00056) \\ +2 & 0 & 0.218902 & 0.218122 (0.0024) & 0.221537 (0.0024) \\ +2 & 1 & 0.279596 & 0.280372 (0.0027) & 0.280990 (0.0025) \\ +2 & 2 & 0.364830 & 0.361380 (0.003) & 0.364535 (0.003) \\ +2 & 3 & 0.307008 & 0.306619 (0.0024) & 0.309576 (0.0025) \\ +2 & 4 & 0.182403 & 0.181656 (0.0021) & 0.182641 (0.0023) \\ +2 & 5 & 0.309058 & 0.307749 (0.0023) & 0.309189 (0.0022) \\ +3 & 0 & 0.470739 & 0.468836 (0.0036) & 0.466214 (0.0041) \\ +3 & 1 & 0.444351 & 0.446781 (0.0033) & 0.448788 (0.0034) \\ +3 & 2 & 0.374155 & 0.373663 (0.0027) & 0.373020 (0.0032) \\ +3 & 3 & 0.277165 & 0.276679 (0.0039) & 0.278645 (0.0043) \\ +3 & 4 & 0.368780 & 0.367594 (0.0037) & 0.369790 (0.0039) \\ +3 & 5 & 0.480622 & 0.479752 (0.0036) & 0.477239 (0.0039) \\ +4 & 0 & 0.509811 & 0.507382 (0.0033) & 0.507785 (0.0036) \\ +4 & 1 & 0.504652 & 0.502008 (0.0033) & 0.501042 (0.0039) \\ +4 & 2 & 0.433303 & 0.429889 (0.0037) & 0.437931 (0.0041) \\ +4 & 3 & 0.493355 & 0.498489 (0.004) & 0.490059 (0.0045) \\ +4 & 4 & 0.282292 & 0.278860 (0.0029) & 0.278743 (0.0027) \\ +4 & 5 & 0.527837 & 0.525461 (0.0035) & 0.525114 (0.004) \\ +6 & 0 & 0.655509 & 0.660608 (0.0035) & 0.652847 (0.0043) \\ +6 & 1 & 0.694866 & 0.703226 (0.0049) & 0.702721 (0.0051) \\ +6 & 2 & 0.688833 & 0.689167 (0.004) & 0.687606 (0.0044) \\ +6 & 3 & 0.497143 & 0.494329 (0.0032) & 0.491664 (0.0035) \\ +6 & 4 & 0.595326 & 0.586449 (0.0038) & 0.591266 (0.0037) \\ +6 & 5 & 0.607480 & 0.611624 (0.0038) & 0.616644 (0.0038) \\ +\bottomrule +\end{tabular} diff --git a/outputs/tables/learning_rate_regimes.tex b/outputs/tables/learning_rate_regimes.tex new file mode 100644 index 0000000..85a8048 --- /dev/null +++ b/outputs/tables/learning_rate_regimes.tex @@ -0,0 +1,21 @@ +\begin{tabular}{@{}rlcccc@{}} +\toprule +Depth & Regime & BP rate & Mean FA rate & Gap & SE \\ +\midrule +1 & Same rate & 0.001 & 0.001 & 0.05906 & 0.0039 \\ +1 & Initial compensation & 0.001 & 0.001041 & 0.04053 & 0.0031 \\ +1 & Independently selected & 0.128 & 0.064 & 0.56940 & 0.01 \\ +2 & Same rate & 0.001 & 0.001 & 0.19917 & 0.014 \\ +2 & Initial compensation & 0.001 & 0.001317 & 0.09729 & 0.01 \\ +2 & Independently selected & 0.128 & 0.032 & 0.64210 & 0.051 \\ +3 & Same rate & 0.001 & 0.001 & 0.27346 & 0.026 \\ +3 & Initial compensation & 0.001 & 0.001607 & 0.16262 & 0.024 \\ +3 & Independently selected & 0.064 & 0.016 & 1.13002 & 0.024 \\ +4 & Same rate & 0.001 & 0.001 & 0.29340 & 0.021 \\ +4 & Initial compensation & 0.001 & 0.001917 & 0.18442 & 0.017 \\ +4 & Independently selected & 0.064 & 0.016 & 1.30812 & 0.06 \\ +6 & Same rate & 0.001 & 0.001 & 0.40664 & 0.038 \\ +6 & Initial compensation & 0.001 & 0.002591 & 0.28850 & 0.027 \\ +6 & Independently selected & 0.064 & 0.004 & 1.75739 & 0.026 \\ +\bottomrule +\end{tabular} diff --git a/scripts/generate_paper_tables.py b/scripts/generate_paper_tables.py new file mode 100644 index 0000000..ed66dae --- /dev/null +++ b/scripts/generate_paper_tables.py @@ -0,0 +1,177 @@ +#!/usr/bin/env python3 +"""Generate LaTeX table fragments for the paper appendices from row-level CSVs. + +Each fragment contains only a tabular environment; captions and labels live in +the paper source. Uncertainty follows the paper's nesting convention: feedback +draws are averaged within each forward initialization first, and standard +errors are computed across forward-initialization means. +""" + +from __future__ import annotations + +import argparse +import csv +import math +import statistics +from collections import defaultdict +from pathlib import Path + + +def parse_args() -> argparse.Namespace: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--depth-dir", type=Path, default=Path("outputs/aaai_depth_experiments")) + parser.add_argument( + "--cnn-dir", type=Path, default=Path("outputs/cnn_initialization_validation") + ) + parser.add_argument( + "--lr-dir", type=Path, default=Path("outputs/learning_rate_compensation") + ) + parser.add_argument("--outdir", type=Path, default=Path("outputs/tables")) + return parser.parse_args() + + +def read_rows(path: Path) -> list[dict[str, str]]: + if not path.exists(): + raise FileNotFoundError(path) + with path.open() as handle: + return list(csv.DictReader(handle)) + + +def sem(values: list[float]) -> float: + if len(values) < 2: + return float("nan") + return statistics.stdev(values) / math.sqrt(len(values)) + + +def write_fragment(path: Path, lines: list[str]) -> None: + path.parent.mkdir(parents=True, exist_ok=True) + path.write_text("\n".join(lines) + "\n") + print(f"wrote {path}") + + +def initialization_table(depth_dir: Path, outdir: Path) -> None: + rows = read_rows(depth_dir / "initialization_rows.csv") + cells: dict[tuple[int, int], dict[str, dict[str, float]]] = defaultdict(dict) + for row in rows: + key = (int(row["depth"]), int(row["init_seed"])) + cells[key][row["rule"]] = { + "pred": float(row["predicted_deficit"]), + "mean": float(row["empirical_deficit"]), + "se": float(row["empirical_stderr"]), + } + lines = [ + r"\begin{tabular}{@{}rrccc@{}}", + r"\toprule", + r"Depth & Init & Prediction & FA measured (SE) & DFA measured (SE) \\", + r"\midrule", + ] + for (depth, init_seed), by_rule in sorted(cells.items()): + fa, dfa = by_rule["FA"], by_rule["DFA"] + assert abs(fa["pred"] - dfa["pred"]) < 1e-12, (depth, init_seed) + lines.append( + f"{depth} & {init_seed - 10_000} & {fa['pred']:.6f} & " + f"{fa['mean']:.6f} ({fa['se']:.2g}) & " + f"{dfa['mean']:.6f} ({dfa['se']:.2g}) \\\\" + ) + lines += [r"\bottomrule", r"\end{tabular}"] + write_fragment(outdir / "initialization_rows.tex", lines) + + +def finite_time_table(depth_dir: Path, outdir: Path) -> None: + rows = read_rows(depth_dir / "finite_time_rows.csv") + cells: dict[tuple[int, int], dict[int, dict[str, list[float]]]] = defaultdict( + lambda: defaultdict(lambda: defaultdict(list)) + ) + fields = ["empirical_gap", "fixed_gap", "velocity_gap", "retangent_gap"] + for row in rows: + cell = cells[(int(row["depth"]), int(row["width"]))][int(row["init_seed"])] + for field in fields: + cell[field].append(float(row[field])) + lines = [ + r"\begin{tabular}{@{}rrccccc@{}}", + r"\toprule", + r"Depth & Width & Measured & SE & Frozen & Linear & Relinearized \\", + r"\midrule", + ] + for (depth, width), by_init in sorted(cells.items()): + init_means = { + field: [statistics.mean(values[field]) for _, values in sorted(by_init.items())] + for field in fields + } + measured = statistics.mean(init_means["empirical_gap"]) + lines.append( + f"{depth} & {width} & {measured:.6f} & {sem(init_means['empirical_gap']):.2g} & " + f"{statistics.mean(init_means['fixed_gap']):.6f} & " + f"{statistics.mean(init_means['velocity_gap']):.6f} & " + f"{statistics.mean(init_means['retangent_gap']):.6f} \\\\" + ) + lines += [r"\bottomrule", r"\end{tabular}"] + write_fragment(outdir / "finite_time_cells.tex", lines) + + +def cnn_table(cnn_dir: Path, outdir: Path) -> None: + rows = read_rows(cnn_dir / "cnn_initialization_rows.csv") + lines = [ + r"\begin{tabular}{@{}lrccc@{}}", + r"\toprule", + r"Rule & Init & Prediction & Measured & SE \\", + r"\midrule", + ] + for row in sorted(rows, key=lambda r: (r["rule"], int(r["init_seed"]))): + lines.append( + f"{row['rule']} & {int(row['init_seed']) - 10_000} & " + f"{float(row['predicted_deficit']):.6f} & " + f"{float(row['empirical_deficit']):.6f} & " + f"{float(row['empirical_stderr']):.2g} \\\\" + ) + lines += [r"\bottomrule", r"\end{tabular}"] + write_fragment(outdir / "cnn_initialization_rows.tex", lines) + + +def learning_rate_table(lr_dir: Path, outdir: Path) -> None: + rows = read_rows(lr_dir / "evaluation_rows.csv") + regime_order = {"same_lr": 0, "initial_compensation": 1, "independently_tuned": 2} + regime_label = { + "same_lr": "Same rate", + "initial_compensation": "Initial compensation", + "independently_tuned": "Independently selected", + } + cells: dict[tuple[int, str], dict[int, list[float]]] = defaultdict(lambda: defaultdict(list)) + fa_rates: dict[tuple[int, str], list[float]] = defaultdict(list) + bp_rates: dict[tuple[int, str], set[float]] = defaultdict(set) + for row in rows: + assert row["stable"] == "True", row + key = (int(row["depth"]), row["regime"]) + cells[key][int(row["init_seed"])].append(float(row["gap_to_bp"])) + fa_rates[key].append(float(row["fa_lr"])) + bp_rates[key].add(float(row["bp_lr"])) + lines = [ + r"\begin{tabular}{@{}rlcccc@{}}", + r"\toprule", + r"Depth & Regime & BP rate & Mean FA rate & Gap & SE \\", + r"\midrule", + ] + for (depth, regime), by_init in sorted( + cells.items(), key=lambda item: (item[0][0], regime_order[item[0][1]]) + ): + init_means = [statistics.mean(values) for _, values in sorted(by_init.items())] + (bp_rate,) = bp_rates[(depth, regime)] + lines.append( + f"{depth} & {regime_label[regime]} & {bp_rate:g} & " + f"{statistics.mean(fa_rates[(depth, regime)]):.4g} & " + f"{statistics.mean(init_means):.5f} & {sem(init_means):.2g} \\\\" + ) + lines += [r"\bottomrule", r"\end{tabular}"] + write_fragment(outdir / "learning_rate_regimes.tex", lines) + + +def main() -> None: + args = parse_args() + initialization_table(args.depth_dir, args.outdir) + finite_time_table(args.depth_dir, args.outdir) + cnn_table(args.cnn_dir, args.outdir) + learning_rate_table(args.lr_dir, args.outdir) + + +if __name__ == "__main__": + main() |
