Sam Vimaire soupira quand il entendit le cri.
The Eyjafjallajökull volcano, one of Iceland’s largest had been dormant for nearly two centuries before returning gently to life in the late evening of March 20, 2010, noticeable at first by the emergence of a red cloud glowing above the vast glacier that covers it. In the following days, fire fountains jetted from a dozen vents on the volcano, reaching as high as 100 meters.
La communication en langage naturel inclut des références à des entités, qui existent dans un espace discursif.
La pomme est un fruit et c'est délicieux.
« […] faut que je le note, d’ailleurs vous me le faites rappeler »
Morgan a vu une licorne. Elle avait une crinière dorée
Si j'avais une voiture, elle serait indigo.
Un triangle à quatre côtés, c'est quelque chose d'incroyable
Ces entités ne sont d'ailleurs pas fixes et peuvent évoluer au fil du discours :
Prenez une belle courgette bien mûre. Préparez-la à passer au four, coupez-la en quatre morceaux et faites-la rôtir avec du thym et du paprika fumé pendant une heure. Servez-la avec du riz et savourez son parfum doux et délicatement épicé.
On dit que ces éléments sont des mentions qui réfèrent à des entités et que des mentions qui font référence à une même entité sont coréférentes.
La tâche de « détection des chaînes de coréférences » (coreference resolution) est en général :
Autrement dit, elle peut être décomposée en deux sous-tâches
Tâches connexes :
Modèles :
Paradigme dominant : E2EC de Kenton Lee et al.
import stanza
stanza.install_corenlp(dir="local/corenlp")
2022-08-21 16:14:15 INFO: Installing CoreNLP package into local/corenlp
2022-08-21 16:14:24 WARNING: For customized installation location, please set the `CORENLP_HOME` environment variable to the location of the installation. In Unix, this is done with `export CORENLP_HOME=local/corenlp`.
import os
os.environ["CORENLP_HOME"] = "local/corenlp"
from stanza.server import CoreNLPClient
with CoreNLPClient(
annotators=["tokenize","ssplit","pos","lemma","ner", "parse", "depparse","coref"],
memory="4G",
endpoint="http://localhost:9001",
be_quiet=True,
) as client:
text = "Beethoven’s first music teacher was his father. Although tradition has it that Johann van Beethoven was a harsh instructor, and that the child Beethoven, “made to stand at the keyboard, was often in tears”, the Grove Dictionary of Music and Musicians claimed that no solid documentation supported this."
document = client.annotate(text)
2022-08-21 16:14:24 INFO: Writing properties to tmp file: corenlp_server-3c09d94e1da34dbe.props 2022-08-21 16:14:24 INFO: Starting server with command: java -Xmx4G -cp local/corenlp/* edu.stanford.nlp.pipeline.StanfordCoreNLPServer -port 9001 -timeout 60000 -threads 5 -maxCharLength 100000 -quiet True -serverProperties corenlp_server-3c09d94e1da34dbe.props -annotators tokenize,ssplit,pos,lemma,ner,parse,depparse,coref -preload -outputFormat serialized
document.corefChain
[chainID: 5 mention { mentionID: 0 mentionType: "PROPER" number: "SINGULAR" gender: "MALE" animacy: "ANIMATE" beginIndex: 0 endIndex: 1 headIndex: 0 sentenceIndex: 0 position: 1 } mention { mentionID: 6 mentionType: "PROPER" number: "SINGULAR" gender: "MALE" animacy: "ANIMATE" beginIndex: 17 endIndex: 18 headIndex: 17 sentenceIndex: 1 position: 2 } mention { mentionID: 5 mentionType: "PROPER" number: "SINGULAR" gender: "MALE" animacy: "ANIMATE" beginIndex: 5 endIndex: 8 headIndex: 7 sentenceIndex: 1 position: 1 } representative: 2 , chainID: 11 mention { mentionID: 11 mentionType: "NOMINAL" number: "SINGULAR" gender: "UNKNOWN" animacy: "ANIMATE" beginIndex: 15 endIndex: 18 headIndex: 16 sentenceIndex: 1 position: 7 } mention { mentionID: 2 mentionType: "NOMINAL" number: "SINGULAR" gender: "UNKNOWN" animacy: "ANIMATE" beginIndex: 0 endIndex: 5 headIndex: 4 sentenceIndex: 0 position: 3 } mention { mentionID: 4 mentionType: "PRONOMINAL" number: "SINGULAR" gender: "MALE" animacy: "ANIMATE" beginIndex: 6 endIndex: 7 headIndex: 6 sentenceIndex: 0 position: 5 } representative: 1 ]
mentions_dict = dict()
for sent in document.sentence:
for m in sent.mentions:
mentions_dict[m.entityMentionIndex] = m
for chain in document.corefChain:
print([mentions_dict[m.mentionID].entityMentionText for m in chain.mention])
['Beethoven', 'Beethoven', 'instructor']
--------------------------------------------------------------------------- KeyError Traceback (most recent call last) Input In [7], in <cell line: 5>() 4 mentions_dict[m.entityMentionIndex] = m 5 for chain in document.corefChain: ----> 6 print([mentions_dict[m.mentionID].entityMentionText for m in chain.mention]) Input In [7], in <listcomp>(.0) 4 mentions_dict[m.entityMentionIndex] = m 5 for chain in document.corefChain: ----> 6 print([mentions_dict[m.mentionID].entityMentionText for m in chain.mention]) KeyError: 11
document.corefChain[0].mention
[mentionID: 0 mentionType: "PROPER" number: "SINGULAR" gender: "MALE" animacy: "ANIMATE" beginIndex: 0 endIndex: 1 headIndex: 0 sentenceIndex: 0 position: 1 , mentionID: 6 mentionType: "PROPER" number: "SINGULAR" gender: "MALE" animacy: "ANIMATE" beginIndex: 17 endIndex: 18 headIndex: 17 sentenceIndex: 1 position: 2 , mentionID: 5 mentionType: "PROPER" number: "SINGULAR" gender: "MALE" animacy: "ANIMATE" beginIndex: 5 endIndex: 8 headIndex: 7 sentenceIndex: 1 position: 1 ]
Exploration :
Dans la suite, on considère qu'on dispose d'un ensemble $K$ (key) de chaînes de coréférences gold et d'un ensembe $R$ (response) de chaînes de coréférence détectées par un système. Les chaînes sont vues comme des ensembles de mentions (représentées par des symboles arbitraires, par exemple des entiers.
On notera $\lvert E\rvert$ le cardinal d'un ensemble $E$, c'est-à-dire le nombre d'éléments qu'il contient.
où $K'$ et $R'$ sont les ensembles des chaînes respectivement gold et système de longueurs au moins $2$ et $p(x, E) = \{x\cap A | A∈E\}$.
Intuitivement : précision/rappel de la détection des liens entre une mention et son plus proche antécédent.
Où $r(m)$ (resp. $k(r)$) la chaîne système (resp. gold) qui contient la mention $m$ et $M_R$ et $M_K$ sont les ensembles des mentions gold et système.
Intuitivement, la précision, c'est la moyenne sur l'ensemble des mentions gold du taux de couverture de la chaîne gold associée à chaque mention $m$ par la chaîne système qui contient $m$.
Où $ϕ$ est une fonction qui évalue l'accord entre deux ensembles et l'alignement $A$ associe à
chaque chaîne gold une chaîne système de telle sorte que $\sum ϕ(k, A(k)$ soit maximale. Si la
fonction $ϕ$ est donnée, un tel alignement peut se trouver efficacement avec l'algorithme de
Kuhn-Munkres (implémenté par exemple par
scipy.optimize.linear_sum_assignment
.
En pratique, on utilise surtout CEAFe, pour lequel la fonction est :
$$ \newcommand\card[1]{\vert#1\rvert} \begin{equation} ϕ₄: (k, r) ⟼ \frac{2\card{k∩r}}{\card{k}+\card{r}} \end{equation} $$Autrement dit, l'indice de Sørensen-Dice.
La définition peut paraître tordue, mais l'idée est sûrement la plus simple : pour évaluer la qualité de la partition en chaîne de l'ensemble des mention on choisit d'associer à chaque chaîne gold une chaîne système (en choisissant celle qui ressemble le plus) et on mesure l'accord moyen.
On considèrera que les mentions sont représentés par les entiers de $1$ à $n$ pour un $n$ donné
K = {(1, 2), (2, 3), (3, 4), (4, 5), (6, 7), (8, 9), (9, 10), (10, 11), (11, 12)}
R1 = set()
R2 = {(1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7), (7, 8), (8, 9), (9, 10), (10, 11), (11, 12)}
R3 = {(1, 2), (2, 3), (3, 4), (4, 5), (6, 7), (7, 8), (8, 9), (9, 10), (10, 11), (11, 12)}
R4 = {(1, 2), (2, 3), (3, 4), (4, 5), (6, 7), (5, 8), (8, 9), (9, 10), (10, 11), (11, 12)}