在 nltk 中组合两个正则表达式语法
Combine two regexp grammars in nltk
我正在使用 nltk
中的语法定义一个名词短语。 nltk
提供的例子是:
grammar = "NP: {<DT>?<NNP>*<NN>}"
那么如果我有一个像这样的句子:show me the Paris hospitals
,库可以检测到名词短语:
>>> s
'show me the Paris hospitals'
>>> grammar = "NP: {<DT>?<NNP>*<NNS>}"
>>> nltk.RegexpParser(grammar).parse(nltk.pos_tag(nltk.word_tokenize(s)))
Tree('S', [('show', 'VB'), ('me', 'PRP'), Tree('NP', [('the', 'DT'), ('Paris', 'NNP'), ('hospitals', 'NNS')])])
现在,句子可以用另一种方式写成:show me the hospitals of Paris
,因此我需要将语法更改为:
>>> grammar = "NP: {<DT>?<NNS><IN><NNP>}"
>>> s = "show me the hospitals in Paris"
>>> nltk.RegexpParser(grammar).parse(nltk.pos_tag(nltk.word_tokenize(s)))
Tree('S', [('show', 'VB'), ('me', 'PRP'), Tree('NP', [('the', 'DT'), ('hospitals', 'NNS'), ('in', 'IN'), ('Paris', 'NNP')])])
如何将两种语法组合成一个独特的语法?我无法弄清楚这两个语法的 OR 条件。
您可以在一个语法中定义两个 NP 规则:
grammar = """
NP: {<DT>?<NNP>*<NNS>}
NP: {<DT>?<NNS><IN><NNP>}
"""
或使用|
作为想要的OR
条件:
grammar = "NP: {<DT>?<NNP>*<NNS>|<DT>?<NNS><IN><NNP>}"
完整示例:
import nltk
sentence_1 = 'show me the Paris hospitals'
sentence_2 = "show me the hospitals in Paris"
grammar_1 = """
NP: {<DT>?<NNP>*<NNS>}
NP: {<DT>?<NNS><IN><NNP>}
"""
parser_1 = nltk.RegexpParser(grammar_1)
grammar_2 = "NP: {<DT>?<NNP>*<NNS>|<DT>?<NNS><IN><NNP>}"
parser_2 = nltk.RegexpParser(grammar_2)
for s in sentence_1, sentence_2:
tokens = nltk.word_tokenize(s)
pos_tags = nltk.pos_tag(tokens)
print(parser_1.parse(pos_tags))
print(parser_2.parse(pos_tags))
# outputs the same for both parsers:
# (S show/VB me/PRP (NP the/DT Paris/NNP hospitals/NNS))
# (S show/VB me/PRP (NP the/DT Paris/NNP hospitals/NNS))
# (S show/VB me/PRP (NP the/DT hospitals/NNS) in/IN Paris/NNP)
# (S show/VB me/PRP (NP the/DT hospitals/NNS) in/IN Paris/NNP)
我正在使用 nltk
中的语法定义一个名词短语。 nltk
提供的例子是:
grammar = "NP: {<DT>?<NNP>*<NN>}"
那么如果我有一个像这样的句子:show me the Paris hospitals
,库可以检测到名词短语:
>>> s
'show me the Paris hospitals'
>>> grammar = "NP: {<DT>?<NNP>*<NNS>}"
>>> nltk.RegexpParser(grammar).parse(nltk.pos_tag(nltk.word_tokenize(s)))
Tree('S', [('show', 'VB'), ('me', 'PRP'), Tree('NP', [('the', 'DT'), ('Paris', 'NNP'), ('hospitals', 'NNS')])])
现在,句子可以用另一种方式写成:show me the hospitals of Paris
,因此我需要将语法更改为:
>>> grammar = "NP: {<DT>?<NNS><IN><NNP>}"
>>> s = "show me the hospitals in Paris"
>>> nltk.RegexpParser(grammar).parse(nltk.pos_tag(nltk.word_tokenize(s)))
Tree('S', [('show', 'VB'), ('me', 'PRP'), Tree('NP', [('the', 'DT'), ('hospitals', 'NNS'), ('in', 'IN'), ('Paris', 'NNP')])])
如何将两种语法组合成一个独特的语法?我无法弄清楚这两个语法的 OR 条件。
您可以在一个语法中定义两个 NP 规则:
grammar = """
NP: {<DT>?<NNP>*<NNS>}
NP: {<DT>?<NNS><IN><NNP>}
"""
或使用|
作为想要的OR
条件:
grammar = "NP: {<DT>?<NNP>*<NNS>|<DT>?<NNS><IN><NNP>}"
完整示例:
import nltk
sentence_1 = 'show me the Paris hospitals'
sentence_2 = "show me the hospitals in Paris"
grammar_1 = """
NP: {<DT>?<NNP>*<NNS>}
NP: {<DT>?<NNS><IN><NNP>}
"""
parser_1 = nltk.RegexpParser(grammar_1)
grammar_2 = "NP: {<DT>?<NNP>*<NNS>|<DT>?<NNS><IN><NNP>}"
parser_2 = nltk.RegexpParser(grammar_2)
for s in sentence_1, sentence_2:
tokens = nltk.word_tokenize(s)
pos_tags = nltk.pos_tag(tokens)
print(parser_1.parse(pos_tags))
print(parser_2.parse(pos_tags))
# outputs the same for both parsers:
# (S show/VB me/PRP (NP the/DT Paris/NNP hospitals/NNS))
# (S show/VB me/PRP (NP the/DT Paris/NNP hospitals/NNS))
# (S show/VB me/PRP (NP the/DT hospitals/NNS) in/IN Paris/NNP)
# (S show/VB me/PRP (NP the/DT hospitals/NNS) in/IN Paris/NNP)