mercredi 27 août 2025

fleur + œuf = ?

 Pollen, éclosion, bourgeon, pistil sont des réponses possibles.

Dans cet article, nous allons explorer un algorithme capable de répondre à ce type d’analogie : fleur + œuf = ?

Bien sûr, on pourrait imaginer utiliser notre graphe sémantique pour tenter une réponse. On chercherait tous les mots liés à fleur, puis parmi eux ceux également liés à œuf. Et, dans ce cas simple… ça fonctionne.

Mais essayez plutôt avec : nébuleuse + tuyauterie = ?
Là, le graphe ne renvoie probablement rien, aucun mot ne relie directement ces deux concepts.

Word2Vec

Word2Vec est un outil introduit en 2013 par une équipe de Google Research. Son objectif : donner une représentation mathématique aux relations sémantiques entre les mots.

Pour faire simple, on peut voir cet algorithme comme une boîte noire : on lui fournit du texte en entrée (beaucoup de texte, ce qu’on appelle un corpus), il “digère” tout ça, et nous renvoie, en sortie… des vecteurs de mots.

Comme son nom l’indique : Word -> Vector.

Concrètement, pour chaque mot apparaissant dans le corpus, l’algorithme calcule un vecteur : autrement dit, des coordonnées dans un espace (généralement entre 25 et 1000 dimensions). Ces vecteurs reflètent les proximités sémantiques entre mots. Deux mots proches dans l’espace auront des sens similaires.

Visualisation du modèle Word2Vec entraîné sur Lexiflaire. Elle a été réalisée à l’aide de Embedding Projector, un outil proposé par TensorFlow pour explorer les représentations vectorielles de mots.


Ce que Word2Vec apporte

Prenons deux mots : panthère et guépard.
Imaginons qu’ils ne soient jamais liés dans notre graphe sémantique, c’est-à-dire qu’ils n’apparaissent jamais dans les mêmes parties de Lexiflaire.
Dans ce cas, aucun lien ne les relie dans le graphe. Pourtant, leur proximité sémantique est évidente.

Avec Word2Vec, même si ces deux mots n'ont jamais été utilisés ensemble, leur distance géométrique sera faible, c’est-à-dire qu’ils seront proches dans l’espace vectoriel.

Mais comment est-ce possible ?

Parce que Word2Vec ne regarde pas uniquement les mots eux-mêmes, mais aussi leur contexte d’apparition.
Un contexte, c’est simplement les mots qui entourent un mot donné dans une phrase du corpus.

Exemple :

“La panthère est un félin vivant dans la savane.”
Une fois lemmatisé et nettoyé (on retire les déterminants, les auxiliaires, etc.), on obtient un contexte pour panthère :
    "félin", "vivre", "savane"

Autre exemple :

“Le guépard est un félin très rapide.”
Contexte pour guépard :
    "félin", "rapide"

Même s’ils n’apparaissent jamais ensemble, leurs contextes sont similaires.
Et Word2Vec apprend justement à rapprocher dans l’espace vectoriel les mots qui partagent des contextes similaires.

C’est toute la force de cet outil : créer des liens implicites, là où un graphe est fondé uniquement sur les cooccurrences.

Un outil largement utilisé

Dans le monde du traitement automatique du langage (NLP), Word2Vec est devenu un outil de base.
Il est utilisé dans une multitude de tâches : classification de texte, recherche d’information, détection de similarités, recommandation, clustering thématique, etc.

La plupart du temps, on ne l’entraîne pas soi-même.
On utilise un modèle pré-entraîné sur un très grand corpus (comme Wikipedia, Google News ou Common Crawl).

Ces modèles pré-entraînés sont performants pour de nombreuses tâches.
Mais pourquoi ne pas tenter d’en entraîner un à partir des parties de Lexiflaire ?

J’avoue que je ne m’attendais pas à grand-chose : les données de Lexiflaire représentent environ 1 Go de texte, contre plusieurs téraoctets pour Wikipedia en français…
Seul point fort : avec un corpus de cette taille, nul besoin d’un supercalculateur pour entraîner le modèle.

Entraînement du modèle

Dans le cas de Wikipedia, le corpus est généralement découpé en phrases, avec une fenêtre glissante autour de chaque mot.
Pour Lexiflaire, chaque paire indice/réponse formera une phrase indépendante (comme pour le graphe). Les contextes générés seront donc courts, directs et très spécifiques :

"panthère félin", "pétale fleur", etc.

On va simplement prendre chacune de ces “phrases” et en mettre une par ligne dans un fichier texte.
On obtient ainsi un corpus d’un peu plus de 1 Go.

Ensuite, il suffit de fournir ce corpus à la boîte noire… mais avec pas mal de réglages.
Je ne vais pas entrer dans tous les détails, mais un point important : les mots ne sont pas directement utilisés. Ce sont plutôt les n-grams (fragments de mots) qui composent chaque mot qui sont pris en compte.

Par exemple, les trigrammes (3-grams) du mot guépard sont :
    "gue", "uep", "epa", "par" et "ard".
Les vecteurs sont calculés pour chaque n-gramme, puis, pour chaque mot, on fait la moyenne des vecteurs de ses fragments.

Ce paramètre du choix des tailles de n-grams (par exemple 3 à 6) est particulièrement pertinent en français.
En effet, les mots proches partagent souvent une même racine, donc des n-grams communs.
Prenons "chevalier" et "chevaleresque". Ce dernier apparaît très peu dans le corpus Lexiflaire, mais grâce à ses n-grams ("che", "chev", "val", etc.), il bénéficie des nombreuses occurrences de chevalier.

Autre réglage important : le nombre de dimensions.


Dans la visualisation présentée plus haut, on ne voit que 3 dimensions (parce qu’au-delà… on ne peut tout simplement plus visualiser). Mais le modèle, lui, n’est pas limité à 3 dimensions.

Si on choisit 10 dimensions, la boîte noire va transformer chaque mot en un vecteur de 10 nombres.
Si on choisit 1000 dimensions, ce seront 1000 valeurs numériques pour représenter chaque mot.

Voici un extrait du modèle avec seulement 6 dimensions :

statique   -0.73778   0.50441  -0.21488   0.15321  -0.31619  -0.52623  

parapluie   0.00956   0.50678  -0.25292   0.60919   0.06999  -1.10530  

câlin       0.09283   0.38353   0.81148  -0.70804   0.36993  -0.26235  

dentition   0.30206  -0.44172   0.06199  -0.16386   1.18450   0.50103  

