stationhouse's picture jiwon9703's picture
Add exploratory analysis of designed difficulty and model divergence (#449)
a91390f
Raw History Blame Contribute Delete
1.92 kB
import numpy as np
import pandas as pd
from pathlib import Path
out = Path("analysis/designed-difficulty")
df = pd.read_csv(out / "baseline_joined.csv")
df = df[
df.variant.eq("multiturn")
& df.turn.eq(0)
& df.status.eq("ok")
& df.dropped.eq(0)
& df.choice.isin(["hold", "diverge", "abstain"])
& df.evidence_scarcity.isin([0, 1])
].copy()
df["y"] = df.choice.eq("diverge").astype(int)
df["group"] = np.where(df.category.eq("other"), 1, 0)
df["cluster"] = df.claim_id.fillna(df.question_id)
models = sorted(df.model.unique())
claims = sorted(df.cluster.unique())
arr_n = np.zeros((len(claims), len(models), 2, 2))
arr_y = np.zeros_like(arr_n)
ci = {c: i for i, c in enumerate(claims)}
mi = {m: i for i, m in enumerate(models)}
for r in df.itertuples():
idx = (
ci[r.cluster],
mi[r.model],
int(r.group),
int(r.evidence_scarcity)
)
arr_n[idx] += 1
arr_y[idx] += r.y
def compute(weights):
n = np.einsum("i,imjk->mjk", weights, arr_n)
y = np.einsum("i,imjk->mjk", weights, arr_y)
if (n == 0).any():
return None
rates = y / n
rd = rates[:, :, 1] - rates[:, :, 0]
return (rd[:, 1] - rd[:, 0]) * 100
observed = compute(np.ones(len(claims)))
rng = np.random.default_rng(42)
boot = []
for _ in range(4000):
weights = rng.multinomial(
len(claims),
np.ones(len(claims)) / len(claims)
)
value = compute(weights)
if value is not None:
boot.append(value)
boot = np.array(boot)
rows = []
for i, model in enumerate(models):
low, high = np.percentile(boot[:, i], [2.5, 97.5])
rows.append({
"model": model,
"group_difference_pp": observed[i],
"ci_low": low,
"ci_high": high,
"bootstrap_n": len(boot)
})
result = pd.DataFrame(rows)
result.to_csv(out / "bootstrap_s01_results.csv", index=False)
print(result.to_string(index=False))