File size: 2,449 Bytes
6e802a4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# fan_metric.py: Code-domain repetition diagnostic (A-B-A-B limit cycles per codebook).

from __future__ import annotations

import argparse
import json
from pathlib import Path


def flip2(seq):
    if len(seq) < 3:
        return None
    hits = tot = 0
    for t in range(2, len(seq)):
        tot += 1
        if seq[t] == seq[t - 2] and seq[t] != seq[t - 1]:
            hits += 1
    return hits / tot if tot else None


def rep(seq):
    if len(seq) < 2:
        return None
    return sum(1 for t in range(1, len(seq)) if seq[t] == seq[t - 1]) / (len(seq) - 1)


def levels_of(row):
    cb0 = row.get("speech_tokens")
    res = row.get("residual_codes") or []
    if cb0 is None:
        return None
    return [cb0] + list(res)


def analyse(path, limit=None):
    rows = [json.loads(l) for l in open(path, encoding="utf-8") if l.strip()]
    if limit:
        rows = rows[:limit]
    per_level_f, per_level_r, nl = {}, {}, 0
    for r in rows:
        lv = levels_of(r)
        if not lv:
            continue
        nl = max(nl, len(lv))
        for k, seq in enumerate(lv):
            f, p = flip2(seq), rep(seq)
            if f is not None:
                per_level_f.setdefault(k, []).append(f)
            if p is not None:
                per_level_r.setdefault(k, []).append(p)
    return per_level_f, per_level_r, nl, len(rows)


def main():
    ap = argparse.ArgumentParser()
    ap.add_argument("paths", nargs="+")
    ap.add_argument("--limit", type=int, default=None)
    args = ap.parse_args()

    print(f"{'file':<34} {'n':>4} | " + " ".join(f"cb{k}" .rjust(6) for k in range(10))
          + " |  mean1-3  mean4-9")
    print("-" * 130)
    for p in args.paths:
        if not Path(p).exists():
            print(f"{Path(p).name:<34} (missing)")
            continue
        f, _r, nl, n = analyse(p, args.limit)
        cells = []
        for k in range(10):
            if k in f and f[k]:
                cells.append(f"{100*sum(f[k])/len(f[k]):6.2f}")
            else:
                cells.append("     -")
        def mean_of(ks):
            vs = [v for k in ks if k in f for v in f[k]]
            return f"{100*sum(vs)/len(vs):7.2f}" if vs else "      -"
        print(f"{Path(p).name:<34} {n:>4} | " + " ".join(cells)
              + f" | {mean_of(range(1,4))} {mean_of(range(4,10))}")
    print("\n(values are flip2 %, the A-B-A-B fan signature; human GT ~0.2-0.5%)")

if __name__ == "__main__":
    main()