File size: 3,365 Bytes
6eed659
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
84
85
86
87
88
#!/usr/bin/env python3
"""INSERTION DE VIRGULES guidée par notre KenLM in-domain (texte WAXAL train, virgules incluses).
Déficit mesuré : nos sorties lin ont 0.29 virgule/1000 car. contre 5.22 dans les références
=> coût +0.0144 sur le combine lin (mesuré). La tentative §5 avait échoué avec un mBERT
multilingue qui RÉÉCRIVAIT tout (et détruisait les points corrects à 94%).
Ici : on n'AJOUTE que des virgules, jamais on ne touche au reste, et le juge est le LM
entraîné sur le corpus qui définit la convention.

Pour chaque position inter-mots : score LM de "... wi wi+1 ..." vs "... wi, wi+1 ...".
On insère si le gain dépasse un seuil (balayé), avec au plus MAXINS virgules par phrase.
Gate : devhard-lin.
"""
import json, math, os, re, sys
import jiwer, kenlm

ARPA = os.environ.get("ARPA", "/scratch/lm/lin_5g.arpa")
LM = kenlm.Model(ARPA)


def comb(refs, hyps):
    pr = [(r, h) for r, h in zip(refs, hyps) if r.strip()]
    a = [x for x, _ in pr]; b = [y for _, y in pr]
    w = jiwer.wer(a, b); c = jiwer.cer(a, b)
    return w, c, 0.5 * w + 0.5 * c


def sc(text):
    return LM.score(text, bos=True, eos=True)


def insert_commas(text, thr, maxins=6):
    """Ajoute des virgules là où le LM y gagne le plus, de façon gloutonne."""
    w = text.split()
    if len(w) < 3:
        return text
    cur = list(w)
    n = 0
    while n < maxins:
        base = sc(" ".join(cur))
        best = (0.0, -1)
        for i in range(len(cur) - 1):
            if cur[i].endswith(",") or cur[i].endswith(".") or cur[i].endswith("!"):
                continue
            cand = list(cur)
            cand[i] = cand[i] + ","
            g = sc(" ".join(cand)) - base
            if g > best[0]:
                best = (g, i)
        if best[1] < 0 or best[0] < thr:
            break
        cur[best[1]] = cur[best[1]] + ","
        n += 1
    return " ".join(cur)


def main():
    D = json.load(open("/root/devhard_allhyps.json", encoding="utf-8"))
    rows = [json.loads(l) for l in open("/root/devhard/devhard_linsna.jsonl", encoding="utf-8")]
    sub = [r for r in rows if r["lang"] == "lin"]
    refs = [r["text"] for r in sub]
    H = D["joint_cont_best"]
    hyps = [H.get(r["id"], "") for r in sub]
    base = comb(refs, hyps)
    print("baseline lin (joint_cont greedy) : WER %.4f CER %.4f combine %.4f" % base, flush=True)
    nref = sum(t.count(",") for t in refs)
    nhyp = sum(t.count(",") for t in hyps)
    print("virgules : refs %d | nos hyps %d" % (nref, nhyp), flush=True)

    print("\nseuil |  virgules ajoutees |   WER    CER   combine   delta")
    best = (base[2], None)
    for thr in (0.2, 0.5, 1.0, 1.5, 2.0, 3.0, 5.0):
        out = [insert_commas(h, thr) for h in hyps]
        added = sum(o.count(",") for o in out) - nhyp
        m = comb(refs, out)
        d = m[2] - base[2]
        if m[2] < best[0]:
            best = (m[2], thr)
        print("%5.1f |  %5d             | %.4f %.4f  %.4f  %+.4f%s"
              % (thr, added, m[0], m[1], m[2], d, "  <-- MIEUX" if d < 0 else ""), flush=True)
    print("\nMEILLEUR : combine %.4f (seuil %s) vs baseline %.4f" % (best[0], best[1], base[2]), flush=True)
    json.dump({"baseline": base[2], "best": best[0], "thr": best[1]},
              open("/root/comma_kenlm.json", "w"))
    print("COMMA_KENLM_DONE", flush=True)


if __name__ == "__main__":
    main()