Close Menu
NCIJ Network NCIJ Network
    What's Hot

    What Ben Carroll’s cabinet cuts say about his ‘new direction’ for Victoria | Victorian politics

    August 4, 2026

    Trump has been able to keep oil prices low. But that power may not last forever.

    August 4, 2026

    Trump, Graham Dominate Senate Race: 5 Takeaways from South Carolina Debate.

    August 4, 2026
    Facebook X (Twitter) Instagram
    Trending
    • What Ben Carroll’s cabinet cuts say about his ‘new direction’ for Victoria | Victorian politics
    • Trump has been able to keep oil prices low. But that power may not last forever.
    • Trump, Graham Dominate Senate Race: 5 Takeaways from South Carolina Debate.
    • AI shopping searches surged 200% in one year – and it’s a top priority for commerce leaders now
    • Y Combinator Open-Sources QM: An MIT-Licensed Multiplayer Agent Harness That Runs In Slack And The Web
    • Attackers Exploit N-able Patch Bypass Flaw on RMM Servers
    • Live updates: Bitcoin flirts with $64,000 as stocks start strong in August
    • Your brain may be wired to regain lost weight
    • About
      • Our Team
      • Editorial Policy
      • Editorial Independence
      • International Support
    • Trust & Standards
      • AI Usage Policy
      • Conflict of Interest Policy
      • Corrections Policy
      • Ethics Policy
      • Fact-Checking Policy
      • Source Protection
    • Get Involved
      • Guide for Sources
      • Support Independent Journalism
    • Legal
      • Cookie Policy
      • Privacy Policy
      • Terms of Use
    Facebook X (Twitter) Instagram
    NCIJ Network NCIJ Network
    Tuesday, August 4
    • Home
    • World
    • Ai
    • Business
    • Politics
    • Health
    • Crypto
    • Science
    • Technology
    • Cybersecurity
    • Defense & Security
    • Economy
    • Energy
    • Europe
    • More
      • Fact Check
      • Investigations
      • Opinion & Analysis
      • Environment
    NCIJ Network NCIJ Network
    Home»Artificial Intelligence

    Evaluating Multimodal Vision Models with Moonshot PerceptionBench Using Robust Data Loading and Automated Judging

    NCIJ NETWNCIJ NETWORKBy NCIJ NETWNCIJ NETWORKAugust 4, 2026 Artificial Intelligence No Comments4 Mins Read
    Share
    Facebook Twitter LinkedIn Pinterest Email

    def run_eval(records, backend):
       print(f"n[eval] backend = {backend.name} on {len(records)} questions")
       t0 = time.time()
       preds = backend.predict_batch(records)
       rows = []
       for rec, raw in zip(records, preds):
           if CFG["JUDGE"] == "llm" and CFG["API_KEY"]:
               ok, how = llm_judge(raw, rec["answer"], rec["problem"])
           else:
               ok, how = rule_judge(raw, rec["answer"], CFG["NUM_REL_TOL"])
           rows.append(dict(index=rec["index"], code=rec["code"], category=rec["category"],
                            source_bmk=rec["source_bmk"], n_images=rec["n_images"],
                            q_chars=rec["q_chars"], max_side=rec["max_side"],
                            ans_type=answer_type(rec["answer"]),
                            gold=rec["answer"], pred=extract_answer(raw),
                            raw=str(raw)[:2000], correct=ok, how=how))
       print(f"[eval] done in {time.time()-t0:.1f}s")
       return pd.DataFrame(rows)
    def bootstrap_ci(vals, n_boot=4000, seed=0):
       a = np.asarray(vals, dtype=float)
       if a.size == 0:
           return (float("nan"), float("nan"))
       rng = np.random.default_rng(seed)
       means = a[rng.integers(0, a.size, (n_boot, a.size))].mean(axis=1)
       return tuple(np.percentile(means, [2.5, 97.5]) * 100)
    def report(res, label):
       print("n" + "=" * 78)
       print(f"§9  RESULTS — {label}")
       print("=" * 78)
       lo, hi = bootstrap_ci(res.correct)
       print(f"nOVERALL accuracy: {res.correct.mean()*100:5.1f}%   "
             f"95% CI [{lo:.1f}, {hi:.1f}]   (n={len(res)})")
       print("(card: no frontier model exceeds 60% overall)n")
       print("-- per atomic capability --")
       tab = []
       for code, g in res.groupby("code"):
           l, h = bootstrap_ci(g.correct)
           tab.append(dict(code=code, capability=CODE_FULL.get(code, code),
                           n=len(g), acc=g.correct.mean() * 100, lo=l, hi=h))
       t = pd.DataFrame(tab).sort_values("acc", ascending=False)
       print(t.to_string(index=False, float_format=lambda x: f"{x:6.1f}"))
       print("n-- difficulty slices --")
       res = res.copy()
       res["img_bucket"] = np.where(res.n_images > 1, "multi-image", "single-image")
       res["res_bucket"] = pd.cut(res.max_side, [0, 800, 1600, 10**6],
                                  labels=["<800px", "800-1600px", ">1600px"])
       for col in ["img_bucket", "res_bucket", "ans_type"]:
           s = res.groupby(col, observed=True).correct.agg(["size", "mean"])
           s["mean"] = (s["mean"] * 100).round(1)
           print(f"n  by {col}:n{s.rename(columns={'size':'n','mean':'acc%'}).to_string()}")
       print("n-- judge decision breakdown --")
       print(res.how.value_counts().to_string())
       errs = res[res.correct == 0]
       if len(errs):
           print("n-- sample failures --")
           for _, r in errs.head(5).iterrows():
               print(f"  [{r.code}] gold={r.gold!r:>14}  pred={r['pred']!r:>20}  ({r.how})")
       return t
    BACKEND = make_backend()
    RES = run_eval(RECORDS, BACKEND)
    PER_CAP = report(RES, BACKEND.name)
    LEADERBOARD = {
       "GPT-5.6-Sol":      [59.7, 69.7, 62.4, 62.1, 55.5, 76.7, 67.0, 55.9, 60.0, 54.9, 26.9],
       "Kimi K3":          [58.5, 68.2, 59.7, 59.4, 52.4, 70.3, 59.1, 55.9, 53.3, 61.2, 41.7],
       "Claude-Fable-5":   [57.2, 58.5, 52.9, 60.9, 51.5, 70.4, 56.1, 51.6, 59.8, 64.3, 45.0],
       "Gemini-3.1-Pro":   [56.2, 58.8, 56.9, 61.8, 50.0, 52.7, 61.7, 54.8, 61.2, 64.3, 40.6],
       "Seed-2.1-Pro":     [55.0, 57.6, 51.2, 58.2, 43.6, 50.0, 59.5, 56.6, 60.4, 66.7, 49.8],
       "Qwen3.5-397B-A17B":[47.5, 55.2, 49.1, 53.0, 44.6, 46.7, 49.8, 44.8, 50.2, 52.9, 26.9],
       "Gemma-4-31B":      [40.7, 42.7, 33.9, 40.3, 39.1, 44.9, 43.7, 39.0, 45.9, 46.7, 32.1],
       "GLM-4.6V":         [32.5, 35.2, 31.8, 35.2, 29.1, 30.6, 34.8, 29.3, 33.7, 39.2, 26.9],
    }
    LB = pd.DataFrame(LEADERBOARD, index=["Overall"] + CODE_ORDER).T
    print("n" + "=" * 78)
    print("§10  OFFICIAL LEADERBOARD (subset, accuracy %)")
    print("=" * 78)
    print(LB.to_string())
    print("nNote the structural finding from the card: Hallu is the weakest column "
         "almost everywhere,nand models with near-identical Overall scores have "
         "very different capability profiles.")
    def radar(per_cap_df, label, compare=("GPT-5.6-Sol", "Gemma-4-31B")):
       codes = [c for c in CODE_ORDER if c in set(per_cap_df.code)]
       if len(codes) < 3:
           print("[radar] need >=3 capabilities"); return
       vals = per_cap_df.set_index("code").acc.reindex(codes).fillna(0).tolist()
       ang = np.linspace(0, 2 * np.pi, len(codes), endpoint=False).tolist()
       close = lambda v: v + v[:1]
       fig, ax = plt.subplots(figsize=(6.4, 6.4), subplot_kw=dict(polar=True))
       ax.plot(close(ang), close(vals), lw=2.4, color="#C44E52", label=label)
       ax.fill(close(ang), close(vals), alpha=.18, color="#C44E52")
       for m in compare:
           if m in LB.index:
               v = LB.loc[m, codes].tolist()
               ax.plot(close(ang), close(v), lw=1.3, ls="--", alpha=.85, label=m)
       ax.set_xticks(ang)
       ax.set_xticklabels(codes)
       ax.set_ylim(0, 100)
       ax.set_yticks([20, 40, 60, 80])
       ax.set_title("PerceptionBench capability profile", pad=24)
       ax.legend(loc="upper right", bbox_to_anchor=(1.32, 1.12), fontsize=8)
       plt.tight_layout(); plt.show()
    if CFG["SHOW_PLOTS"]:
       radar(PER_CAP, BACKEND.name)
       fig, ax = plt.subplots(figsize=(7, 3.2))
       s = LB["Overall"].sort_values()
       ax.barh(s.index, s.values, color="#8C8C8C")
       ax.barh([BACKEND.name], [RES.correct.mean() * 100], color="#C44E52")
       ax.axvline(60, ls="--", c="k", lw=1)
       ax.text(60.5, -.4, "60% ceiling: unbeaten", fontsize=8)
       ax.set_xlabel("Overall accuracy (%)"); ax.set_title("Your run vs. the leaderboard")
       plt.tight_layout(); plt.show()
    tag = re.sub(r"[^A-Za-z0-9_.-]", "_", BACKEND.name)
    p_pred = os.path.join(CFG["OUT_DIR"], f"predictions_{tag}.jsonl")
    p_cap  = os.path.join(CFG["OUT_DIR"], f"per_capability_{tag}.csv")
    p_meta = os.path.join(CFG["OUT_DIR"], f"run_meta_{tag}.json")
    with open(p_pred, "w") as f:
       for _, r in RES.iterrows():
           f.write(json.dumps(r.to_dict(), default=str) + "n")
    PER_CAP.to_csv(p_cap, index=False)
    json.dump({"config": {k: v for k, v in CFG.items() if "KEY" not in k},
              "backend": BACKEND.name, "n_questions": len(RES),
              "rows_scanned": N_SCANNED,
              "overall_acc": float(RES.correct.mean() * 100),
              "ci95": list(bootstrap_ci(RES.correct)),
              "timestamp": time.strftime("%Y-%m-%dT%H:%M:%S")},
             open(p_meta, "w"), indent=2)
    print(f"n[export] {p_pred}n[export] {p_cap}n[export] {p_meta}")
    print("n" + "=" * 78)
    print("DONE.  Next steps:")
    print("  1) CFG['BACKEND']='api'  + PB_API_KEY/PB_API_BASE/PB_API_MODEL  -> score a real MLLM")
    print("  2) CFG['BACKEND']='local' on a GPU runtime -> score an open 2-3B VLM")
    print("  3) CFG['JUDGE']='llm' -> reproduce the paper's LLM-as-judge protocol")
    print("  4) Raise N_PER_CATEGORY / MAX_SCAN, or LOAD_MODE='full' for all 3,000 rows")
    print("  5) Ablations worth running: crop-to-region vs. full image, image resolution")
    print("     sweep (MAX_IMAGE_SIDE 512/1024/2048), and CoT-on vs. CoT-off prompts")
    print("=" * 78)
    
    Automated data Evaluating Judging Loading models Moonshot Multimodal PerceptionBench Robust vision
    NCIJ NETWNCIJ NETWORK
    • Website

    Keep Reading

    Y Combinator Open-Sources QM: An MIT-Licensed Multiplayer Agent Harness That Runs In Slack And The Web

    Apple launches legal challenge against UK government demand to access data | Apple

    How to Secure AI Agents, MCP Servers, and LLM Apps in Production

    EU AI Act Article 50 transparency rules enter force

    ⚡ Weekly Recap: Rogue AI Models, $88M Bitcoin Theft, Water-System Attacks and Dangling DNS Hijacks

    A $10 billion data center proposal in central Wisconsin quietly went away

    Add A Comment
    Leave A Reply Cancel Reply

    Editors Picks

    What Ben Carroll’s cabinet cuts say about his ‘new direction’ for Victoria | Victorian politics

    August 4, 2026

    Trump has been able to keep oil prices low. But that power may not last forever.

    August 4, 2026

    Trump, Graham Dominate Senate Race: 5 Takeaways from South Carolina Debate.

    August 4, 2026

    AI shopping searches surged 200% in one year – and it’s a top priority for commerce leaders now

    August 4, 2026
    Latest Posts

    A Russian Spy, Suddenly Cast Into the Spotlight, Flees Japan

    July 23, 2026

    Did Trump accidentally declassify proof Russia tried to help him win 2020 election?

    July 23, 2026

    Trump Puts Section 338 Tariffs on Canada as Greer Foreshadows New Global Duties

    July 23, 2026

    Subscribe to News

    Get the latest sports news from NewsSite about world, sports and politics.

    NCIJ Network is an independent digital news platform delivering trusted investigative journalism, European and global news, in-depth analysis, and fact-based reporting with accuracy, transparency, and integrity.

    Facebook X (Twitter) Instagram Pinterest YouTube

    What Ben Carroll’s cabinet cuts say about his ‘new direction’ for Victoria | Victorian politics

    August 4, 2026

    Trump has been able to keep oil prices low. But that power may not last forever.

    August 4, 2026

    Trump, Graham Dominate Senate Race: 5 Takeaways from South Carolina Debate.

    August 4, 2026

    Subscribe to Updates

    Get the latest creative news from FooBar about art, design and business.

    Type above and press Enter to search. Press Esc to cancel.