entailler   0.20181   0.52643   0.02855   0.51429   0.16853  -0.13925  

Chaque ligne représente un mot, et chaque colonne une coordonnée dans l’espace sémantique.
Ici, on n’a pas seulement des dimensions X, Y et Z… mais U, V, W, X, Y, Z.

Et que l’on ait 3 dimensions, 6 ou 1000, cela ne change rien à la logique :
on peut toujours calculer une distance ou un angle entre deux mots.

Par exemple, une distance en 2 dimensions, c’est le bon vieux Pythagore :
    d = √(x² + y²)

Avec nos 6 dimensions, on applique simplement la même formule :
    d = √(u² + v² + w² + x² + y² + z²)

Et avec 300 dimensions ? Pareil. Juste un peu plus de patience et un bon CPU.

Mais à quoi correspondent ces "dimensions" ?

Ces dimensions sont apprises automatiquement par l’algorithme via des calculs mathématiques complexes. Contrairement à un questionnaire où chaque question mesure un trait précis (âge, taille, etc.), ici, les dimensions n’ont pas de signification explicite et directe.

Pour autant, ces dimensions portent quand même du sens. Prenons une expérience de pensée :

Imaginons qu’une des dimensions encode le concept de température. Le mot chaud aurait une valeur proche de +1, froid une valeur proche de -1, tandis que des mots sans lien direct comme table ou voiture seraient proches de 0 sur cette dimension.

En réalité, aucune dimension ne représente strictement un concept unique comme la température. Chaque dimension est plutôt un mélange complexe et chaotique, par exemple :
dimension 1 = 0.5 × concept(température) - 0.2 × (concept cinéma ou astronomie) + 0.3 × concept(animaux sauvages), etc.

Mais cette représentation vectorielle permet malgré tout de mesurer la proximité sémantique entre deux mots : plus leurs vecteurs sont proches dans cet espace multidimensionnel, plus leur signification est proche dans le langage.

Donc, comment choisir le nombre de dimensions ?

Les modèles entraînés sur Wikipedia comptent généralement au moins 300 dimensions, qui est le minimum pour bien capter les nuances sémantiques dans un corpus aussi massif.

Alors, plus il y a de dimensions, mieux c’est ? Pas forcément.

Un nombre trop élevé de dimensions peut entraîner un surapprentissage : dans ce cas, chaque mot finit par avoir une proximité sémantique faible avec presque tous les autres mots, ce qui réduit la qualité des distinctions.

À l’inverse, avec trop peu de dimensions, on risque d’avoir beaucoup d’incohérences et de perdre des subtilités importantes. Finalement, le mieux reste d’entraîner plusieurs modèles de différentes dimensions, puis d’estimer empiriquement lequel est le plus performant.

Rang m25 (25 dims) Score m50 (50 dims) Score m100 (100 dims) Score
0 guépard 1.00 guépard 1.00 guépard 1.00
1 léopard 0.98 léopard 0.97 léopard 0.93
2 jaguar 0.92 jaguar 0.93 jaguar 0.85
3 puma 0.91 puma 0.90 panthère 0.85
4 zèbre 0.91 panthère 0.90 tigre 0.84
5 félin 0.90 tigre 0.87 félin 0.81
6 ocelot 0.90 léopardé 0.86 puma 0.81
7 tigre 0.90 félin 0.85 léopardé 0.81
8 panthère 0.88 lynx 0.83 lion 0.77
9 fauve 0.86 tigré 0.82 lynx 0.73
10 tigré 0.86 lion 0.81 gazelle 0.73
11 gazelle 0.85 zèbre 0.81 antilope 0.73
12 antilope 0.85 fauve 0.79 tigré 0.72
13 léopardé 0.85 gazelle 0.79 fauve 0.71
14 lynx 0.85 antilope 0.79 hyène 0.68
15 futé 0.85 couguar 0.78 couguar 0.68
16 impala 0.84 hyène 0.74 ocelot 0.66
17 félidé 0.83 ocelot 0.73 zèbre 0.66
18 couguar 0.82 phéniqué 0.72 sportswear 0.65
19 lion 0.81 félidé 0.72 impala 0.64
20 tacheter 0.81 impala 0.72 félinité 0.64
21 zébu 0.80 tacheter 0.71 lièvre 0.63
22 félinité 0.80 coyote 0.69 félidé 0.62
23 serval 0.80 zébu 0.69 phacochère 0.62
24 castor 0.78 chacal 0.68 coyote 0.62
25 kényan 0.78 mustang 0.68 fennec 0.62
26 wombat 0.78 ferrari 0.67 chacal 0.62
27 renard 0.78 félinité 0.67 phéniqué 0.61
28 gnou 0.77 lionceau 0.67 roussâtre 0.60
29 dalmatien 0.77 gavial 0.66 buffle 0.60
30 okapi 0.77 roussâtre 0.66 isatis 0.60
31 isard 0.77 guêper 0.66 girafe 0.59
32 prédateur 0.77 gnou 0.66 caracal 0.59
33 orang-outang 0.77 kényan 0.66 serval 0.59
34 coyote 0.76 féroce 0.66 crocodile 0.59
35 quiétiste 0.76 wombat 0.66 férocité 0.59
36 mustang 0.76 fennec 0.65 renard 0.59
37 roussâtre 0.76 couard 0.65 babiroussa 0.59
38 linga 0.76 ricanant 0.65 tigrer 0.59
39 buffle 0.76 jenny 0.65 flamand 0.58
40 legato 0.75 férocité 0.65 lionceau 0.58
41 savane 0.75 lémurien 0.65 poursuiveur 0.58
42 semi-aride 0.75 prédateur 0.65 flamant 0.58
43 sauvagin 0.75 girafe 0.65 sanglier 0.58
44 fiat 0.75 dalmatien 0.65 zébu 0.58
45 pur-sang 0.74 poursuiveur 0.64 biche 0.57
46 tigrer 0.74 savane 0.64 suricate 0.57
47 traqueur 0.74 semi-aride 0.64 sauvagesse 0.57
48 féroce 0.74 biche 0.64 ferrari 0.57
49 animal 0.74 proie 0.64 hippopotame 0.57
50 martre 0.73 chat 0.64 gnou 0.57

Ici, nous avons les 50 mots les plus proches de « guépard » selon trois modèles entraînés avec 25, 50 et 100 dimensions. Analysons ces résultats.

