繁体   English   中英

在NLTK解析树中转义括号

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM