Извлечение поддерева Дерево NLTK

Мне нужна небольшая помощь с деревьями NLTK.

Я пытаюсь извлечь некоторые поддеревья из этого французского дерева:

Исходное дерево

(SENT (NP-SUJ↓ (PRO=H Personne)) (VN=H (ADV* ne) (V=H sait)) (ADV* exactement) (PONCT* .))

Я хочу только извлечь деревья, имеющие «= H» в конце метки POS, а затем добавить родительский узел:

Вот так: (NP-SUJ↓ (PRO=H Personne)) and this: (VN=H (V=H sait))

И я написал функцию для этого:

def AddParent(tree):
    grammar = []
    for subtree in tree.subtrees():
        if subtree.height()==2 and subtree.label().endswith("=H"):
            PartialTree = ParentedTree(subtree.parent().label(), 
                               [ParentedTree(subtree.label(), subtree)])
            grammar.append(PartialTree)
    return grammar

#Test
pt = ParentedTree.fromstring("(SENT (NP-SUJ↓ (PRO=H Personne)) (VN=H (ADV* ne) (V=H sait)) (ADV* exactement) (PONCT* .))")
AddParent(pt)
[ParentedTree('NP-SUJ↓', [ParentedTree('PRO=H', ['Personne'])]), 
ParentedTree('VN=H', [ParentedTree('V=H', ['sait'])])]

У меня здесь две проблемы: во-первых, я хочу продолжать добавлять информацию в эти поддеревья из исходного дерева. Например, я хочу продолжать добавлять узлы-предки, а затем дочерние, чтобы сделать что-то вроде этого:

(SENT (NP-SUJ↓ ) (VN=H (V=H sait)))

Поддерево

Но я потерял след оригинального дерева...

Во-вторых, функция parent() возвращает все содержащиеся в ней поддеревья. И я просто хочу иметь определенные узлы.

Каким будет хороший подход для извлечения этого последнего поддерева???

Большое спасибо за Вашу помощь! Я новичок в этом, но мне очень нравится!


person Jonathan    schedule 16.06.2016    source источник


Ответы (1)


Я не могу сказать, что понимаю вашу жалобу на parent() (возможно, вы имели в виду subtrees()?), но есть более простые способы получить доступ к поддеревьям:

  1. Поверхностное улучшение: функция subtrees() принимает аргумент filter, поэтому вам не нужно проверять возвращаемые поддеревья в коде:

    for subtree in tree.subtrees(filter=lambda t: t.label().endswith("=H"))
    
  2. Поддерево — это ссылка на часть исходного дерева. Если вы не изменяете его, он по-прежнему является частью исходного, и вы можете подниматься по дереву (поскольку вы используете «родительские» деревья). Фактически, обратите внимание, что если вы вносите изменения в содержимое поддерева, исходное дерево будет изменено. Но вместо того, чтобы встраивать найденное дерево в новый узел, создайте совершенно новую копию:

    partial = ParentedTree(subtree.parent().label(), [ subtree.copy() ])
    

    Затем вы можете свободно удалять или изменять ветки в копии, и у вас все еще есть исходные tree и subtree для работы.

  3. Хотя вы можете использовать метод parent(), чтобы подняться вверх по дереву, я часто нахожу более удобным работать с "позициями дерева". Позиция дерева — это кортеж целых чисел, который функционирует как путь вниз по дереву (используйте его как целочисленный индекс в списке). Чтобы найти родителя, вам просто нужно отрезать последний элемент древовидной позиции:

    for postn in tree.treepositions():
        if tree[postn].label().endswith("=H"):
            parentpos = postn[:-1]   # everything but the last element
            partial = Tree(tree[parentpos].label(), [ tree[postn] ])
    

    Обратите внимание, что если вы используете этот метод, вам больше не нужен метод parent(), и, следовательно, вы можете использовать Tree, а не ParentedTree.

Вышеупомянутое, вероятно, не делает именно то, что вы хотели (трудно понять, что именно вы делаете), но я надеюсь, что вы поняли картину.

person alexis    schedule 16.06.2016
comment
Большое спасибо! Это именно то, что я искал, но я не знал, как это сделать. - person Jonathan; 17.06.2016
comment
Рад слышать это. Поскольку мой ответ решил вашу проблему, примите его, нажав на большую галочку слева от него. (Вы также можете проголосовать за любой вопрос или ответ на этом сайте, который вы считаете полезным.) - person alexis; 17.06.2016