2017-07-16 3 views
32

Je travaille sur deux PNL-projets en Python, et les deux ont même tâche d'extraire les valeurs et les opérateurs de comparaison de phrases telles que:Comment extraire les numéros (ainsi que des adjectifs de comparaison ou gammes)

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

j'ai vu Deux manières différentes de résoudre ce problème, l'une utilisant des expressions régulières très complexes, l'autre utilisant NER (et quelques regexes aussi).

Comment puis-je analyser les valeurs de telles phrases? Je suppose que c'est une tâche commune dans la PNL.


La sortie souhaitée serait quelque chose comme:

Entrée:

"supérieur à 10 $"

Sortie:

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

Utilisez le paquet CogComp-quantificateurs: https: // GitHub.com/CogComp/cogcomp-nlp/arbre/maître/pipeline Il peut extraire des quantités et normaliser leurs unités. – Daniel

+1

Facebook caneton est bon pour cette tâche https://github.com/facebookincubator/duckling –

Répondre

24

Je l'aborderais probablement comme une tâche de segmentation et j'utiliserais la partie nltk de l'outil de marquage de la parole associé à sa séquence d'expression régulière. 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 effectuer les opérations suivantes:

import nltk 

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

La première chose que je voudrais faire est de modifier vos phrases un peu afin que vous ne confondez pas trop de la part de tagger de la parole. Voici quelques exemples de changements que vous pouvez faire (très simples expressions régulières) mais vous pouvez expérimenter et voir s'il y a d'autres:

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

donc nous obtenons:

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

maintenant vous pouvez obtenir les parties du discours 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 sera votre morceau POS texte balisé selon une expression régulière simple (relativement):

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

Ceci définit un analyseur avec une grammaire que des morceaux de phrases numériques (ce que nous appellerons le type de phrase). Il définit votre expression numérique comme: un nom facultatif, suivi d'un adverbe optionnel, suivi d'un adjectif comparatif, d'une préposition, d'un nombre et d'un nom optionnel. Ceci est juste une suggestion pour la façon dont vous pourriez vouloir définir vos phrases, mais je pense que ce sera beaucoup plus simple que d'utiliser une expression régulière sur les mots eux-mêmes.

Pour obtenir vos phrases que vous pouvez 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 que vos phrases que vous pouvez 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')]]