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()
|