Pour commencer, les "scores" correspondent à la similaritée cosinus. C'est à dire au cosinus de l'angle entre le vecteur "guépard" et les autres vecteurs du modèle.

Pour les trois modèles, le mot « guépard » obtient une similarité parfaite avec lui-même (1,00), ce qui est attendu (cos(0)=1.0). Les mots les plus proches — léopard, jaguar, puma, félin, tigre, panthère — apparaissent systématiquement dans le top 10.

Le modèle à 25 dimensions attribue globalement des scores plus élevés (plus proches de 1) aux mots les plus similaires. Celui à 50 dimensions introduit davantage de variations dans les similarités, avec des scores légèrement plus faibles pour certains mots. Enfin, le modèle à 100 dimensions présente des similarités globalement plus basses, mais une plus grande diversité dans les mots voisins, avec des termes attendus comme « panthère », « tigre », « lion », « hyène », ainsi que quelques mots moins attendus tels que « sportswear » ou « ferrari ».

On observe aussi que certains mots changent de position selon la dimension. Par exemple, « panthère » est en 8e position dans le modèle à 25 dimensions, mais remonte à la 3e ou 4e place dans les modèles à 50 et 100 dimensions. Des mots comme « félin » ou « tigre » varient également sensiblement dans leur classement et leur score.

« Guépard » n’est pas forcément le meilleur exemple, et en réalité il n’y en a pas de parfait. J’ai dû examiner les résultats de plusieurs modèles aux dimensions variées (jusqu’à 300) et pour différents mots, fréquents, rares, avec des concepts larges ou spécifiques. J’en suis, pour le moment, arrivé à la conclusion que le modèle à 100 dimensions offrait un bon compromis.

Maintenant comparons le model a 100 dimensions entrainé avec les données de Lexiflaire et un model a 500 dimensions entrainé avec un corpus wikipedia :

#mWikiScorem100Score
0guépard1.00guépard1.00
1hyène0.67léopard0.93
2lycaon0.65jaguar0.85
3antilope0.65panthère0.85
4phacochère0.63tigre0.84
5caracal0.62félin0.81
6léopard0.62puma0.81
7gnou0.60léopardé0.81
8impala0.60lion0.77
9gazelle0.58lynx0.73
10girafe0.57gazelle0.73
11oryx0.56antilope0.73
12félin0.55tigré0.72
13rhinocéros0.54fauve0.71
14ocelot0.54hyène0.68
15babouin0.54couguar0.68
16puma0.54ocelot0.66
17bubale0.53zèbre0.66
18zèbre0.51sportswear0.65
19panthère0.51impala0.64
20lion0.51félinité0.64
21suricate0.51lièvre0.63
22hippopotame0.50félidé0.62
23félidé0.50phacochère0.62
24buffle0.47coyote0.62
25mangouste0.47fennec0.62
26fennec0.46chacal0.62
27chacal0.46phéniqué0.61
28lynx0.45roussâtre0.60
29lionceau0.45buffle0.60
30pangolin0.43isatis0.60
31tigre0.43girafe0.59
32varan0.43caracal0.59
33éléphant0.42serval0.59
34autruche0.41crocodile0.59
35zoo0.41férocité0.59
36braconnage0.40renard0.59
37crinière0.40babiroussa0.59
38carnivore0.40tigrer0.59
39cercopithèque0.40flamand0.58
40mustélidé0.40lionceau0.58
41coati0.40poursuiveur0.58
42daim0.40flamant0.58
43nandou0.40sanglier0.58
44crocodile0.40zébu0.58
45jaguar0.40biche0.57
46harnacher0.40suricate0.57
47pécari0.39sauvagesse0.57
48tapir0.39ferrari0.57
49lamantin0.39hippopotame0.57
50guanaco0.39gnou0.57



On peut noter que le modèle Wikipédia est cohérent (ce qui est attendu), mais avec des scores de similarité sémantique globalement plus faibles. Les mots les plus proches sont aussi différents. Des termes plus encyclopédiques apparaissent rapidement, comme lycaon ou oryx, deux mots absents du modèle Lexiflaire (enfin, lycaon est bien là, mais au-delà de la 200e place).

Le modèle Lexiflaire met surtout en avant d'autres félins dans son top 50, là où le modèle Wikipédia associe aussi des éléments liés à l’environnement du guépard. Par exemple, on trouve crinière et braconnage vers la 37e place. Ces deux mots sont également présents dans le modèle Lexiflaire, mais plus loin : crinière est en position 107 et braconnage en 162. 

Les deux modèles sont donc cohérents, et c’est satisfaisant de voir qu’un modèle entraîné avec les parties de Lexiflaire s’en sort plutôt bien face à un modèle formé sur Wikipédia. Ce n’était pas gagné, vu la différence de taille entre les deux corpus.

Voyons maintenant un autre exemple, avec un mot moins courant et moins spécifique qu’un animal : usurpation.
Ce genre de concept abstrait est un bon test pour les modèles sémantiques. Moins d’images concrètes, moins de cooccurrences directes, et des contextes plus flous… Les différences entre modèles devraient y être plus visibles.


#mWikiScorem100Score
0usurpation1.00usurpation1.00
1usurper0.56usurper0.80
2usurpateur0.45prête-nom0.71
3légitime0.38falsifier0.70
4compte0.35imposture0.70
5anonymat0.35falsification0.69
6coempereur0.34usurpateur0.69
7frauduleux0.32faussaire0.67
8identité0.32truandage0.66
9confirmation0.31fraude0.65
10légitimité0.31contrefaçon0.64
11soupçon0.30escroquerie0.64
12prétendre0.29plagier0.64
13bureaucrate0.29spoliation0.64
14faux0.29escroquer0.62
15empereur0.29appropriation0.62
16banni0.29tricherie0.62
17abus0.29subtiliser0.62
18arroger0.29identité0.61
19adresse0.29contrefaire0.61
20honorius0.29imposteur0.61
21falsifier0.29dérober0.60
22conspirer0.29approprier0.60
23raison0.28arnaque0.60
24comploter0.28emparer0.60
25bannir0.28plagiat0.59
26requête0.28contrefait0.59
27fâcheux0.28contrebande0.59
28e-mail0.28recel0.59
29steward0.27truquage0.58
30bannissement0.27imposte0.58
31authentifier0.27frauduleux0.58
32intéressé0.27duperie0.58
33énième0.27grivèlerie0.58
34répréhensible0.27tromperie0.57
35vandale0.27arnaquer0.57
36dissimulation0.27subornation0.57
37trône0.27fausser0.57
38malveillant0.27transgression0.56
39indélicat0.27plagiaire0.56
40mail0.27extorsion0.56
41falsification0.27transgresseur0.56
42wiki0.27truanderie0.56
43révolter0.26brigandage0.56
44prétoire0.26violation0.55
45piratage0.26truander0.55
46dioclétien0.26imiter0.55
47exarque0.26mystification0.55
48reconnecter0.26extorquer0.55
49sédition0.26illégalité0.55
50abuser0.26supercherie0.55


