NLTK RegexpParser,通过精确匹配一项来分块短语

Posted

技术标签:

【中文标题】NLTK RegexpParser,通过精确匹配一项来分块短语【英文标题】:NLTK RegexpParser, chunk phrase by matching exactly one item 【发布时间】:2016-12-31 15:48:37 【问题描述】:

我正在使用 NLTK 的 RegexpParser 来分块一个名词短语,我用语法将其定义为

 grammar = "NP: <DT>?<JJ>*<NN|NNS>+"
 cp = RegexpParser(grammar)

这很好,它匹配一个名词短语:

DT 如果存在 JJ 随便几号 NN 或 NNS,至少一个

现在,如果我想匹配相同但将 JJ 的 whatever number 转换为 只有一个,该怎么办?所以我想匹配 DT(如果存在),one JJ 和 1+ NN/NNS。如果有多个 JJ,我只想匹配其中一个,即最接近名词的一个(如果有,则为 DT,以及 NN/NNS)。

语法

grammar = "NP: <DT>?<JJ><NN|NNS>+"

只有当只有一个 JJ 时才会匹配,语法

grammar = "NP: <DT>?<JJ>1<NN|NNS>+"

考虑到typical Regexp patterns,我认为这会起作用,但会引发 ValueError。

例如,在“这条漂亮的绿裙子”中,我想分块“这条绿裙子”。

那么,我该怎么做呢?

【问题讨论】:

语法 = "NP: ?+" 是正确的。你能举个例子,它没有给出确定器吗? 因为您的示例中有 2 个 JJ。你说 - “我想匹配 DT,如果它存在,一个 JJ 和 1+ NN/NNS。” @RAVI,看起来你很准确,这解释了问题。您应该将其扩展为 OP 可以接受的答案。 【参考方案1】:

语法 grammar = "NP: &lt;DT&gt;?&lt;JJ&gt;&lt;NN|NNS&gt;+" 符合您提到的要求。

你在评论部分给出的例子,你没有在输出中得到 DT -

"This beautiful green skirt is for you."

Tree('S', [('This', 'DT'), ('beautiful', 'JJ'), Tree('NP', [('green','JJ'), 
('skirt', 'NN')]), ('is', 'VBZ'), ('for', 'IN'), ('you', 'PRP'), ('.', '.')])

在您的示例中,2 consecutive JJs 不符合您所说的要求 - "I want to match DT if it exists, one JJ and 1+ NN/NNS."


对于更新的要求 - I want to match DT if it exists, one JJ and 1+ NN/NNS. If there are more than one JJ, I want to match only one of them, the one nearest to the noun (and DT if there is, and NN/NNS).

在这里,你需要使用

grammar = "NP: <DT>?<JJ>*<NN|NNS>+"

并对 NP 块进行后处理以删除额外的 JJ。

代码:

from nltk import Tree

chunk_output = Tree('S', [Tree('NP', [('This', 'DT'), ('beautiful', 'JJ'), ('green','JJ'), ('skirt', 'NN')]), ('is', 'VBZ'), ('for', 'IN'), ('you', 'PRP'), ('.', '.')])

for child in chunk_output:
    if isinstance(child, Tree):               
        if child.label() == 'NP':
            for num in range(len(child)):
                if not (child[num][1]=='JJ' and child[num+1][1]=='JJ'):
                    print child[num][0]

输出:

This
green
skirt

【讨论】:

对,所以没有办法直接告诉解析器我只想要一个。 是的,这是不可能的,因为您想在两者之间跳过一些内容。如果你知道正则表达式匹配的工作原理,你就会明白。

以上是关于NLTK RegexpParser,通过精确匹配一项来分块短语的主要内容,如果未能解决你的问题,请参考以下文章

NLTK 正则表达式和 CFG

使用 NLTK 将两个字符串匹配在一起?

NLTK实现文本切分

通过精确的单词匹配过滤熊猫数据框

字符串列包含通过 spark scala 精确匹配的单词

Java - MongoDB不区分大小写不检查精确匹配