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

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

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

Я нашел два разных подхода к решению этой проблемы:

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


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

Ввод:

"более 10 долларов"

Вывод:

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

person svfat    schedule 16.07.2017    source источник
comment
Используйте пакет CogComp-quantifier: github.com/CogComp/cogcomp-nlp/tree/ master / pipeline Он может извлекать количества и нормализовать их единицы.   -  person Daniel    schedule 17.07.2017
comment
Утенок Facebook хорош для этой задачи github.com/facebookincubator/duckling   -  person Ramtin M. Seraj    schedule 25.09.2017


Ответы (1)


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

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

Теперь мы можем создать блокировку, которая разбивает текст с тегами 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')]]
person bunji    schedule 16.07.2017