Ici, on observe nettement le côté encyclopédique du modèle Wikipedia, avec des mots comme Dioclétien, Honorius ou coempereur, des termes cohérents historiquement mais qui peuvent sembler flous. En revanche, le modèle Lexiflaire est clairement centré sur le champ lexical de la fraude, du plagiat et de la contrefaçon.

Mais à quoi peut bien servir le modèle Lexiflaire ?
Ce modèle permet notamment de compléter le graphe sémantique, qui peut parfois être parcellaire ou trop structuré autour des cooccurrences. Une des applications, dont nous parlerons dans un prochain article, est la détection de thématiques dans le vocabulaire de Lexiflaire. Et bien sûr, il sert aussi à créer un robot capable de jouer à Lexiflaire

Le modèle ne se limite pas à donner les mots les plus proches dans l’espace sémantique : il permet également de faire des opérations sémantiques, autrement dit de manipuler les concepts de manière vectorielle.Dans le cadre d’une partie de Lexiflaire, on peut par exemple rencontrer trois indices et deux mauvaises réponses proposées par le joueur :

Indices : félin, savane, rapide
Réponses du joueur : chat, lion

À partir de là, on peut construire une opération sémantique sous forme vectorielle, en combinant les indices et en soustrayant les mauvaises réponses :
    félin + savane + rapidechatlion

On peut même pondérer chaque terme selon son importance perçue :
    2 × félin + 1 × savane + 0.5 × rapide − 1 × chat − 0.5 × lion

Ce type de manipulation vectorielle est particulièrement utile dans le cadre d’un robot jouant à Lexiflaire, pour générer de nouveaux indices pertinents à partir du contexte de la partie.

Voici le résultat pour cette "équation" : 

#mWikiScorem100Score
0félin0.73félin0.81
1savane0.60savane0.78
2guépard0.46guépard0.73
3ocelot0.44léopard0.69
4félidé0.40félidé0.69
5puma0.39fauve0.69
6carnivore0.37tigre0.68
7antilope0.37jaguar0.68
8herbeux0.37gazelle0.68
9aride0.37semi-aride0.67
10broussaille0.37panthère0.65

Pour fleur + oeuf :

#mWikiScorem100Score
0fleur0.75fleur0.81
1oeuf0.75oeuf0.81
2pondre0.51fleurs0.72
3fleurir0.50éclore0.71
4faner0.49fleurir0.70
5éclore0.49marguerite0.69
6pétale0.48plante0.67
7polliniser0.47bourgeon0.66
8floraison0.47liliacé0.65
9tépale0.44pétale0.65

Ou encore pour tuyauterie + nébuleuse...

#mWikiScorem100Score
0nébuleuse0.72tuyauterie0.79
1tuyauterie0.72nébuleuse0.79
2nébuleux0.60canalisation0.76
3amas0.50plomberie0.71
4messier0.47tuyautage0.69
5constellation0.46nébuleux0.68
6extragalactique0.46tuyau0.66
7ophiuchus0.45égout0.65
8globulaire0.45tuyère0.65
9tuyau0.45robinetterie0.65

lundi 9 juin 2025

Génération de graphe sémantique

 

Visualisation d'un graphe sémantique. (moteur maison golang/ebitengine)

Pour commencer… qu’est-ce qu’un graphe ?

Un graphe, c’est une structure de données composée de nœuds (aussi appelés sommets), reliés entre eux par des liens (ou arêtes).
C’est une structure très souple, qui permet de modéliser à peu près n’importe quel type de relation entre des éléments.
Dans bien des cas, structurer les données sous forme de graphe serait inutile ou excessif… mais dans d’autres, c’est un outil efficace.

Parmi les exemples les plus connus, on trouve les graphes sociaux, qui ont explosé avec l’essor des réseaux du même nom.
Dans un graphe social, chaque nœud représente une personne (ou plus exactement, un compte utilisateur sur un réseau).
Les plateformes les plus populaires comptent des millions, voire des milliards de nœuds.
Si deux personnes sont "amies", on trace un lien entre leurs deux nœuds.

Bob et Alice ont chacun un compte sur le réseau : ils sont donc représentés chacun par un sommet (ou nœud) dans le graphe. Comme Bob et Alice sont amis, on trace un lien (arête) entre leurs sommets respectifs. On répète cette opération pour chaque paire d’amis sur le réseau… ce qui donne un graphe massif, à l’image de la taille du réseau social.

(Bob) <--> (Alice)

Graphe sémantique

Ok pour les graphes sociaux, mais quel rapport avec Lexiflaire, les mots, la sémantique ?

On peut appliquer le même principe, mais cette fois, chaque sommet correspond à un mot (ou, comme on l’a vu dans l’article précédent, à un lemme), et chaque lien représente une similarité entre deux mots.

On peut imaginer qu’un mot sera relié à ses synonymes, à ses antonymes, ou à d’autres mots appartenant au même champ lexical.
Par exemple, roue sera lié à pneu, chaud à froid, ou encore locomotive à wagon.

Dans les graphes sociaux, les liens sont simples : si deux sommets sont amis, il y a un lien ; sinon, il n’y en a pas.

Dans le cas de notre graphe sémantique, c’est plus nuancé. Certains liens sont plus forts que d’autres.
Chaque lien a un poids mesurable, généralement exprimé entre 0 et 1 (ou en pourcentage).
Visuellement, un lien plus fort pourra être représenté par une ligne plus épaisse.

Par exemple, le lien entre rail et train sera — on peut l’imaginer — très fort, disons 80 %.
Le lien entre rail et wagon existera aussi, mais sera plus faible, peut-être autour de 50 %.



Et on construit ça comment ?

Repartons de la base : une partie de Lexiflaire.

Mot à deviner : wagon
Indice 1 : locomotive
Réponse 1 : train
Indice 2 : remorque
Réponse 2 : wagon

On va prendre chaque paire indice / réponse, les lemmatiser, les ajouter au graphe si les sommets correspondants n’existent pas encore, et créer un lien entre eux s’il n’existe pas déjà.

