关于python:比较两个相似的,不同的NLTK树

Comparing two similar, non-identical NLTK trees

我正在尝试编写一个包含两个句子并检查它们是否相似的程序。我不想使用成熟的解析器,而是使用一种我认为我最常遇到的简单语法来创建一个解析器。现在,我对句子中的名词短语感兴趣。检查标记为名词短语的子树是否相等将很容易。我想为此添加更多内容,并让用户决定是否接受缺失/不匹配的限定符(部分匹配)。

输出树的格式为(S(NP The / DT bag / NN)是/ VBZ(JP blue / JJ)),其中我定义了语法名词短语(NP)和形容词短语(JP)

为了进行匹配,我考虑了一些路线:

  • 删除相关树中的确定器节点,然后进行比较
  • 将所有确定器节点的值更改为一个公共值,例如X
  • 列出除标记为" DT"的叶节点以外的所有叶节点的列表

我是python的新手,在这里面临一些问题:

  • 如果我编写一个递归函数来遍历名词短语树,直到它到达带有确定器的叶子,我将无法修改原始树中的值,因为它仅传递值。

  • 我发现的关于nltk树的唯一删除功能是一种要求删除相对于树根的确切索引的函数,格式为[0,0](如果它是树的最左子级)。根节点的最左子级。这很棘手,因为它很可能涉及每个节点的整数列表,这些整数随着树的高度而增长

  • 我创建了一个列表列表,其中每个列表都包含一个名词短语的所有叶子(不包括限定词),并进行了比较。

所以,我的问题是

如何从NLTK树中删除节点,而无需先获取其索引为[0,0,1,0,...]形式?

我又如何不使用索引而修改叶子值?(我想使用递归函数,并且每当函数到达叶子时,我都想修改它)

如果不可能,那么如何获得叶子的索引?我为此感到难过。 Nltk树具有树位置功能,但这仅适用于子树。与其他节点相比,Python是否认为叶子是不同的类型?因为树位置不适用于我的叶子。这可能是因为我的叶子是元组,而不仅仅是字符串,但是我不知道如何更改它,因为这是pos标记程序的输出。那么,是否有某种方法可以将我的叶子(即[DT / DT]形式的元组)替换为形式为(DT the)的子树?再次定义递归过程将不会修改原始树。

有什么建议/意见吗?


好的,让我们一一解答。

1
tree = Tree.parse("(S (NP The/DT bag/NN) is/VBZ (JP blue/JJ))")

删除节点:

tree.remove(Tree('JP', ['blue/JJ']))

tree.remove('is/VBZ')

修改值。 您可以通过获取Tree成员的索引来做到这一点(请记住,它继承了list):

tree.index('is/VBZ')

但这又不是一个好方法。

遍历叶子的最佳方法是使用tree.leaves()获取叶子,然后通过tree.leaf_treeposition(index)获取索引,并使用这些索引就地修改/删除叶子。