如何使用 nltk 正则表达式模式来提取特定的短语块?

Posted

技术标签:

【中文标题】如何使用 nltk 正则表达式模式来提取特定的短语块?【英文标题】:How to use nltk regex pattern to extract a specific phrase chunk? 【发布时间】:2016-03-09 12:39:11 【问题描述】:

我编写了以下正则表达式来标记某些短语模式

pattern = """
        P2: <JJ>+ <RB>? <JJ>* <NN>+ <VB>* <JJ>*
        P1: <JJ>? <NN>+ <CC>? <NN>* <VB>? <RB>* <JJ>+
        P3: <NP1><IN><NP2>
        P4: <NP2><IN><NP1>

    """

这种模式可以正确地标记一个短语,例如:

a = 'The pizza was good but pasta was bad'

并用 2 个短语给出所需的输出:

    披萨很好吃 意大利面很糟糕

但是,如果我的句子是这样的:

a = 'The pizza was awesome and brilliant'

只匹配短语:

'pizza was awesome' 

而不是想要的:

'pizza was awesome and brilliant'

如何在我的第二个示例中也加入正则表达式模式?

【问题讨论】:

从语言上讲,我不认为你们都可以pizza was good 一个名词短语,也不是动词短语,因为你去掉了限定词。它更像是您要提取的一些短语结构。 基本上,我想在评论中使用描述菜肴的短语。不是名词短语。编辑了我的问题! 别担心,我明白你在做什么。是用来分析情绪的吧?我正在写一个答案 =) 你真的想保留确定器吗? 实际上不需要确定器!非常感谢..会试试看! :) 【参考方案1】:

首先我们来看看NLTK给出的POS标签:

>>> from nltk import pos_tag
>>> sent = 'The pizza was awesome and brilliant'.split()
>>> pos_tag(sent)
[('The', 'DT'), ('pizza', 'NN'), ('was', 'VBD'), ('awesome', 'JJ'), ('and', 'CC'), ('brilliant', 'JJ')]
>>> sent = 'The pizza was good but pasta was bad'.split()
>>> pos_tag(sent)
[('The', 'DT'), ('pizza', 'NN'), ('was', 'VBD'), ('good', 'JJ'), ('but', 'CC'), ('pasta', 'NN'), ('was', 'VBD'), ('bad', 'JJ')]

(注意:以上是NLTK v3.1 pos_tag的输出,旧版本可能会有所不同)

你想要捕捉的本质上是:

NN VBD JJ CC JJ NN VBD JJ

让我们用这些模式来捕捉它们:

>>> from nltk import RegexpParser
>>> sent1 = ['The', 'pizza', 'was', 'awesome', 'and', 'brilliant']
>>> sent2 = ['The', 'pizza', 'was', 'good', 'but', 'pasta', 'was', 'bad']
>>> patterns = """
... P: <NN><VBD><JJ><CC><JJ>
... <NN><VBD><JJ>
... """
>>> PChunker = RegexpParser(patterns)
>>> PChunker.parse(pos_tag(sent1))
Tree('S', [('The', 'DT'), Tree('P', [('pizza', 'NN'), ('was', 'VBD'), ('awesome', 'JJ'), ('and', 'CC'), ('brilliant', 'JJ')])])
>>> PChunker.parse(pos_tag(sent2))
Tree('S', [('The', 'DT'), Tree('P', [('pizza', 'NN'), ('was', 'VBD'), ('good', 'JJ')]), ('but', 'CC'), Tree('P', [('pasta', 'NN'), ('was', 'VBD'), ('bad', 'JJ')])])

这就是硬编码的“作弊”!!!

让我们回到 POS 模式:

NN VBD JJ CC JJ NN VBD JJ

可以简化为:

NN VBD JJ (CC JJ)

因此您可以在正则表达式中使用可选运算符,例如:

>>> patterns = """
... P: <NN><VBD><JJ>(<CC><JJ>)?
... """
>>> PChunker = RegexpParser(patterns)
>>> PChunker.parse(pos_tag(sent1))
Tree('S', [('The', 'DT'), Tree('P', [('pizza', 'NN'), ('was', 'VBD'), ('awesome', 'JJ'), ('and', 'CC'), ('brilliant', 'JJ')])])
>>> PChunker.parse(pos_tag(sent2))
Tree('S', [('The', 'DT'), Tree('P', [('pizza', 'NN'), ('was', 'VBD'), ('good', 'JJ')]), ('but', 'CC'), Tree('P', [('pasta', 'NN'), ('was', 'VBD'), ('bad', 'JJ')])])

很可能您使用的是旧标记器,这就是您的模式不同的原因,但我想您知道如何使用上面的示例捕获所需的短语。

步骤如下:

首先,使用pos_tag 检查什么是 POS 模式 然后概括并简化模式 然后将它们放入RegexpParser

【讨论】:

以上是关于如何使用 nltk 正则表达式模式来提取特定的短语块?的主要内容,如果未能解决你的问题,请参考以下文章

NLTK RegEx Chunker 未使用通配符捕获已定义的语法模式

如何使用正则表达式删除 std::wstring 中特定短语的所有实例?

正则表达式:匹配文本段落中除特定短语外的所有内容

特定模式的正则表达式提取

NLTK实现文本切分

正则表达式