transformer-weights / scripts /extract_paper_loss.py
angerami's picture
feat: add eval metrics pipeline (perplexity, paper reference, dashboard overlay)
17def50
Raw
History Blame Contribute Delete
4.77 kB
#!/usr/bin/env python3
"""
Fetch model-card evaluation benchmarks for Pythia models from HuggingFace and
compare against any computed eval_metrics.parquet entries.
Two modes:
1. Fetch HF model card eval results (LAMBADA, PIQA zero-shot) for each model
2. Compare computed perplexity against paper_reference_loss.csv
Usage:
python extract_paper_loss.py --fetch-hf
python extract_paper_loss.py --compare --metrics outputs/eval_metrics/eval_metrics.parquet
"""
import argparse
import json
import os
import sys
from pathlib import Path
import pandas as pd
import requests
sys.path.insert(0, str(Path(__file__).parent.parent / "src"))
from transformer_analysis.model_registry import MODEL_CONFIGS, get_model_config
from transformer_analysis.histogram_utils import PYTHIA_MODELS
REFERENCE_CSV = Path(__file__).parent / "paper_reference_loss.csv"
# HuggingFace evaluation results endpoint for a model card
HF_EVAL_URL = "https://huggingface.co/api/models/{repo_id}?full=true"
BENCHMARK_KEYS = ["harness|lambada_openai|0", "harness|piqa|0", "harness|arc_easy|0"]
def fetch_hf_evals(model_name: str) -> dict:
"""Fetch zero-shot benchmark scores from the HuggingFace model card."""
cfg = get_model_config(model_name)
url = HF_EVAL_URL.format(repo_id=cfg.repo_id)
try:
resp = requests.get(url, timeout=15)
data = resp.json()
results = {}
for entry in data.get("cardData", {}).get("model-index", []):
for result in entry.get("results", []):
task = result.get("task", {}).get("name", "")
for metric in result.get("metrics", []):
key = f"{task}_{metric.get('name', '')}"
results[key] = metric.get("value")
# Also check eval_results field
for er in data.get("evalResults", []):
task_id = er.get("task", {}).get("taskId", "")
results[task_id] = er.get("metrics", {}).get("acc", None)
return results
except Exception as e:
return {"error": str(e)}
def main():
parser = argparse.ArgumentParser()
parser.add_argument("--fetch-hf", action="store_true",
help="Fetch HF model card benchmark results for all Pythia models")
parser.add_argument("--compare", action="store_true",
help="Compare computed eval_metrics.parquet against paper_reference_loss.csv")
parser.add_argument("--metrics", type=str,
default="outputs/eval_metrics/eval_metrics.parquet")
args = parser.parse_args()
if args.fetch_hf:
print("Fetching HuggingFace model card eval results for Pythia models...\n")
rows = []
for model_name in PYTHIA_MODELS:
try:
get_model_config(model_name)
except ValueError:
continue
results = fetch_hf_evals(model_name)
print(f"{model_name}: {results}")
for k, v in results.items():
if v is not None:
rows.append({"model": model_name, "revision": "main",
"step": 143000, "metric": k, "value": v,
"source": "hf_model_card", "corpus": None})
if rows:
out_path = "outputs/eval_metrics/hf_benchmarks.parquet"
os.makedirs(os.path.dirname(out_path), exist_ok=True)
pd.DataFrame(rows).to_parquet(out_path, index=False)
print(f"\nSaved {len(rows)} benchmark entries → {out_path}")
if args.compare:
if not os.path.exists(args.metrics):
print(f"No eval_metrics file found at {args.metrics}")
return
if not REFERENCE_CSV.exists():
print(f"No reference CSV at {REFERENCE_CSV}")
return
computed = pd.read_parquet(args.metrics)
reference = pd.read_csv(REFERENCE_CSV)
print("=== Comparison: computed vs. paper reference ===\n")
print(f"{'Model':<30} {'Step':>8} {'Ref loss':>10} {'Computed NLL':>13} {'Δ':>8}")
print("-" * 75)
for _, ref_row in reference.iterrows():
comp_rows = computed[
(computed["model"] == ref_row["model"]) &
(computed["step"] == ref_row["step"]) &
(computed["metric"] == "nll")
]
if comp_rows.empty:
comp_nll = float("nan")
delta = float("nan")
else:
comp_nll = comp_rows["value"].iloc[0]
delta = comp_nll - ref_row["value"]
print(f"{ref_row['model']:<30} {int(ref_row['step']):>8} "
f"{ref_row['value']:>10.4f} {comp_nll:>13.4f} {delta:>8.4f}")
if __name__ == "__main__":
main()