|
|
| """Applique le modele de restauration de virgules a une soumission.
|
|
|
| Chaque virgule BIEN placee corrige 1 substitution de mot (+1 caractere manquant) ;
|
| chaque virgule MAL placee en CREE une. Le gain n est donc positif que si la precision
|
| depasse 50 %. => on n insere qu au-dessus d un SEUIL de probabilite, et on balaye ce
|
| seuil : seuil eleve = peu d insertions mais tres sures.
|
|
|
| SEUIL=1.01 => aucune insertion => reproduit BASE a l identique (CONTROLE).
|
|
|
| On traite les DEUX langues (references : 0.81 virgule/enonce en lingala, 0.51 en shona ;
|
| notre sortie : 0.05 et 0.13). Le rapport `taux atteint` permet de voir a quel seuil on
|
| se rapproche du taux de reference sans forcer.
|
|
|
| On ne touche QUE les virgules : ni la casse, ni le point final, ni l ordre des mots.
|
| """
|
| import csv
|
| import json
|
| import os
|
|
|
| import numpy as np
|
| import torch
|
| from transformers import AutoModelForTokenClassification, AutoTokenizer
|
|
|
| BASE = os.environ.get("BASE", "/root/sub_XC010.csv")
|
|
|
|
|
|
|
|
|
|
|
| MODELS = [x for x in os.environ.get("PUNCT_MODEL", "/scratch/runs/punct2/best").split(",") if x]
|
| LANGF = os.environ.get("LANGF", "/root/test_lang.json")
|
| THS = [float(x) for x in os.environ.get("THS", "1.01,0.9,0.8,0.7,0.6,0.5").split(",")]
|
|
|
|
|
|
|
|
|
| TH_LIN = os.environ.get("TH_LIN", "")
|
|
|
|
|
|
|
| TH_SNA = os.environ.get("TH_SNA", "")
|
| TAG = os.environ.get("TAG", "PC")
|
| MAXLEN = int(os.environ.get("MAXLEN", "192"))
|
| REF_RATE = {"lin": 0.81, "sna": 0.51}
|
|
|
|
|
| def main():
|
| base = {r["ID"]: r["Target"] for r in csv.DictReader(open(BASE, encoding="utf-8"))}
|
| lang = json.load(open(LANGF))
|
| ids = list(base)
|
| print("base %d clips" % len(base), flush=True)
|
|
|
|
|
|
|
|
|
| PROB, WORDS, RAW = {}, {}, {}
|
| ACC = {}
|
| B = 32
|
| for MODEL in MODELS:
|
| tok = AutoTokenizer.from_pretrained(MODEL)
|
| model = AutoModelForTokenClassification.from_pretrained(MODEL).cuda().eval()
|
| with torch.inference_mode():
|
| for i in range(0, len(ids), B):
|
| chunk = ids[i:i + B]
|
| wl = []
|
| for k in chunk:
|
|
|
|
|
|
|
|
|
|
|
|
|
| w = [x for x in str(base[k]).split() if x] or ["a"]
|
| wl.append([x.replace(",", "") or "a" for x in w])
|
| RAW[k] = w
|
| x = tok(wl, is_split_into_words=True, truncation=True, max_length=MAXLEN,
|
| padding=True, return_tensors="pt")
|
| xx = {kk: vv.cuda() for kk, vv in x.items()}
|
| p = torch.softmax(model(**xx).logits.float(), -1)[:, :, 1].cpu().numpy()
|
| for j, k in enumerate(chunk):
|
| wid = x.word_ids(j)
|
| prev, pr = None, {}
|
| for t, w in enumerate(wid):
|
| if w is not None and w != prev:
|
| pr[w] = float(p[j, t])
|
| prev = w
|
| WORDS[k] = wl[j]
|
| v = np.array([pr.get(n, 0.0) for n in range(len(wl[j]))])
|
| ACC[k] = v if k not in ACC else ACC[k] + v
|
| if (i + B) % 320 == 0:
|
| print(" %d/%d" % (i + B, len(ids)), flush=True)
|
| del model
|
| torch.cuda.empty_cache()
|
| print("modele %s note" % os.path.basename(MODEL.rstrip("/")), flush=True)
|
| for k in ACC:
|
| PROB[k] = ACC[k] / len(MODELS)
|
| print("probabilites moyennees sur %d modele(s)" % len(MODELS), flush=True)
|
|
|
| from huggingface_hub import HfApi
|
| api = HfApi(token=open(os.path.expanduser("~/.cache/huggingface/token")).read().strip())
|
| for th in THS:
|
| out, nins = dict(base), {"lin": 0, "sna": 0}
|
| ncl = {"lin": 0, "sna": 0}
|
| nchg = 0
|
| for k in ids:
|
| lg = lang.get(k, "lin")
|
| ncl[lg] = ncl.get(lg, 0) + 1
|
|
|
|
|
| w, p = list(RAW[k]), PROB[k]
|
|
|
|
|
|
|
|
|
| thl = th
|
| if th <= 1.0:
|
| if TH_LIN and lg == "lin":
|
| thl = float(TH_LIN)
|
| elif TH_SNA and lg == "sna":
|
| thl = float(TH_SNA)
|
| for n in range(min(len(w), len(p)) - 1):
|
| if p[n] >= thl and not w[n].endswith(","):
|
| w[n] = w[n] + ","
|
| nins[lg] = nins.get(lg, 0) + 1
|
| h = " ".join(w)
|
| if h != base[k]:
|
| nchg += 1
|
| out[k] = h
|
| empt = sum(1 for x in out.values() if not str(x).strip())
|
| tag = "%s%03d" % (TAG, round(th * 100))
|
| OUT = "/root/sub_%s.csv" % tag
|
| with open(OUT, "w", newline="", encoding="utf-8") as f:
|
| wr = csv.writer(f)
|
| wr.writerow(["ID", "Target"])
|
| for k in base:
|
| wr.writerow([k, out[k] or "a"])
|
| assert len(out) == 892 and empt == 0, "%s INVALIDE" % tag
|
| tl = sum(out[k].count(",") for k in ids if lang.get(k) == "lin")
|
| ts = sum(out[k].count(",") for k in ids if lang.get(k) == "sna")
|
| rl = tl / max(ncl["lin"], 1)
|
| rs = ts / max(ncl["sna"], 1)
|
| if th <= 1.0:
|
| api.upload_file(path_or_fileobj=OUT,
|
| path_in_repo="phase2_corrected/sub_%s.csv" % tag,
|
| repo_id="Pricile/waxal2026-backup", repo_type="model")
|
| flag = " <-- CONTROLE : doit etre 0" if th > 1.0 else ""
|
| print("%-8s seuil %.2f | clips modifies %3d/892 | virg/enonce lin %.2f (ref %.2f)"
|
| " sna %.2f (ref %.2f)%s"
|
| % (tag, th, nchg, rl, REF_RATE["lin"], rs, REF_RATE["sna"], flag), flush=True)
|
| print("APPLY_PUNCT_DONE", flush=True)
|
|
|
|
|
| if __name__ == "__main__":
|
| main()
|
|
|