Pour chaque sommet, on enregistre le nombre d’occurrences (combien de fois ce mot apparaît dans une partie).
Pour chaque lien, on enregistre le nombre de cooccurrences (combien de fois ces deux mots ont été associés dans une paire).

Mais on ne s’arrête pas là.

La réponse wagon ne dépend pas uniquement de l’indice remorque, mais aussi du contexte donné par l’indice précédent, locomotive.
On va donc créer un lien supplémentaire entre locomotive et wagon : un lien plus indirect, mais pertinent.

En revanche, train et remorque n’ont pas nécessairement de lien, car la réponse train a été donnée avant l’apparition de l’indice remorque, donc aucune raison de créer un lien entre eux.

Avec uniquement cette partie :

  • Sommet locomotive = 1

  • Sommet train = 1

  • Sommet remorque = 1

  • Sommet wagon = 1

  • Lien locomotive – train = 1

  • Lien remorque – wagon = 1

  • Lien locomotive – wagon = 1

Continuons le processus, mais cette fois en prenant en compte l’ensemble des parties jouées dans Lexiflaire.
Que donnent les comptages globaux pour nos sommets et nos liens ?

  • Sommet locomotive = 21 972

  • Sommet train = 72 314

  • Sommet remorque = 12 627

  • Sommet wagon = 25 797

  • Lien locomotive – train = 9376

  • Lien remorque – wagon = 103

  • Lien locomotive – wagon = 2730

Comme on peut le constater, le nombre d’occurrences d’un sommet est bien supérieur au nombre de cooccurrences entre deux mots liés. Ce qui est parfaitement logique.

Dans un cas extrême, le nombre maximal de cooccurrences entre locomotive et train est limité par le nombre total d’occurrences du mot le moins fréquent, ici locomotive.

Comme nous l’avons vu dans l’article précédent, il y a environ 35 000 lemmes différents dans les parties de Lexiflaire.
Cela signifie : 35 000 sommets (ou nœuds) dans notre graphe.

Mais alors, combien de liens entre ces sommets ?
Plus de 2 millions.

Parmi eux, certains liens ont un comptage très faible, même lorsqu’ils relient deux mots très fréquents.

Prenons un exemple :
Le lien entre train et animal.
Ces deux mots sont très fréquents dans le jeu :

  • train apparaît environ 72 000 fois

  • animal, plus de 300 000 fois

Mais en y réfléchissant… un lien entre animal et train n’a pas vraiment de sens. Ou alors tiré par les cheveux.
Et pourtant, on retrouve 22 cooccurrences entre ces deux mots.

Un lien avec une valeur de 22, pour relier un mot aussi fréquent qu’animal (300 000 occurrences), c’est trop faible pour être représentatif.

On voit ici que le comptage brut ne suffit pas : il peut être trompeur, surtout lorsqu’il relie deux mots très fréquents sans réel lien sémantique fort.

Il faut donc normaliser ces valeurs.

Une première idée : la pondération par fréquence

Pour commencer simplement, on peut chercher à pondérer la valeur du lien par les fréquences des deux mots qu’il relie.

Voici la formule intuitive :

Poids(A-B) = Coocc(A,B) ÷ Moyenne des occurrences de A et B
Soit, en formule :
  Poids(A-B) = Coocc(A,B) / ((Occ(A) + Occ(B)) / 2)

Exemple : locomotive ↔ train

  • Occ(locomotive) = 21 972

  • Occ(train) = 72 314

  • Coocc(locomotive, train) = 9376

On applique la formule :

Poids(locomotive-train) = 9376 / ((21972 + 72314) / 2) ≈ 0,19

Soit environ 19 % : on s’attendrait à nettement plus entre train et locomotive

Mais c’est finalement logique : un mot comme train est relié à une grande diversité de concepts. Dans le graphe sémantique, train n’est pas seulement lié à locomotive, rail ou wagon. Il est aussi relié à des notions plus larges, parfois floues, culturelles, absurdes ou même anecdotiques.

Voici les mots liés à train, filtrés uniquement pour éviter les grossièretés (et parce qu’on n’est pas limité par la place) : 

