Подтвердить что ты не робот

Как извлечь числа (наряду с прилагательными или диапазонами сравнения)

Я работаю над двумя NLP-проектами в Python, и у них есть аналогичная задача для извлечения значений и операторов сравнения из предложений вроде:

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

Я видел два разных способа решения этой проблемы: один использовал очень сложные регулярные выражения, а один использовал NER (и некоторые регулярные выражения тоже).

Как я могу анализировать значения из таких предложений? Я предполагаю, что это общая задача в НЛП.


Желаемый результат будет примерно таким:

Ввод:

"больше $10"

Вывод:

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

Ответ 1

Я бы, вероятно, подошел к этому как задача chunking и использовал nltk часть речевого метки в сочетании с регулярным выражением chunker. Это позволит вам определить регулярное выражение, основанное на части речи слов в ваших предложениях, а не на самих словах. Для данного предложения вы можете сделать следующее:

import nltk

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

Первое, что я хотел бы сделать, это немного изменить ваши предложения, чтобы вы не слишком сильно путали часть речевого метки. Вот несколько примеров изменений, которые вы можете сделать (с очень простыми регулярными выражениями), но вы можете поэкспериментировать и посмотреть, есть ли другие:

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

поэтому получаем:

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

теперь вы можете получить части речи из своего предложения:

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

Теперь мы можем создать chunker, который будет обрезать ваш тег с тегами POS в соответствии с (относительно) простым регулярным выражением:

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

Этот параметр определяет синтаксический анализатор с грамматикой, которая разбивает числовые фразы (что мы будем называть вашим типом фразы). Он определяет вашу цифровую фразу как: необязательное существительное, за которым следует необязательное наречие, за которым следует сравнительное прилагательное, предлог, число и необязательное существительное. Это всего лишь предложение о том, как вы можете определить свои фразы, но я думаю, что это будет намного проще, чем использование регулярного выражения для самих слов.

Чтобы получить свои фразы, вы можете:

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

Или получить только свои фразы, которые вы можете сделать:

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