File size: 2,027 Bytes
cbe9a94
 
 
 
b891f5c
a4c4ce7
cbe9a94
 
 
 
50eaad1
 
 
cbe9a94
 
 
 
 
 
a4c4ce7
 
cbe9a94
 
 
a4c4ce7
cbe9a94
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
import argparse
import json

import torch

from oev.evaluate import load_model, pack_question
from oev.tokenizer_hf import HFTokenPacker


def ensemble_accuracy(ckpts, data_dir, device="cuda"):
    if device.startswith("cuda") and not torch.cuda.is_available():
        raise SystemExit("CUDA requested but unavailable. "
                         "Pass device='cpu' explicitly if CPU numbers are intended.")
    models = [load_model(c, device) for c in ckpts]
    packers = [HFTokenPacker(m.cfg["backbone"]) for m in models]
    with open(f"{data_dir}/test.jsonl", encoding="utf-8") as handle:
        rows = [json.loads(line) for line in handle]

    correct = total = 0
    # per-question projection comes from oev.evaluate.pack_question (the same
    # normalization benchmark_ext, distill and serve use)
    with torch.no_grad():
        for r in rows:
            for q in r["questions"]:
                pq = pack_question(q)
                probs_sum = None
                label = None
                for m, p in zip(models, packers):
                    ids, anchors, label = p.pack(r["state"], pq, m.cfg["max_len"])
                    tids = torch.tensor([ids], device=device)
                    pmask = torch.zeros(1, len(ids), dtype=torch.bool, device=device)
                    apos = torch.tensor([anchors], device=device)
                    pr = torch.softmax(m(tids, pmask, apos)[0].float(), dim=-1)
                    probs_sum = pr if probs_sum is None else probs_sum + pr
                total += 1
                correct += int(probs_sum.argmax().item() == label)
    return correct / total, total


if __name__ == "__main__":
    p = argparse.ArgumentParser()
    p.add_argument("--ckpts", required=True, help="comma-separated checkpoint paths")
    p.add_argument("--data-dir", default="data/typed")
    args = p.parse_args()
    ckpts = [c.strip() for c in args.ckpts.split(",") if c.strip()]
    acc, n = ensemble_accuracy(ckpts, args.data_dir)
    print(f"ensemble accuracy: {acc:.4f} (n={n})")