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

Posted

技术标签:

【中文标题】NLTK RegEx Chunker 未使用通配符捕获已定义的语法模式【英文标题】:NLTK RegEx Chunker not capturing defined grammar patterns with wildcards 【发布时间】:2016-03-24 22:44:56 【问题描述】:

我正在尝试使用 NLTK 的 POS 标签作为正则表达式来分块一个句子。根据句子中单词的标签,定义了2条规则来识别短语。

主要是,我想捕捉一个或多个动词后面跟着一个可选的限定词,然后是一个或多个名词的块。这是定义中的第一条规则。但它不会被捕获为短语块。

import nltk

## Defining the POS tagger 
tagger = nltk.data.load(nltk.tag._POS_TAGGER)


## A Single sentence - input text value
textv="This has allowed the device to start, and I then see glitches which is not nice."
tagged_text = tagger.tag(textv.split())

## Defining Grammar rules for  Phrases
actphgrammar = r"""
     Ph: <VB*>+<DT>?<NN*>+  # verbal phrase - one or more verbs followed by optional determiner, and one or more nouns at the end
     <RB*><VB*|JJ*|NN*\$> # Adverbial phrase - Adverb followed by adjective / Noun or Verb
     """

### Parsing the defined grammar for  phrases
actp = nltk.RegexpParser(actphgrammar)

actphrases = actp.parse(tagged_text)

分块器的输入,tagged_text 如下。

标记文本 出[7]: [('这个','DT'), ('有', 'VBZ'), ('允许', 'VBN'), ('the', 'DT'), ('设备', 'NN'), ('到','到'), ('开始','NNP'), ('和', '抄送'), ('我','PRP'), ('那么', 'RB'), ('见','VB'), ('故障','NNS'), ('哪个','WDT'), ('是','VBZ'), ('不是','RB'), ('nice.', 'NNP')]

在最终输出中,仅捕获匹配第二条规则的副词短语('then see')。 我希望口头短语('allowed the device')与第一条规则匹配并被捕获,但事实并非如此。

actphrases Out[8]: Tree('S', [('This', 'DT'), ('has', 'VBZ'), ('allowed', 'VBN'), ('the', 'DT'), ('device', 'NN'), ('to', 'TO'), ('start,', 'NNP'), ('and', 'CC'), ('I', 'PRP'), Tree('Ph', [('then', 'RB'), ('see', 'VB')]), ('glitches', 'NNS'), ('which', 'WDT'), ('is', 'VBZ'), ('not', 'RB'), ('nice.', 'NNP')])

使用的 NLTK 版本是 2.0.5 (Python 2.7) 任何帮助或建议将不胜感激。

提前致谢,

巴拉。

【问题讨论】:

首先将您的 NLTK 更新到 3.1。自 2.0 以来发生了重大变化,因此有必要获得工作代码。 sudo apt-get install python-nltksudo pip install -U nltk。那就看看***.com/questions/34090734/… 【参考方案1】:

对您的正则表达式进行关闭但微小的更改将获得您想要的输出。当您想使用RegexpParser 语法获得通配符时,您应该使用.* 而不是*,例如VB.* 而不是 VB*

>>> from nltk import word_tokenize, pos_tag, RegexpParser
>>> text = "This has allowed the device to start, and I then see glitches which is not nice."
>>> tagged_text = pos_tag(word_tokenize(text))    
>>> g = r"""
... VP: <VB.*><DT><NN.*>
... """
>>> p = RegexpParser(g); p.parse(tagged_text)
Tree('S', [('This', 'DT'), ('has', 'VBZ'), Tree('VP', [('allowed', 'VBN'), ('the', 'DT'), ('device', 'NN')]), ('to', 'TO'), ('start', 'VB'), (',', ','), ('and', 'CC'), ('I', 'PRP'), ('then', 'RB'), ('see', 'VBP'), ('glitches', 'NNS'), ('which', 'WDT'), ('is', 'VBZ'), ('not', 'RB'), ('nice', 'JJ'), ('.', '.')])

请注意,您正在捕捉Tree(AdvP, [('then', 'RB'), ('see', 'VB')]),因为标签正是RBVB。因此,在这种情况下,语法中的通配符(即 `"""AdvP: """)会被忽略。

另外,如果是两种不同类型的短语,最好使用 2 个标签而不是一个。而且(我认为)通配符后的字符串结尾有点多余,所以最好:

g = r"""
VP:<VB.*><DT><NN.*> 
AdvP: <RB.*><VB.*|JJ.*|NN.*>
"""

【讨论】:

太棒了.. 感谢@alvas,感谢您的帮助,我也删除了多余的字符串结尾。它现在可以工作了。关于短语标签,我打算保持不变,因为我想稍后根据subtree.label 将两种短语类型过滤到同一个列表中。如果我在列表中提到多个标签,例如if subtree.node in ("VP","AdvP"),则该列表是不可散列的。这就是为什么我更喜欢为两种类型的短语保留相同的标签。这会在解析中带来任何问题。 ? 规则可能是分层的,如果它们是相同的标签。不确定解析数据时它会做什么,但我猜它应该可以工作。 是否有使用 NLTK 正则表达式分块器进行分块的权威指南?将上述内容更改为“*”时,我的数据取得了平庸的成功。 NLTK 章节 (nltk.org/howto/chunk.html) 真的是最好的来源吗? 我也在寻找 NLTK regex chunker 的综合资源,但到目前为止我找到的最好的是 guru99.com/pos-tagging-chunking-nltk.html。我仍在寻找更全面的资源。

以上是关于NLTK RegEx Chunker 未使用通配符捕获已定义的语法模式的主要内容,如果未能解决你的问题,请参考以下文章

不懂NLTK Regex Parsing Format

NLTK - nltk.tokenize.RegexpTokenizer - 正则表达式未按预期工作

Python nltk.clean_html 未实现

python 字典Chunker

Python Pandas Regex:在列中搜索带有通配符的字符串并返回匹配项[重复]

Python NLTK pos_tag 未返回正确的词性标记