# -*- coding: utf-8 -*- """Audit 5: precision held-out des regles de TRAIT D'UNION + confusion matrix point final.""" import csv, json, os from collections import Counter OUT = [] def P(*a): s = " ".join(str(x) for x in a); OUT.append(s); print(s) sub = {} with open("/root/sub_LMA06.csv", encoding="utf-8") as f: for row in csv.DictReader(f): sub[row["ID"]] = row["Target"] lang = json.load(open("/root/test_lang.json", encoding="utf-8")) hyp = {"lin": [], "sna": []} for k, v in sub.items(): if lang.get(k) in hyp: hyp[lang[k]].append(v) train, val = {"lin": [], "sna": []}, {"lin": [], "sna": []} for L in ("lin", "sna"): for sp, st in (("train", train), ("validation", val)): with open("/scratch/prep/manifests/waxal_%s_%s.jsonl" % (L, sp), encoding="utf-8") as f: for line in f: if line.strip(): st[L].append(json.loads(line)["text"]) tot_w = sum(len(t.split()) for L in hyp for t in hyp[L]) tot_c = sum(len(t) for L in hyp for t in hyp[L]) W_ERR, C_ERR = 0.5/tot_w, 0.5/tot_c PUNCT = ".,;:!?\"()«»" def toks(t): return [x for x in (w.strip(PUNCT) for w in t.split()) if x] P("=== TRAIT D'UNION : la regle 'a b' -> 'a-b' est-elle fiable ? (VAL held-out) ===") P("1 fix correct = -2 err-mot -1 err-car ; 1 fix errone = +2 err-mot +1 err-car") UNIT = 2*W_ERR + C_ERR P("valeur d'un fix = %.3e score ; ecart au 2e = %.1f fix nets" % (UNIT, 0.000199/UNIT)) for L in ("lin", "sna"): def counts(texts): u = Counter(); b = Counter() for t in texts: ws = [w.lower() for w in toks(t)] u.update(ws); b.update(zip(ws, ws[1:])) return u, b u_tr, b_tr = counts(train[L]) u_va, b_va = counts(val[L]) hyp_bi = Counter() for t in hyp[L]: ws = [w.lower() for w in toks(t)]; hyp_bi.update(zip(ws, ws[1:])) P("") P("--- %s ---" % L) P(" %-30s %6s %6s %7s | %6s %6s %7s | %5s" % ("regle a b -> a-b", "trHyph", "trSep", "trPrec", "vaHyph", "vaSep", "vaPrec", "hyp")) tot_fire = 0; tot_tp = 0; tot_fp = 0 rows = [] for (a, b), c in hyp_bi.items(): h = a + "-" + b th, ts = u_tr.get(h, 0), b_tr.get((a, b), 0) vh, vs = u_va.get(h, 0), b_va.get((a, b), 0) if th + vh < 3: continue rows.append((c, a, b, th, ts, vh, vs)) rows.sort(reverse=True) for c, a, b, th, ts, vh, vs in rows: tp = th/max(th+ts, 1); vp = vh/max(vh+vs, 1) if (vh+vs) else float("nan") P(" %-30s %6d %6d %6.1f%% | %6d %6d %6s | %5d" % (a+" "+b, th, ts, 100*tp, vh, vs, ("%.1f%%" % (100*vp)) if (vh+vs) else "n/a", c)) tot_fire += c; tot_tp += vh; tot_fp += vs prec = tot_tp/max(tot_tp+tot_fp, 1) P(" TOTAL: %d declenchements | precision VAL agregee = %.2f%% (%d/%d)" % (tot_fire, 100*prec, tot_tp, tot_tp+tot_fp)) net = tot_fire*(2*prec-1) P(" GAIN = %d x (2p-1)=%.3f = %.1f fix nets = %+.5f score" % (tot_fire, 2*prec-1, net, net*UNIT)) # variante conservatrice: seulement les regles a precision train >= 90% ff = tt = fpp = 0 for c, a, b, th, ts, vh, vs in rows: if th/max(th+ts,1) >= 0.90: ff += c; tt += vh; fpp += vs if ff: pr2 = tt/max(tt+fpp,1); net2 = ff*(2*pr2-1) P(" CONSERVATEUR (precision train>=90%%): %d declench., precision VAL=%.2f%% -> %.1f fix nets = %+.5f score" % (ff, 100*pr2, net2, net2*UNIT)) # combien de traits d'union produisons-nous deja ? nh = sum(1 for t in hyp[L] for w in toks(t) if "-" in w) ntr = sum(1 for t in train[L] for w in toks(t) if "-" in w) P(" mots contenant '-' : hyp=%d (%.3f%% des mots) | train=%d (%.3f%%)" % (nh, 100.0*nh/sum(len(toks(t)) for t in hyp[L]), ntr, 100.0*ntr/sum(len(toks(t)) for t in train[L]))) # ===== point final : matrice de confusion complete ===== P("") P("=== POINT FINAL : matrice de confusion devhard-lin (joint_cont_best) ===") allh = json.load(open("/root/devhard_allhyps.json", encoding="utf-8")) refs = {} for fn in os.listdir("/root/devhard"): with open("/root/devhard/"+fn, encoding="utf-8") as f: for line in f: if line.strip(): d = json.loads(line); refs[d["id"]] = d.get("text", "") hyps = allh["joint_cont_best"] pairs = [(h.strip().endswith("."), refs[i].strip().endswith(".")) for i, h in hyps.items() if i.startswith("lin_") and i in refs and refs[i].strip()] n11 = sum(1 for a,b in pairs if a and b); n10 = sum(1 for a,b in pairs if a and not b) n01 = sum(1 for a,b in pairs if not a and b); n00 = sum(1 for a,b in pairs if not a and not b) P("n=%d n11=%d n10=%d n01=%d n00=%d" % (len(pairs), n11, n10, n01, n00)) P("P(ref='.' | nous emettons '.') = %.3f" % (n11/max(n11+n10,1))) P("P(ref='.' | nous n'emettons PAS) = %.3f <- si > 0.5, forcer '.' partout gagne" % (n01/max(n01+n00,1))) ntest_no = sum(1 for t in hyp["lin"] if not t.strip().endswith(".")) p = n01/max(n01+n00,1) P("clips lingala du TEST sans point final = %d" % ntest_no) P("gain si on force le point: %d x (2p-1)=%.3f = %.1f clips nets = %+.5f score" % (ntest_no, 2*p-1, ntest_no*(2*p-1), ntest_no*(2*p-1)*(W_ERR+C_ERR))) ntest_no_s = sum(1 for t in hyp["sna"] if not t.strip().endswith(".")) P("clips shona du TEST sans point final = %d (marge negligeable)" % ntest_no_s) with open("/root/audit_STATSLING5_out.txt","w",encoding="utf-8") as f: f.write("\n".join(OUT)) print("\n[OK] /root/audit_STATSLING5_out.txt")