Pregunta Cómo extraer números (junto con adjetivos de comparación o rangos)


Estoy trabajando en dos proyectos de PNL en Python, y ambos tienen tareas similares para extraer valores y operadores de comparación de oraciones como:

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

Vi dos maneras diferentes de resolver este problema, una usando expresiones regulares muy complejas, y otra usando NER (y algunas expresiones regulares también).

¿Cómo puedo analizar los valores de tales oraciones? Supongo que esta es una tarea común en NLP.


El resultado deseado sería algo así como:

Entrada:

"más de $ 10"

Salida:

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

32
2017-07-16 07:19


origen


Respuestas:


Probablemente abordaría esto como una tarea de fragmentación y uso nltkTagger de la parte del discurso combinado con su chunker de expresión regular. Esto le permitirá definir una expresión regular basada en la parte del discurso de las palabras en sus oraciones en lugar de en las palabras mismas. Para una oración dada, puede hacer lo siguiente:

import nltk

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

Lo primero que haría es modificar un poco las oraciones para no confundir demasiado el marcador de la parte del discurso. Aquí hay algunos ejemplos de cambios que puede realizar (con expresiones regulares muy simples) pero puede experimentar y ver si hay otros:

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

así que obtenemos:

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

ahora puedes obtener las partes del discurso de tu oración:

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')]

Ahora podemos crear un Chunker que dividirá el texto etiquetado POS según una expresión regular (relativamente) simple:

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

Esto define un analizador sintáctico con una gramática que descompone las frases numéricas (lo que llamaremos su tipo de frase). Define su frase numérica como: un sustantivo opcional, seguido de un adverbio opcional, seguido de un adjetivo comparativo, una preposición, un número y un sustantivo opcional. Esta es solo una sugerencia de cómo puede querer definir sus frases, pero creo que esto será mucho más simple que usar una expresión regular en las palabras mismas.

Para obtener tus frases puedes hacer:

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))  

O para obtener solo sus frases que puede hacer:

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')]]

26
2017-07-16 15:20