Reconstruction de synonymes - énoncé#

Links: notebook, html, PDF, python, slides, GitHub

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.

from jyquickhelper import add_notebook_menu
add_notebook_menu()

Construction de la base de synonymes#

from actuariat_python.data import wolf_xml
wolf_xml()
['.\wolf-1.0b4.xml.', 'debvisdic-strict.dtd']
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))
from actuariat_python.data import enumerate_wolf_synonyms
for syn in enumerate_wolf_synonyms("wolf-1.0b4.xml", errors="ignore"):
    print(syn)
    break
['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.

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)
line 0 allsyn 0
10002

On affiche les premiers groupes :

i = 0
for k, v in allsyn.items():
    print(k,v)
    i += 1
    if i > 10:
        break
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.

import urllib.request
with urllib.request.urlopen("http://www.gutenberg.org/cache/epub/4647/pg4647.txt") as u:
    content = u.read()
char = content.decode(encoding="utf-8")

On découpe en mot.

import re
reg = re.compile("([- a-zA-Zâàäéèëêîïôöùûü']+)")
phrases = [_.lower() for _ in reg.findall(char)]
for i, phrase in enumerate(phrases):
    if i >= 990:
        print(phrase)
    if i >= 1000:
        break
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 :

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)
[['vibrer', 'le', 'intellectuel'],
 ['chatouiller', 'le', 'obscur'],
 ['chatouiller', 'le', 'intellectuel'],
 ['chatouiller', 'le', 'ésotérique'],
 ['chatouiller', 'le', 'cérébral']]

On traite tous les mots :

len(phrases)
7099
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
('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.

from pyensae.datasource import download_data
download_data("zadig_augmente.zip")
['zadig_augmente.txt']