.. _reconstructionsynonymesenoncerst: ==================================== Reconstruction de synonymes - énoncé ==================================== .. only:: html **Links:** :download:`notebook `, :downloadlink:`html `, :download:`PDF `, :download:`python `, :downloadlink:`slides `, :githublink:`GitHub|_doc/notebooks/nlp/reconstruction_synonymes_enonce.ipynb|*` Ce notebook est plus un jeu. On récupère d’abord des synonymes via la base `WOLF `__. On ne garde que les synonymes composé d’un seul mot. On prend ensuite un texte quelconque qu’on découpe en phrase. Pour chaque phrase qu’on rencontre, on remplace des mots au hasard par leur synonymes. Chaque phrase sera présente une fois à l’identique et plusieurs fois avec des synonymes différents. L’objectif est alors de proposer une méthode pour reconstruire la base de synonymes. .. code:: ipython3 from jyquickhelper import add_notebook_menu add_notebook_menu() .. contents:: :local: Construction de la base de synonymes ------------------------------------ .. code:: ipython3 from actuariat_python.data import wolf_xml wolf_xml() .. parsed-literal:: ['.\\wolf-1.0b4.xml.', 'debvisdic-strict.dtd'] .. code:: ipython3 import os if not os.path.exists("wolf-1.0b4.xml"): raise FileNotFoundError("wolf-1.0b4.xml") if os.stat("wolf-1.0b4.xml").st_size < 3000000: raise FileNotFoundError("Size of 'wolf-1.0b4.xml' is very small: {0}".format(os.stat("wolf-1.0b4.xml").st_size)) .. code:: ipython3 from actuariat_python.data import enumerate_wolf_synonyms for syn in enumerate_wolf_synonyms("wolf-1.0b4.xml", errors="ignore"): print(syn) break .. parsed-literal:: ['respirer', 'inspirer'] On passe en revue toute la basse (il y a environ 120.000 lignes) et on s’arrête après 10000 synonymes car sinon, cela prend un temps fou. .. code:: ipython3 allsyn = {} for line, syn in enumerate(enumerate_wolf_synonyms("wolf-1.0b4.xml")): if line % 10000 == 0: print("line", line, "allsyn", len(allsyn)) clean = [_.lower() for _ in syn if " " not in _] if len(clean) > 1: for word in clean: if word not in allsyn: allsyn[word] = set(clean) continue else: for cl in clean: allsyn[word].add(cl) if len(allsyn) > 10000: break len(allsyn) .. parsed-literal:: line 0 allsyn 0 .. parsed-literal:: 10002 On affiche les premiers groupes : .. code:: ipython3 i = 0 for k, v in allsyn.items(): print(k,v) i += 1 if i > 10: break .. parsed-literal:: commerciable {'commercialisable', 'commerciable'} réformer {'corriger', 'rectifier', 'amender', 'remédier', 'libérer', 'améliorer', 'délivrer', 'réformer'} herbe {'voile', 'croisière', 'herbe'} bancal {'vacillant', 'vieux', 'branlant', 'délabré', 'chambranlant', 'bancal', 'caduc', 'chancelant', 'boiteux'} querelle {'différend', 'dispute', 'querelle', 'litige', 'contravention'} explicitement {'clairement', 'explicitement', 'évidemment', 'univoquement'} extraconjugal {'adultère', 'extraconjugal'} méticuleusement {'méticuleusement', 'soigneusement'} épaulé-jeté {'propre', 'épaulé-jeté', 'pur'} arcade {'arcade', 'arc'} majoritairement {'primordialement', 'majoritairement'} Génération d’une base de phrases modifiées ------------------------------------------ On utilise `Zadig `__. .. code:: ipython3 import urllib.request with urllib.request.urlopen("http://www.gutenberg.org/cache/epub/4647/pg4647.txt") as u: content = u.read() .. code:: ipython3 char = content.decode(encoding="utf-8") On découpe en mot. .. code:: ipython3 import re reg = re.compile("([- a-zA-Zâàäéèëêîïôöùûü']+)") phrases = [_.lower() for _ in reg.findall(char)] .. code:: ipython3 for i, phrase in enumerate(phrases): if i >= 990: print(phrase) if i >= 1000: break .. parsed-literal:: desterham il parla en ces termes toiles de justice abîmes de science miroirs de vérité qui avez la pesanteur du plomb la dureté du fer l'éclat du diamant et beaucoup d'affinité avec l'or puisqu'il m'est permis de On génère les phrases modifiées : .. code:: ipython3 import random def modification(phrase, allsyn, nmax=10): mots = phrase.split() options = [] nb = 1 for mot in mots: if mot in allsyn: options.append(list(set([mot] + list(allsyn[mot])))) else: options.append([mot]) nb *= len(options[-1]) if nb == 1: return [phrase] else: res = [] for i in range(0, min(nmax, nb//2+1, nb)): sol = [] for mot in options: h = random.randint(0, len(mot)-1) sol.append(mot[h]) res.append(sol) return res modification("chatouiller le cérébral", allsyn) .. parsed-literal:: [['vibrer', 'le', 'intellectuel'], ['chatouiller', 'le', 'obscur'], ['chatouiller', 'le', 'intellectuel'], ['chatouiller', 'le', 'ésotérique'], ['chatouiller', 'le', 'cérébral']] On traite tous les mots : .. code:: ipython3 len(phrases) .. parsed-literal:: 7099 .. code:: ipython3 with open("zadig_augmente.txt", "w", encoding="utf-8") as f: total = 0 init = 0 for i, phrase in enumerate(phrases): augm = modification(phrase, allsyn) init += 1 for au in augm: f.write(" ".join(au) + "\n") total += 1 "total", total, "initial", init .. parsed-literal:: ('total', 32358, 'initial', 7099) Exercice : retrouver une partie des synonymes à partir du dernier fichier créé ------------------------------------------------------------------------------ Le fichier utilisé peut être généré à partir du code précédent ou utiliser cette version : `zadig_augmente.zip `__. .. code:: ipython3 from pyensae.datasource import download_data download_data("zadig_augmente.zip") .. parsed-literal:: ['zadig_augmente.txt']