[英]Escape parentheses in NLTK parse tree
在NLTK中,我们可以将括号树转换为实际的Tree对象。 但是,当令牌包含括号时,解析不是您所期望的,因为NLTK将这些括号解析为新节点。
举个例子,拿一个句子
他们喜欢(d)很多
这可以解析为
(S (NP (PRP They)) (VP like(d) (NP (PRP it)) (NP (DT a) (NN lot))) (. .))
但是如果你用NLTK将它解析成树并输出它 - 很明显(d)
被解析为一个新节点,这并不奇怪。
from nltk import Tree
s = '(S (NP (PRP They)) (VP like(d) (NP (PRP it)) (NP (DT a) (NN lot))) (. .))'
tree = Tree.fromstring(s)
print(tree)
结果是
(S
(NP (PRP They))
(VP like (d ) (NP (PRP it)) (NP (DT a) (NN lot)))
(. .))
所以(d )
是VP内的节点,而不是标记的一部分like
。 树解析器中是否有一种方法可以转义括号?
最初我认为这是不可能的......但是在编写我的答案的过程中,我找到了一个解决方案。 然而,解决方案非常混乱,所以我将原来的答案留给了稍微好一点的解决方案。
nltk
允许您提供自定义正则表达式,以便您可以编写正则表达式来匹配转义的括号。 正则表达式([^\\s\\(\\)\\\\]+(\\\\(?=\\()\\([^\\s\\(\\)\\\\]+\\\\(?=\\))\\))*[\\\\]*)+
将匹配由反斜杠( \\
)转义的括号。 但是,这将包括每个叶子中的转义反斜杠,因此您必须编写叶函数来删除它们。 以下代码将正确解析它:
from nltk import Tree
s = '(S (NP (PRP They)) (VP like\(d\) (NP (PRP it)) (NP (DT a) (NN lot))) (. .))'
tree = Tree.fromstring(s, leaf_pattern=r"([^\s\(\)\\]+(\\(?=\()\([^\s\(\)\\]+\\(?=\))\))*[\\]*)+", read_leaf=lambda x: x.replace("\\(", "(").replace("\\)", ")"))
print(tree)
它输出:
(S
(NP (PRP They))
(VP like(d) (NP (PRP it)) (NP (DT a) (NN lot)))
(. .))
也许你可以要求nltk
匹配另一个括号:
from nltk import Tree
s = '[S [NP [PRP They]] [VP like(d) [NP [PRP it]] [NP [DT a] [NN lot]]] [. .]]'
tree = Tree.fromstring(s, brackets='[]')
print(tree)
打印出来:
(S
(NP (PRP They))
(VP like(d) (NP (PRP it)) (NP (DT a) (NN lot)))
(. .))
您可以使用pformat
方法(在调用print时在内部调用)获得不同的括号:
print(tree.pformat(parens='[]'))
打印出来:
[S
[NP [PRP They]]
[VP like(d) [NP [PRP it]] [NP [DT a] [NN lot]]]
[. .]]
传统方法是将括号转换为解析内的-LRB-
和-RRB-
。 大多数使用Penn Treebank数据的工具都支持这种转义(NLTK,CoreNLP和许多其他工具)。
NLTK支持这一点,但其默认的PTB样式标记化假设括号是单独的标记而不是可能的标记内部:
from nltk.tokenize.treebank import TreebankWordTokenizer, TreebankWordDetokenizer
t = TreebankWordTokenizer()
d = TreebankWordDetokenizer()
s = "They like(d) it a lot."
tokens = t.tokenize(s, convert_parentheses=True)
print("Tokens:", tokens)
detokenized = d.detokenize(tokens, convert_parentheses=True)
print("Detokenized:", detokenized)
输出:
Tokens: ['They', 'like', '-LRB-', 'd', '-RRB-', 'it', 'a', 'lot', '.']
Detokenized: They like (d) it a lot.
如果您在输入数据中自己转换括号而不插入额外的空格,则默认标记化和使用convert_parentheses=True
的去标记工作:
s = 'They like-LRB-d-RRB- it a lot.'
tokens = t.tokenize(s)
print("Tokens:", tokens)
detokenized = d.detokenize(tokens, convert_parentheses=True)
print("Detokenized:", detokenized)
输出:
Tokens: ['They', 'like-LRB-d-RRB-', 'it', 'a', 'lot', '.']
Detokenized: They like(d) it a lot.
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.