wagon 26.57%, locomotive 19.89%, gare 18.43%, rail 11.84%, ferroviaire 4.41%, tgv 4.03%, sncf 4.02%, chemineau 2.42%, avion 1.86%, dérailler 1.77%, caténaire 1.64%, bus 1.59%, vapeur 1.56%, cheminot 1.50%, funiculaire 1.32%, passager 1.26%, voiture 1.21%, véhicule 1.21%, voie 1.17%, tunnel 1.15%, railler 1.12%, quai 0.99%, billet 0.85%, voyage 0.85%, fer 0.84%, ticket 0.81%, locomotion 0.81%, chemin 0.79%, station 0.76%, charbon 0.72%, voyageur 0.61%, ferrer 0.50%, grève 0.42%, déraillement 0.40%, compartiment 0.40%, retard 0.40%, composter 0.40%, vitesse 0.37%, téléphérique 0.35%, cabine 0.35%, rapide 0.34%, arrêt 0.33%, ferré 0.30%, ligne 0.29%, rame 0.27%, barrière 0.27%, sifflement 0.26%, chauffeur 0.25%, moyen 0.24%, ensemble 0.23%, voyager 0.21%, poinçonner 0.21%, route 0.20%, réseau 0.19%, micheline 0.19%, terminus 0.19%, jouet 0.19%, siège 0.19%, accident 0.18%, express 0.18%, couchette 0.18%, arrière 0.18%, convoi 0.17%, passage 0.17%, bateau 0.17%, roue 0.16%, marchandise 0.16%, collision 0.15%, siffler 0.15%, déplacement 0.15%, camion 0.14%, usager 0.14%, rouler 0.14%, départ 0.13%, machine 0.13%, déportation 0.13%, classe 0.13%, cheminer 0.13%, caréner 0.13%, aiguillage 0.13%, fumée 0.12%, pilote 0.12%, wagonnet 0.12%, guichet 0.12%, destination 0.12%, cheminée 0.12%, coke 0.11%, long 0.11%, sifflet 0.11%, orient 0.11%, mine 0.11%, car 0.10%, itinéraire 0.10%, roule 0.10%, derrière 0.10%, cathéter 0.10%, navette 0.10%, place 0.09%, niveau 0.09%, engin 0.09%, suicide 0.09%, pont 0.09%, remorque 0.09%, bagage 0.09%, cheval 0.09%, aéroport 0.09%, crémaillère 0.08%, arriéré 0.08%, fret 0.08%, télésiège 0.08%, général 0.08%, longue 0.08%, manche 0.08%, câblé 0.08%, payant 0.08%, circuit 0.08%, météo 0.07%, indice 0.07%, valise 0.07%, voix 0.07%, atterrissage 0.07%, tortillard 0.07%, loco 0.07%, sortir 0.07%, fantôme 0.07%, correspondance 0.07%, vélo 0.07%, connexion 0.07%, horaire 0.06%, maquette 0.06%, chouchou 0.06%, touriste 0.06%, vagabond 0.06%, shoah 0.06%, western 0.06%, diligence 0.06%, signal 0.06%, fumé 0.06%, hangar 0.06%, avant 0.06%, moto 0.06%, rayer 0.06%, commun 0.06%, allure 0.05%, camp 0.05%, automobile 0.05%, désolé 0.05%, circulation 0.05%, thomas 0.05%, gars 0.05%, vite 0.05%, soute 0.05%, arrivée 0.05%, montagne 0.05%, ferry 0.05%, garer 0.05%, client 0.05%, chariot 0.05%, mdr 0.05%, déporter 0.05%, conduire 0.05%, gaz 0.05%, terminal 0.05%, caravane 0.04%, ville 0.04%, lactée 0.04%, manège 0.04%, stop 0.04%, raie 0.04%, dérayer 0.04%, mécanique 0.04%, fusée 0.04%, métal 0.04%, ancien 0.04%, embarquer 0.04%, piste 0.04%, crash 0.04%, vermeil 0.04%, billetterie 0.04%, déplacer 0.04%, sol 0.04%, aller 0.04%, simple 0.04%, devant 0.04%, roué 0.04%, agent 0.04%, manifestation 0.04%, wtt 0.04%, descendre 0.04%, heu 0.04%, vacance 0.04%, partir 0.04%, aérien 0.04%, dessus 0.04%, nomade 0.04%, machiniste 0.04%, entier 0.04%, aiguiller 0.04%, dessous 0.04%, modélisme 0.04%, poinçonneur 0.04%, chenille 0.03%, lieu 0.03%, routier 0.03%, dévier 0.03%, queue 0.03%, carambolage 0.03%, postérieur 0.03%, cocaïne 0.03%, clochard 0.03%, personne 0.03%, halte 0.03%, partie 0.03%, ram 0.03%, fraudeur 0.03%, généralité 0.03%, futur 0.03%, ferraille 0.03%, attendre 0.03%, hitler 0.03%, grand 0.03%, périphérie 0.03%, mécanicien 0.03%, fil 0.03%, calèche 0.03%, férié 0.03%, aiguilleur 0.03%, monter 0.03%, déporté 0.03%, ruche 0.03%, aide 0.03%, essieu 0.03%, téléski 0.03%, autoroute 0.03%, klaxon 0.03%, rai 0.03%, viaduc 0.03%, chanceler 0.03%, fin 0.03%, essence 0.03%, porte 0.03%, distance 0.03%, conteneur 0.03%, carte 0.03%, rapt 0.03%, tutelle 0.03%, retour 0.03%, plus 0.03%, taxi 0.03%, cockpit 0.03%, miniature 0.03%, syndicat 0.03%, bar 0.03%, omnibus 0.03%, composteur 0.03%, nazi 0.03%, réservation 0.03%, banquette 0.03%, escale 0.03%, embarquement 0.03%, tout 0.03%, mouvement 0.03%, port 0.03%, nord 0.03%, file 0.03%, support 0.03%, parking 0.03%, con 0.03%, auto 0.03%, terre 0.03%, pause 0.02%, petit 0.02%, cargaison 0.02%, prendre 0.02%, routière 0.02%, montmartre 0.02%, fourgon 0.02%, arrivé 0.02%, restaurant 0.02%, moderne 0.02%, angleterre 0.02%, russe 0.02%, vague 0.02%, arriver 0.02%, allemagne 0.02%, lit 0.02%, mer 0.02%, payer 0.02%, parcours 0.02%, tourne 0.02%, atterrir 0.02%, connard 0.02%, attelage 0.02%, quotidien 0.02%, téléférique 0.02%, chaudière 0.02%, sdf 0.02%, corail 0.02%, avancer 0.02%, merci 0.02%, pendaison 0.02%, remontée 0.02%, relatif 0.02%, fumer 0.02%, vacancier 0.02%, argent 0.02%, oublié 0.02%, parc 0.02%, fauteuil 0.02%, chaîne 0.02%, papier 0.02%, croupe 0.02%, caisse 0.02%, merde 0.02%, frontière 0.02%, garage 0.02%, gens 0.02%, circuler 0.02%, type 0.02%, tête 0.02%, bétail 0.02%, vie 0.02%, service 0.02%, lien 0.02%, monorail 0.02%, ballast 0.02%, marche 0.02%, ski 0.02%, poinçon 0.02%, autobus 0.02%, lyon 0.02%, objet 0.02%, garde 0.02%, première 0.02%, pilotage 0.02%, acier 0.02%, mort 0.02%, tarif 0.02%, panne 0.02%, capot 0.02%, gâter 0.02%, cinéma 0.02%, aiguisage 0.02%, global 0.02%, course 0.02%, sonnette 0.02%, internet 0.02%, détourner 0.02%, conduit 0.02%, révolution 0.02%, dû 0.02%, périphérique 0.02%, bois 0.02%, rapidité 0.02%, éviter 0.02%, barre 0.02%, accueil 0.02%, illégal 0.02%, métier 0.02%, bruit 0.02%, interdit 0.02%, ton 0.02%, diesel 0.02%, volant 0.02%, sur 0.02%, court 0.02%, virage 0.02%, inverse 0.02%, voleur 0.02%, rangement 0.02%, four 0.02%, voir 0.02%, chambre 0.02%, temps 0.02%, plan 0.02%, endroit 0.02%, sirène 0.02%, pipi 0.01%, vieux 0.01%, coffre 0.01%, foule 0.01%, rue 0.01%, vent 0.01%, énergie 0.01%, pièce 0.01%, nul 0.01%, débuter 0.01%, jeu 0.01%, feu 0.01%, maison 0.01%, film 0.01%, tourner 0.01%, enfant 0.01%, chaud 0.01%, faire 0.01%, guerre 0.01%, vache 0.01%, corde 0.01%, chien 0.01%, animal 0.01%, eau 0.01%

