簡體   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