NLP - 提取“正确的”名词短语

时间:2013-11-24 05:48:50

标签: regex nlp

我遇到了与NLP相关的问题,我希望能得到一些建议来帮助解决它。我目前正在编写一个程序,其中给定一个包含货币编号的句子,程序将能够返回与该编号对应的名词短语。例如,给出这句话:

“那辆自行车的价格是100美元。”

我将名词短语“bike”与“$ 100”匹配。我正在使用Stanford NLP的解析器来查找句子中的名词短语,并且如您所知,在名词短语中可能有名词短语。例如,在句子中:

“这些商品的购买价格是50美元。”

两个名词短语“购买价格”和“商品”都包含在名词短语“这些商品的购买价格”下,由斯坦福大学的解析器确定。因此,当匹配时,只考虑我所称的基本名词短语,或者其中不包含任何其他名词短语的名词短语,这是有意义的。但这并不总是有效,因为在这句话例如:

“他因办公空间而产生了23,000美元的相关费用以及与办公用品相关的1万美元的费用。”

由解析器识别的基本名词短语将是“成本”x2,“办公用品”和“办公空间”。但这些名词短语都没有恰当地描述数字“23000美元”和“万美元”。我们真正需要的是更为通用的名词短语“办公用品的成本”和“办公空间的成本”来充分描述这些数字。

所以我一直试图找出一种方法来提取不太宽泛或过于具体的名词短语,如前两个例子所示。但到目前为止,似乎还没有可能开发出适用于所有不同句子的方法。如果有人可以就如何解决这个问题提出任何建议,我们将不胜感激。

提前感谢您的时间。

2 个答案:

答案 0 :(得分:1)

这听起来像一个开放的问题,过于宽泛或过于具体的问题可能与建筑有关。因此,即使我们解决了这个句子,它也可能无法很好地传递给其他人。

在你的上一个例子中,“他因办公室空间而产生了23000美元的费用......”这是你想要的PP“23000美元”中的“of”的论据。

如果你将句子放入解析器(有一个在线演示here),你得到

(ROOT
  (S
    (NP (PRP He))
    (VP (VBD incurred)
    (NP
    (NP
      (NP
        (QP ($ $) (CD 23) (CD thousand)))
      (PP (IN of)
        (NP
          (NP (NNS costs))
          (VP (VBN related)
            (PP (TO to)
              (NP (NN office) (NN space)))))))

(...)

因此,如果您能够识别出这种结构并找到美元金额,那么您可能只能采用其PP的参数:

(NP
  (NP (NNS costs))
   (VP (VBN related)
        (PP (TO to)
          (NP (NN office) (NN space)))))

类似地,对于“购买价格”示例,您需要“for”的参数,即“这些商品”。

答案 1 :(得分:1)

看看我最近实施的这个库: https://github.com/krzysiekfonal/grammaregex

我认为这正是你所寻求的 - 所以你可以根据在句子树上处理的类似regex的过滤器来解析你的句子,找到一个匹配的单词。对你来说一个不方便的事情可能是它不使用coreNLP而是使用spacy库(https://spacy.io/) - 将来我想使它独立于NLP lib。

这篇文章中考虑的主要内容 - 我认为你需要做的事情 - 不仅要考虑postags,还要考虑词之间的依赖关系关系。这里有一个例子:

>>>import spacy
>>>from grammaregex import print_tree, match_tree, find_tokens
>>>nlp = spacy.load("en") 
>>>doc = nlp(u"Mrs. Robinson graduated from the Wharton School of the University of Pennsylvania in 1980.") 
>>>sent = next(doc.sents)

>>>print_tree(sent, "tag_")
{ { { Mrs.->compound(NNP) } Robinson->nsubj(NNP) } graduated->ROOT(VBD) { from->prep(IN) { { the->det(DT) } { Wharton->compound(NNP) } School->pobj(NNP) { of->prep(IN) { { the->det(DT) } University->pobj(NNP) { of->prep(IN) { Pennsylvania->pobj(NNP) } } } } } } { in->prep(IN) { 1980->pobj(CD) } } { .->punct(.) } }
>>>match_tree(sent, "VBD/prep/IN/pobj/NNP")
True
>>>match_tree(sent, "VBD/prep/IN/pobj/VBD")
False
>>>match_tree(sent, "VBD/**/DT")
True
>>>find_tokens(sent, "VBD/prep/IN/pobj/*")
[School, 1980]
>>>find_tokens(sent, "VBD/prep/IN/*/[NNP,DT]")
[School]
>>>find_tokens(sent, "VBD/**/DT")
[the, the]

所以你只需要使用print_tree来查看你的句子树(你也可以在https://displacy.spacy.io/上使用更好的图形化可视化),然后调整你将在find_tokens方法中使用的正则表达式字符串。

在这里你可以找到这个简单的lib的快速介绍: https://medium.com/@krzysiek89dev/grammaregex-library-regex-like-for-text-mining-49e5706c9c6d#.vrrm88bt4