Bon, on peut noter que dans le top, au-dessus de 0,1 %, c’est très cohérent. En dehors de chemineau, qui n’a pas le même sens que cheminot, et de railler, mais ce sont des erreurs d’orthographe un peu particulières… Ensuite, c’est plus variable, mais ça reste acceptable.

Et c’est bien le problème : à 0,1 %, on s’attend à un lien bruité, à côté de la plaque. Là, on a des 0,1 %, voire 0,05 %, qui méritent leur place dans l’environnement sémantique de train. Mais c’est dû à la masse de données : il nous faut une transformation pour ça.

Log/Log

On ne va pas tout reprendre depuis le début, le changement est simple : on ajoute des logarithmes.

Je passe très vite sur le logarithme : un logarithme évolue beaucoup plus lentement que sa valeur. Par exemple : log(10) = 2, log(100) = 3, log(1000) = 4, etc.

Avant, on avait :
Poids(A-B) = Coocc(A, B) ÷ Moyenne des occurrences de A et B

Maintenant, on a :
Poids(A-B) = Log(Coocc(A, B)) ÷ Log(Moyenne des occurrences de A et B)

Je ne vais pas remettre toute la liste… mais quelques exemples :
le top — wagon 87,73 %, locomotive 84,99 %, gare 84,28 %, rail 80,15 %, ferroviaire 70,53 %.
Cette fois, les liens très forts sont, comme attendu, proches de 1 (enfin… de 100 %, mais c’est pareil).
Et pour des liens miniatures : vacancier 21,83 %, oublié 21,82 %, vache 21,77 %. 

Cette transformation log/log a deux effets très utiles. D’abord, elle rend les poids plus lisibles et interprétables : on se retrouve avec une échelle plus intuitive, où les très fortes cooccurrences frôlent les 100% et les liens plus faibles tombent doucement sans être écrasés. Ensuite, elle permet de fixer des seuils empiriques, en observant visuellement les résultats :

  • > 65 % : lien fort

  • > 45 % : lien cohérent

  • > 30 % : lien éloigné mais encore acceptable

On pourrait aller plus loin : lorsqu’un lien relie deux mots avec des fréquences très différentes, il n’est pas inintéressant de garder deux poids distincts, un pour chaque direction — un poids in et un poids out. Cela revient à ne diviser que par log(occ(A)) ou log(occ(B)). J’ajouterai sûrement un point à cet article si j’arrive à bien interpréter ces deux variantes.

Et maintenant ?

Ce graphe pondéré, une fois nettoyé et transformé, devient une carte sémantique : chaque mot est relié à ses voisins par des liens dont l’intensité reflète une proximité d’usage. C’est déjà utile en soi, mais ce n’est qu’un début : on pourra en extraire des groupes de mots (par clustering, à venir). Et comme on l’a vu dans les illustrations, en ne gardant que les liens les plus forts, le graphe prend aussi une forme visuelle intéressante.

Dans le prochain article, on abordera un autre usage des données de Lexiflaire, avec un autre modèle : Word2Vec.



vendredi 6 juin 2025

Lemmatisation


Première étape incontournable : la lemmatisation.

Lexiflaire, c’est plus de 15 millions de manches jouées.
Chaque manche contient en moyenne 2,3 indices et 2,3 propositions.

Ça nous fait environ 70 millions de tokens à traiter.
(un token, c’est une unité de texte — en gros, un mot.)

Mais il y a des doublons, beaucoup...

Prenons un exemple :

  • "animal" apparaît 170 000 fois

  • "animaux" : 30 000 fois

  • "animale" (forme adjectivale féminine) : 2 400 fois

Est-ce vraiment utile de conserver toutes ces variantes comme des mots différents ?
Dans la majorité des traitements qu’on souhaite faire… non. Ce qu’on veut, c’est regrouper toutes ces formes sous une seule entrée logique : le lemme.

Dit autrement :

  • Le lemme d’un nom, c’est sa forme au singulier.

  • Le lemme d’un adjectif, sa forme au masculin singulier.

  • Le lemme d’un verbe, son infinitif.

L’objectif : regrouper ce qui a le même sens, même si la forme change selon le genre, le nombre ou le temps.

Sans lemmatisation, le corpus contient environ 200 000 formes différentes.
Beaucoup ne sont que les déclinaison d'un même mot : pluriels, conjugaisons, féminins, fautes de frappe…

Après lemmatisation, ce chiffre tombe à environ 35 000 lemmes.
Pour cela, j’utilise Morphalou, développé par le CNRTL, qui référence plus de 540 000 formes fléchies correspondant à environ 68 000 lemmes.

Ambiguïtés grammaticales

Un même mot peut parfois dépendre de plusieurs lemmes.
Par exemple, minerais : est-ce une conjugaison du verbe miner, ou le pluriel du nom minerai ?

Une première règle simple s’applique :
-Si un mot est identique à un lemme, on choisit ce lemme-là.
Sinon, on hiérarchise les catégories grammaticales selon l’ordre :
nom > verbe > adjectif.

Et quand le mot est mal orthographié ?


Mais évidemment, pour pouvoir lemmatiser un mot, encore faut-il qu’il soit correctement orthographié. Les erreurs et fautes de frappe sont fréquentes — surtout dans un jeu de rapidité comme Lexiflaire, où on n’a pas toujours le temps de s’embêter avec les accents.

La correction orthographique, comme celle qu’on retrouve dans un traitement de texte ou un clavier de smartphone, existe… mais comment ça fonctionne ?

Elle s’appuie sur une structure appelée DAWG (Directed Acyclic Word Graph), qui permet de rechercher de manière « floue » dans un dictionnaire, grâce à la distance de Levenshtein.

Cette distance mesure le nombre minimal d’opérations (insertion, suppression, substitution) nécessaires pour transformer un mot en un autre. Par exemple, si l’on saisit « flimme », l’algorithme pourra proposer « flemme » ou « flamme », qui ne sont qu’à une distance de 1.

Dans notre cadre, ce mécanisme permet de limiter la perte de données liée aux fautes d’orthographe, même si environ 15 % des mots restent non corrigés, faute de correspondance claire.

Exemples concrets :

  • "minerai" → c’est déjà un lemme, donc on le garde tel quel.

  • "animaux" → correspond uniquement au lemme "animal" → on garde "animal".

  • "minerais" → peut être le pluriel du nom "minerai" ou une forme du verbe "miner" → on donne la priorité au nom, donc on garde "minerai".

  • "fllamme" → inconnu tel quel, mais il existe une seule correspondance à une distance de Levenshtein de 1 : "flamme", qui est un lemme → on garde "flamme".

  • "flimme" → inconnu, deux correspondances à distance 1 : "flemme" et "flamme" → ambigu, on ignore ce mot.

