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