【问题标题】:Absolute position of leaves in NLTK treeNLTK 树中叶子的绝对位置
【发布时间】:2016-08-18 07:11:53
【问题描述】:

我正在尝试查找给定句子中名词短语的跨度(开始索引,结束索引)。下面是提取名词短语的代码

sent=nltk.word_tokenize(a)
sent_pos=nltk.pos_tag(sent)
grammar = r"""
    NBAR:
        {<NN.*|JJ>*<NN.*>}  # Nouns and Adjectives, terminated with Nouns

    NP:
        {<NBAR>}
        {<NBAR><IN><NBAR>}  # Above, connected with in/of/etc...
    VP:
        {<VBD><PP>?}
        {<VBZ><PP>?}
        {<VB><PP>?}
        {<VBN><PP>?}
        {<VBG><PP>?}
        {<VBP><PP>?}
"""

cp = nltk.RegexpParser(grammar)
result = cp.parse(sent_pos)
nounPhrases = []
for subtree in result.subtrees(filter=lambda t: t.label() == 'NP'):
  np = ''
  for x in subtree.leaves():
    np = np + ' ' + x[0]
  nounPhrases.append(np.strip())

对于 a = "美国内战,也称为美国内战或简称内战,是在几个南方奴隶州宣布分离后,于 1861 年至 1865 年在美国爆发的内战并形成了美利坚联盟国。”,提取的名词短语是

['美国内战', '战争', '州', '内战', '内战战斗', '美国', '几个南方', '州', '分裂国家', '同盟国','美国']。

现在我需要找到名词短语的跨度(短语的开始位置和结束位置)。例如,上述名词短语的跨度将是

[(1,3), (9,9), (12, 12), (16, 17), (21, 23), ....].

我对 NLTK 还很陌生,我研究过 http://www.nltk.org/_modules/nltk/tree.html。我尝试使用 Tree.treepositions() 但无法使用这些索引提取绝对位置。任何帮助将不胜感激。谢谢!

【问题讨论】:

    标签: python tree nlp nltk chunking


    【解决方案1】:

    没有任何隐式函数可以返回 https://github.com/nltk/nltk/issues/1214 突出显示的字符串/标记的偏移量

    但是您可以使用来自https://github.com/nltk/nltk/blob/develop/nltk/translate/ribes_score.py#L123RIBES score 使用的ngram 搜索器

    >>> from nltk import word_tokenize
    >>> from nltk.translate.ribes_score import position_of_ngram
    >>> s = word_tokenize("The American Civil War, also known as the War between the States or simply the Civil War, was a civil war fought from 1861 to 1865 in the United States after several Southern slave states declared their secession and formed the Confederate States of America.")
    >>> position_of_ngram(tuple('American Civil War'.split()), s)
    1
    >>> position_of_ngram(tuple('Confederate States of America'.split()), s)
    43
    

    (返回查询ngram的起始位置)

    【讨论】:

    • 感谢您的回复!但在 NP 'War' 的情况下,由于同一个词在句子中多次出现,position_of_ngram(tuple('War'.split()), s) 将返回第一次出现的索引,即 3 而提取的 NP 是在索引 9。有解决办法吗?再次感谢!
    • @Corleone,因为没有“偏移”的概念,所以您能做的最好的事情是获取 ngram 的第一个实例或递归获取“下一个”实例。
    • @alvas,谢谢!我想我会那样做。我试图接受答案,但我的业力目前还不够好:/
    【解决方案2】:

    这是另一种方法,它使用它们在树字符串中的绝对位置来增加标记。现在可以从任何子树的叶子中提取绝对位置。

    def add_indices_to_terminals(treestring):
        tree = ParentedTree.fromstring(treestring)
        for idx, _ in enumerate(tree.leaves()):
            tree_location = tree.leaf_treeposition(idx)
            non_terminal = tree[tree_location[:-1]]
            non_terminal[0] = non_terminal[0] + "_" + str(idx)
        return str(tree)
    

    示例用例

    >>> treestring = (S (NP (NNP John)) (VP (V runs)))
    >>> add_indices_to_terminals(treestring)
    (S (NP (NNP John_0)) (VP (V runs_1)))
    

    【讨论】:

      【解决方案3】:

      使用以下代码实现组成解析树的标记偏移量:

      def get_tok_idx_of_tree(t, mapping_label_2_tok_idx, count_label, i):
          if isinstance(t, str):
              pass
          else:
              if count_label[0] == 0:
                  idx_start = 0
              elif i == 0:
                  idx_start = mapping_label_2_tok_idx[list(mapping_label_2_tok_idx.keys())[-1]][0]
              else:
                  idx_start = mapping_label_2_tok_idx[list(mapping_label_2_tok_idx.keys())[-1]][1] + 1
      
              idx_end = idx_start + len(t.leaves()) - 1
              mapping_label_2_tok_idx[t.label() + "_" + str(count_label[0])] = (idx_start, idx_end)
              count_label[0] += 1
      
              for i, child in enumerate(t):
                  get_tok_idx_of_tree(child, mapping_label_2_tok_idx, count_label, i)
      
          
      

      下面是组成树:

      以上代码的输出:

      {'ROOT_0': (0, 3), 'S_1': (0, 3), 'VP_2': (0, 2), 'VB_3': (0, 0), 'NP_4': (1, 2), 'DT_5': (1, 1), 'NN_6': (2, 2), '._7': (3, 3)}
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-02-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-07-20
        • 2023-03-09
        • 2013-04-30
        相关资源
        最近更新 更多