2017-07-16 20 views
32

我的工作在两个NLP项目在Python,两者有相似的任务可以从类似的句子中提取值和比较操作:如何提取数字(与比较形容词或范围沿)

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

我看到两种不同的方式来解决这个问题,一种使用非常复杂的正则表达式,另一种使用NER(以及一些正则表达式)。

如何从这些句子中解析出数值?我认为这是NLP的一个常见任务。


所需的输出会是这样的:

输入:

“大于10 $”

输出:

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

使用CogComp-量词封装:https://开头github上。com/CogComp/cogcomp-nlp/tree/master/pipeline它可以提取数量,并标准化它们的单位。 – Daniel

+1

Facebook小鸭适合这项任务https://github.com/facebookincubator/duckling –

回答

24

我可能会将此作为一个分块任务,并使用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')]]