Conclusion

Cette étape de lemmatisation constitue la base de tous les traitements à venir.
Le prochain article portera sans doute sur la création de graphes sémantiques, rendue possible par cette normalisation.


Reprise du blog : traitement des données de Lexiflaire

Le blog reprend du service, mais cette fois pour parler du traitement des données de Lexiflaire.

En 10 ans, plus de 15 millions de manches ont été jouées. Cela représente une masse de données considérable, pleine d’indices, de réponses... de jus de cerveau.

Désormais, ce blog suivra l'exploitation de ces données, en s’appuyant sur les techniques modernes de traitement du langage naturel. L’objectif : mieux comprendre les dynamiques du jeu, entraîner des modèles, et peut-être, à terme, donner naissance à un nouveau jeu de mots… ou à une version enrichie de Lexiflaire.

À suivre !

jeudi 31 décembre 2015

Petite mise à jour et 750000 manches

Lexiflaire en chiffres :

765.000 manches jouées.
2.100.000 indices envoyés.
2464 mots jouables.

Les mots qui nécessitent le plus d'indices pour être devinés:
  • embrayer - 4373 points - 3.5 indices
  • nomenclature - 6374 points - 3.4 indices
  • clignoter - 3983 points - 3.4 indices
  • enneigé - 4108 points - 3.3 indices
  • cramponner - 3464 points - 3.3 indices
Les mots les plus long à faire deviner: 
  • nomenclature - 6374 points - 91 secondes
  • galvaniser - 6097 points - 85 secondes
  • galvauder - 6530 points - 84 secondes
  • ontologie - 6465 points - 82 secondes
  • mercantilisme - 6107 points - 81 secondes  
Les mots ayant le plus de points (et donc les plus difficiles) : 
  • manichéen avec 6608 points
  • galvauder avec 6530 points
  • éclectisme avec 6512 points
  • ontologie avec 6465 points
  • pochoir avec 6415 points

Mises à jour

  •  Le "Top complices" se trouve maintenant dans un onglet spécifique dans "Mon compte". (avec plus d'infos)
  • Dans l'onglet des derniers mots joués ("mon compte"), les mots sont cliquables. Ajout du nombre de briques moyen nécessaire pour faire deviner le mot, et du temps moyen pour le faire deviner, dans la page des mots. 
  • Dans "gestion du compte", le choix et le changement de pseudo ET de mot de passe se fait forcement en même temps. (avant tout pour obliger les visiteurs à choisir un pseudo et un mot de passe. Pas juste un pseudo)
  • Changements ergonomiques:
    • A la fin de la 4eme manche, le choix entre discuter où finir la partie est plus clair et différent visuellement des manches précédentes.
    • La couleur de la difficulté des mots en fin de manche (vert, rouge, pourpre, etc...) est revu. (seuils de points différents)
    • Bouton pour voir le graphe des mots en plein écran

www.facebook.com/lexiflaire
jpatate2@gmail.com

mardi 19 mai 2015

100000 Manches et mises à jour

100.000 manches jouées!

Lexiflaire en chiffres :

107168 manches jouées.
269422 indices envoyés.
2228 mots jouables.
966 mots jouables difficiles (2000+ points)

Les mots qui nécessitent le plus d'indices pour être devinés:
  • sagesse - 2824points - 3,7 indices en moyenne
  • rudimentaire - 2870points - 3,6 indices en moyenne
  • hilarité - 2973points - 3,5 indices en moyenne
  • ergonomie - 3195points - 3,5 indices en moyenne
  • cramponner - 2277points - 3,5 indices en moyenne
Les mots ayant le plus de points (et donc les plus difficiles) : 
  • cuistrerie avec 3343 points
  • indignation avec 3289 points
  • accabler avec 3268 points
  • cohorte avec 3227 points
  • sollicitude avec 3213 points

Mises à jour

  • Ajout d'un bouton demander la main.
  • Ajout du score sur la page principale ainsi que la tendance (hausse baisse). La tendance se fait sur le score et non sur le classement.
  • Votre meilleur classement est mémorisé.
  • Ajout d'un score spécifique à un complice. Dans la page de classement vous pouvez cliquer sur le pseudo d'un joueur. Sur cette page vous verrez le nombre de manches que vous avez joué face à ce joueur. Ainsi qu'un score spécifique à votre "duo".

www.facebook.com/lexiflaire
www.twitter.com/lexiflaire
jpatate2@gmail.com

dimanche 12 avril 2015

50000 manches jouées!

Le seuil des 50000 manches jouées sur Lexiflaire est passé !

Merci à vous!

Lexiflaire en chiffres :

52350 manches jouées.
132041 indices envoyés.
2105 mots jouables.
751 mots jouables difficiles (2000+ points)

Les mots qui nécessitent le plus d'indices pour être devinés:
  • hilarité - 2711points - 3,8 indices en moyenne
  • jubilation - 2692points - 3,8 indices en moyenne
  • accabler - 2870points - 3,7 indices en moyenne
  • ergonomie - 2865points - 3,7 indices en moyenne
  • subjuguer - 2709points - 3,7 indices en moyenne
Les mots ayant le plus de points (et donc les plus difficiles) : 
  • indignation avec 3050 points
  • simagrée avec 3001 points
  • coriace (le bien nommé) avec 2962 points
  • infâme avec 2938 points
  • obligeance avec 2918 points

Quelques graphes de mots :
Ces liens ne mènent pas à des images, le graphe va bouger pendant 10secondes pour se rendre le plus lisible possible. Vous pouvez zoomer grâce à la mollette de la souris (ou en écartant deux doigts sur tablette) et déplacer en maintenant le bouton gauche de la souris et bouger.

Les nœuds (points) correspondent aux mots (indices et réponses) joués dans lexiflaire.
La taille du nœud dépend du nombre de fois où le mot a été utilisé dans le jeu.
Deux nœuds sont reliés s'ils ont été utilisé dans la même manche.
La taille des arrêtes entre les mots, dépends du nombre de fois où les mots ont été utilisés dans les mêmes manches.

J'utilise sigma.js pour la visualisation de graphes.

www.facebook.com/lexiflaire
www.twitter.com/lexiflaire
jpatate2@gmail.com