Calcul de similarité entre des rôles

fred_mangeVoici une petite portion de script.

Imaginons que vous ayiez un rôle (« Acteur », pour l’évènement « mange »).

Vous trouvez une description (si, si) de cet évènement dans une autre ressource et voudriez savoir si ce rôle « Acteur » est appariable avec, par exemple, « Agent ».
Vous êtes en anglais, ce rôle et plus ou moins bien décrit d’un côté ou de l’autre… S’il est coancré d’un côté (précédé systématiquement de telle préposition pour un verbe par exemple intransitif) et ne l’est pas de l’autre, cela ne doit pas être rédhibitoire. Il peut aussi être introduit auprès du verbe par une préposition modifiant le sens du verbe : un modifier. Aller dans la ruelle diffère d’aller hors de la ruelle… on ne va pas dans le même sens.

Alors…

  • Nous sommes en python.
    • Une classe « Role », avec une coancre (on peut pousser à vérifier la coancre, ici c’est hors de l’exemple pour des raisons de légèreté côté fiabilité de l’information détenue) et/ou un modifier. Si le rôle est introduit, par un modifier (on_modified_event = True) ou une coancre (coancred=True), nous avons un booléen (introduced qui est égal à (on_modified_event or coancred))
    • Un objet de classe, « proximités », pour stocker les proximités évaluées : si les mots sont un peu variés, l’usage de wordnet est gourmand. Un stockage dans du json des calculs pourra même être envisagé sans complexe. Dans le init, si proximités est vide et json, chargement…
import itertools
from nltk.corpus import wordnet

class Role:
 proximités={}
 def proximity_abs(self, other):
    """ 
    renvoie un nombre compris entre 0 et 1
    """
    proxi=0.
    if self.nom==other.nom :
        proxi=.7
    else:
        if other.nom+self.nom in Event.Relation.Role.proximités.keys():
            proxi+=Event.Relation.Role.proximités[other.nom+self.nom]
        else:
            #jamais de max sur liste vide, et le mot a au moins le mérite d'exister...
            list=[.01]
            syns1 = wordnet.synsets(self.nom)
            syns2 = wordnet.synsets(other.nom)
            for sense1, sense2 in itertools.product(syns1, syns2):
                list.append( wordnet.wup_similarity(sense1, sense2))
            Event.Relation.Role.proximités[other.nom + self.nom] = max(list)
            Event.Relation.Role.proximités[self.nom + other.nom] = Event.Relation.Role.proximités[other.nom + self.nom]
        #on calcule la proximité en retranchant 0.01 : des mots différents ne vont pas obtenir autant que des mots équivalents. 
        proxi+= ((Event.Relation.Role.proximités[other.nom + self.nom])*0.7)-.01
    #la suite se discute, disons que l'idée est de vouloir sélectionner quelque chose qui a du sens, on ne se servira pas de cette classe pour faire du rôle à rôle, mais de l'appariement pour des évènements proches).
    if self.coanchored == other.coanchored:
        proxi+=.1
    if self.on_modified_event == other.modified_event:
        proxi+=1
    if other.introduced()== self.introduced():
        proxi+=.1
    return proxi