如何提取数字(连同比较形容词或范围)

36

我正在使用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}

使用CogComp-quantifier包:https://github.com/CogComp/cogcomp-nlp/tree/master/pipeline 它可以提取数量,并规范化它们的单位。 - Daniel
1
Facebook的Duckling对于这个任务非常适合。你可以在https://github.com/facebookincubator/duckling找到它。 - Ramtin M. Seraj
2个回答

31
我会把这个任务看作是分块任务,并使用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')]]

2

https://spacy.io/universe/project/numerizer 可能适用于您的使用情况。

来自链接:

from spacy import load
import numerizer
nlp = load('en_core_web_sm') # or any other model
doc = nlp('The Hogwarts Express is at platform nine and three quarters')
doc._.numerize()
# {nine and three quarters: '9.75'}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接