2016-10-18 3 views
-1

Я работаю с набором данных Standford Sentiment Treebank, и я пытаюсь извлечь листья и узлы. Данные приведены нижеNLTK отдельно извлекать листья и нелистовые узлы

(3 (2 (2 The) (2 Rock)) (4 (3 (2 is) (4 (2 destined) (2 (2 (2 (2 (2 to) (2 (2 be) (2 (2 the) (2 (2 21st) (2 (2 (2 Century) (2 's)) (2 (3 new) (2 (2 ``) (2 Conan)))))))) (2 '')) (2 and)) (3 (2 that) (3 (2 he) (3 (2 's) (3 (2 going) (3 (2 to) (4 (3 (2 make) (3 (3 (2 a) (3 splash)) (2 (2 even) (3 greater)))) (2 (2 than) (2 (2 (2 (2 (1 (2 Arnold) (2 Schwarzenegger)) (2 ,)) (2 (2 Jean-Claud) (2 (2 Van) (2 Damme)))) (2 or)) (2 (2 Steven) (2 Segal))))))))))))) (2 .))) 

, что я хотел так что-то выглядит следующим образом:

я) Листья с меткой (уни-грамм):

[(2 The), (2 Rock), (2 is), (2 destined),...] 

II) Uper узлов с этикетками (bi-gram):

[(2 (2 the) (2 Rock)), (2 (2 ``) (2 Conan)), (2 (2 Century) (2 's)),..] 

до тех пор, пока я не доберусь до корня дерева.

Я попытался использовать регулярное выражение, чтобы выполнить это, но он не может корректно выводить.

Код у меня (для уни-грамм):

import re 
import nltk 

location = '.../NLP/Standford_Sentiment_Tree_Data_Set/' +\ 
      'trainDevTestTrees_PTB/trees/train.txt' 
text = open(location, 'r') 

test = text.readlines()[0] 
text.close() 

uni_regex = re.compile(r'(\([0-4] \w+\))') 
temp01 = uni_regex.findall(test) 

# bi-gram 
bi_regex = re.compile(r'(\([0-4] \([0-4] \w+\) \([0-4] \w+\)\))') 
temp02 = bi_regex.findall(test) 

Приведенный выше код выхода:

['(2 The)', '(2 Rock)', '(2 is)', '(2 destined)', '(2 to)', '(2 be)', '(2 the)', '(2 21st)', '(2 Century)', '(3 new)',...] 

и не может захватить (2 ``), (2 '') и извлекает (2 Jean) вместо (2 Jean-Claude)

Выход не записывается (2 (2``) (2 Conan))

Есть ли способ получить результат, который я хочу использовать nltk или какую-то конфигурацию regex, которая не пропустит никаких токенов?

Я искал и попытался изменить решение, представленное в NLTK tree data structure, finding a node, it's parent or children, но этот вопрос, похоже, касается поиска определенного слова в отпуске и отображения древовидной структуры, тогда как мне требуется, чтобы отступом решение напоминало приведенное выше п-граммы.

ответ

2

Не тратьте время на регулярные выражения, это то, для чего предназначены древовидные классы. Используйте Tree класс в NLTK как это:

mytree = "(3 (2 (2 The) (2 Rock)) (4 (3 (2 is) (4 (2 destined) (2 (2 (2 (2 (2 to) (2 (2 be) (2 (2 the) (2 (2 21st) (2 (2 (2 Century) (2 's)) (2 (3 new) (2 (2 ``) (2 Conan)))))))) (2 '')) (2 and)) (3 (2 that) (3 (2 he) (3 (2 's) (3 (2 going) (3 (2 to) (4 (3 (2 make) (3 (3 (2 a) (3 splash)) (2 (2 even) (3 greater)))) (2 (2 than) (2 (2 (2 (2 (1 (2 Arnold) (2 Schwarzenegger)) (2 ,)) (2 (2 Jean-Claud) (2 (2 Van) (2 Damme)))) (2 or)) (2 (2 Steven) (2 Segal))))))))))))) (2 .)))" 

>>> t = nltk.Tree.fromstring(mytree) 
>>> print(t) 
(3 
    (2 (2 The) (2 Rock)) 
    (4 
    (3 
     (2 is) 
     (4 
     (2 destined) 
     (2 
      ... 

Вы можете извлечь и сосчитать листья, и запросить соответствующие «treepositions» (путь к каждому листу, в виде списка):

>>> leafpos = [ t.leaf_treeposition(n) for n, x in enumerate(t.leaves()) ] 
>>> print(leafpos[0:3]) 
[(0, 0, 0), (0, 1, 0), (1, 0, 0, 0)] 

Наконец, вы можете идти вверх по treepositions, чтобы получить единицы вы хотите: поддерево доминировала узлом непосредственно над каждым листом, два шага выше каждого листа, и т.д.:

>>> level1_subtrees = [ t[path[:-1]] for path in leafpos ] 
>>> for x in level1_subtrees: 
...  print(x, end = " ") 
(2 The) (2 Rock) (2 is) (2 destined) (2 to) (2 be) (2 the) ... 

>>> level2_subtrees = [ t[path[:-2]] for path in leafpos ] 

Обратите внимание, однако, что поддеревья более высокого уровня не выглядят так, как вы себе представляете. Если вы поднимаетесь на два уровня из листа 3 (destined), например, вы не получите «bigram». Вы попадете в узел с пометкой 4, который доминирует над большинством остальных предложений. Возможно, вам действительно интересно перечислить все поддеревья? В этом случае просто перейдите к t.subtrees().

Если это не то, что вы хотите, посмотрите на API Tree и выберите другой способ выбрать нужные вам детали.

Смежные вопросы