36 votes

Comment extraire des nombres (avec des adjectifs de comparaison ou des intervalles) ?

Je travaille sur deux projets NLP en Python, et tous deux ont une tâche similaire à celle de extraire des valeurs numériques et des opérateurs de comparaison à partir de phrases, comme la suivante :

"... greater than $10 ... ",
"... weight not more than 200lbs ...",
"... height in 5-7 feets ...",
"... faster than 30 seconds ... "

J'ai trouvé deux approches différentes pour résoudre ce problème :

Comment puis-je analyser les valeurs numériques de ces phrases ? Je suppose qu'il s'agit d'une tâche courante dans le domaine du NLP.


Le résultat souhaité serait quelque chose comme :

Entrée :

"plus de 10 $"

Sortie :

{'value': 10, 'unit': 'dollar', 'relation': 'gt', 'position': 3}

0 votes

Utiliser le paquet CogComp-quantifier : github.com/CogComp/cogcomp-nlp/tree/master/pipeline Il peut extraire des quantités et normaliser leurs unités.

1 votes

Le caneton Facebook est bien adapté à cette tâche github.com/facebookincubator/duckling

31voto

bunji Points 3118

Je l'aborderais probablement comme une tâche de découpage et j'utiliserais nltk combiné à son analyseur d'expressions régulières. Cela vous permettra de définir une expression régulière basée sur la partie du discours des mots dans vos phrases plutôt que sur les mots eux-mêmes. Pour une phrase donnée, vous pouvez faire ce qui suit :

import nltk

# example sentence
sent = 'send me a table with a price greater than $100'

La première chose à faire est de modifier légèrement vos phrases afin de ne pas trop perturber le marqueur de partie du discours. Voici quelques exemples de modifications que vous pouvez apporter (avec des expressions régulières très simples), mais vous pouvez expérimenter et voir s'il y en a d'autres :

$10 -> 10 dollars
200lbs -> 200 lbs
5-7 -> 5 - 7 OR 5 to 7

nous obtenons donc :

sent = 'send me a table with a price greater than 100 dollars'

Vous pouvez maintenant obtenir les parties du discours à partir de votre phrase :

sent_pos = nltk.pos_tag(sent.split())
print(sent_pos)

[('send', 'VB'), ('me', 'PRP'), ('a', 'DT'), ('table', 'NN'), ('with', 'IN'), ('a', 'DT'), ('price', 'NN'), ('greater', 'JJR'), ('than', 'IN'), ('100', 'CD'), ('dollars', 'NNS')]

Nous pouvons maintenant créer un chunker qui va découper votre texte étiqueté POS en fonction d'une expression régulière (relativement) simple :

grammar = 'NumericalPhrase: {<NN|NNS>?<RB>?<JJR><IN><CD><NN|NNS>?}'
parser = nltk.RegexpParser(grammar)

Cela définit un analyseur avec une grammaire qui regroupe les phrases numériques (ce que nous appellerons votre type de phrase). Il définit votre phrase numérique comme suit : un nom optionnel, suivi d'un adverbe optionnel, suivi d'un adjectif comparatif, d'une préposition, d'un nombre et d'un nom optionnel. Ce n'est qu'une suggestion sur la manière dont vous pouvez définir vos phrases, mais je pense que c'est beaucoup plus simple que d'utiliser une expression régulière sur les mots eux-mêmes.

Pour obtenir vos phrases, vous pouvez le faire :

print(parser.parse(sent_pos))
(S
  send/VB
  me/PRP
  a/DT
  table/NN
  with/IN
  a/DT
  (NumericalPhrase price/NN greater/JJR than/IN 100/CD dollars/NNS))  

Ou pour obtenir uniquement vos phrases, vous pouvez le faire :

print([tree.leaves() for tree in parser.parse(sent_pos).subtrees() if tree.label() == 'NumericalPhrase'])

[[('price', 'NN'),
  ('greater', 'JJR'),
  ('than', 'IN'),
  ('100', 'CD'),
  ('dollars', 'NNS')]]

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X