#!/usr/bin/env python3 """CALIBRATION DE LA CASSE ET DU POINT FINAL, cote LINGALA uniquement. Fait mesure (recherche du 6 aout, 14 400 segments de reference) : reference notre sortie majuscule initiale 75,5 % 89,2 % point final 67,2 % 88,1 % (shona : 99,6/95,1 -> 99,3/99,8 = parfaitement calibre, on n'y touche pas) Le modele reproduit le taux quand il est EXTREME (shona) et SUR-TIRE quand il est INTERMEDIAIRE (lingala) : signature d'une decision prise sans information par item. Coherent avec le fait que casse et ponctuation sont un trait de l'ANNOTATEUR : variance inter-locuteurs 30x l'i.i.d., correlation r=0,93 entre les deux traits au niveau du locuteur. Sur des locuteurs INEDITS (le test), le modele acoustique ne peut structurellement pas savoir. Theorie de la decision : si la decision ne porte AUCUNE information, minimiser l'erreur attendue impose de toujours choisir la CLASSE MAJORITAIRE, pas de reproduire le taux de base. casse : p=0,755 -> toujours majuscule. Erreur 0,300 -> 0,245 (gain 5,5 pts) point : p=0,672 -> toujours un point. Erreur 0,369 -> 0,328 (gain 4,1 pts) Sur 446 clips lingala : ~42 clips corriges, ~+0,0010 de metrique. Si au contraire la decision EST informative, ce sera negatif -- c'est la soumission qui tranche. """ import csv, json, os BASE = "/root/sub_SNAW06.csv" # meilleure soumission connue (0.761213149) lang = json.load(open("/root/test_lang.json")) base = {r["ID"]: r["Target"] for r in csv.DictReader(open(BASE, encoding="utf-8"))} END = (".", "!", "?") def force_upper(t): return t[:1].upper() + t[1:] if t else t def force_period(t): t = t.rstrip() return t if (not t or t.endswith(END)) else t + "." VARIANTS = [ ("CALIBU", True, False, "majuscule initiale forcee (89,2 % -> 100 %)"), ("CALIBP", False, True, "point final force (88,1 % -> 100 %)"), ("CALIBUP", True, True, "les deux"), ] # etat de depart, pour verification lin_ids = [k for k in base if lang.get(k) == "lin"] sna_ids = [k for k in base if lang.get(k) == "sna"] u0 = sum(1 for k in lin_ids if base[k][:1].isupper()) / len(lin_ids) p0 = sum(1 for k in lin_ids if base[k].rstrip().endswith(END)) / len(lin_ids) us = sum(1 for k in sna_ids if base[k][:1].isupper()) / len(sna_ids) ps = sum(1 for k in sna_ids if base[k].rstrip().endswith(END)) / len(sna_ids) print("depart %s :" % os.path.basename(BASE), flush=True) print(" lin majuscule %.1f %% point final %.1f %% (references : 75,5 / 67,2)" % (100 * u0, 100 * p0), flush=True) print(" sna majuscule %.1f %% point final %.1f %% (references : 99,6 / 95,1 -> on n'y touche pas)" % (100 * us, 100 * ps), flush=True) from huggingface_hub import HfApi api = HfApi(token=open(os.path.expanduser("~/.cache/huggingface/token")).read().strip()) for tag, do_u, do_p, why in VARIANTS: out = dict(base) nchg = 0 for k in lin_ids: t = base[k] if do_u: t = force_upper(t) if do_p: t = force_period(t) if t != base[k]: nchg += 1 out[k] = t empt = sum(1 for x in out.values() if not str(x).strip()) dsna = sum(1 for k in sna_ids if out[k] != base[k]) OUT = "/root/sub_%s.csv" % tag with open(OUT, "w", newline="", encoding="utf-8") as f: w = csv.writer(f) w.writerow(["ID", "Target"]) for k in base: w.writerow([k, out[k] or "a"]) assert len(out) == 892 and empt == 0 and dsna == 0, "%s INVALIDE" % tag api.upload_file(path_or_fileobj=OUT, path_in_repo="phase2_corrected/sub_%s.csv" % tag, repo_id="Pricile/waxal2026-backup", repo_type="model") nu = sum(1 for k in lin_ids if out[k][:1].isupper()) / len(lin_ids) np_ = sum(1 for k in lin_ids if out[k].rstrip().endswith(END)) / len(lin_ids) print("%-8s %-42s lin modifies %3d/446 | maj %.1f %% point %.1f %% | sna 0 | vides 0" % (tag, why, nchg, 100 * nu, 100 * np_), flush=True) print("CALIB_DONE", flush=True)