Chunking Stanford命名实体识别器(NER)输出NLTK格式

时间:2014-12-23 22:46:15

标签: python nlp nltk stanford-nlp named-entity-recognition

我在NLTK中使用NER来查找句子中的人员,地点和组织。我能够产生这样的结果:

[(u'Remaking', u'O'), (u'The', u'O'), (u'Republican', u'ORGANIZATION'), (u'Party', u'ORGANIZATION')]

使用它可以将所有东西组合在一起吗? 我想要的是这样的:

u'Remaking'/ u'O', u'The'/u'O', (u'Republican', u'Party')/u'ORGANIZATION'

谢谢!

4 个答案:

答案 0 :(得分:8)

它看起来很长但是它确实起作用了:

ner_output = [(u'Remaking', u'O'), (u'The', u'O'), (u'Republican', u'ORGANIZATION'), (u'Party', u'ORGANIZATION')]
chunked, pos = [], ""
for i, word_pos in enumerate(ner_output):
    word, pos = word_pos
    if pos in ['PERSON', 'ORGANIZATION', 'LOCATION'] and pos == prev_tag:
        chunked[-1]+=word_pos
    else:
        chunked.append(word_pos)
    prev_tag = pos

clean_chunked = [tuple([" ".join(wordpos[::2]), wordpos[-1]]) if len(wordpos)!=2 else wordpos for wordpos in chunked]

print clean_chunked

[OUT]:

[(u'Remaking', u'O'), (u'The', u'O'), (u'Republican Party', u'ORGANIZATION')]

更多详情:

第一个for-loop"带内存"实现这样的目标:

[(u'Remaking', u'O'), (u'The', u'O'), (u'Republican', u'ORGANIZATION', u'Party', u'ORGANIZATION')]

您将意识到所有名称Enitties将在元组中包含多于2个项目,您想要的是单词作为列表中的元素,即'Republican Party'中的(u'Republican', u'ORGANIZATION', u'Party', u'ORGANIZATION'),所以你会做这样的事情来获得偶数元素:

>>> x = [0,1,2,3,4,5,6]
>>> x[::2]
[0, 2, 4, 6]
>>> x[1::2]
[1, 3, 5]

然后你也意识到NE元组中的最后一个元素是你想要的标记,所以你会做`

>>> x = (u'Republican', u'ORGANIZATION', u'Party', u'ORGANIZATION')
>>> x[::2]
(u'Republican', u'Party')
>>> x[-1]
u'ORGANIZATION'

它有点特别和冗长,但我希望它有所帮助。在这里它是一个功能,祝福圣诞节:

ner_output = [(u'Remaking', u'O'), (u'The', u'O'), (u'Republican', u'ORGANIZATION'), (u'Party', u'ORGANIZATION')]


def rechunk(ner_output):
    chunked, pos = [], ""
    for i, word_pos in enumerate(ner_output):
        word, pos = word_pos
        if pos in ['PERSON', 'ORGANIZATION', 'LOCATION'] and pos == prev_tag:
            chunked[-1]+=word_pos
        else:
            chunked.append(word_pos)
        prev_tag = pos


    clean_chunked = [tuple([" ".join(wordpos[::2]), wordpos[-1]]) 
                    if len(wordpos)!=2 else wordpos for wordpos in chunked]

    return clean_chunked


print rechunk(ner_output)

答案 1 :(得分:3)

这实际上是在CoreNLP的下一个版本中,名称为MentionsAnnotator。它可能无法直接从NLTK获得,除非NLTK人员希望支持它以及标准的斯坦福NER接口。

在任何情况下,目前您都必须复制我已链接到的代码(使用LabeledChunkIdentifier进行脏工作)或者用Python编写自己的后处理器。

答案 2 :(得分:2)

您可以使用标准NLTK方式使用 nltk.Tree 来表示块。这可能意味着您必须稍微更改您的表示。

我通常所做的是将 NER标记的句子表示为三元组列表

sentence = [('Andrew', 'NNP', 'PERSON'), ('is', 'VBZ', 'O'), ('part', 'NN', 'O'), ('of', 'IN', 'O'), ('the', 'DT', 'O'), ('Republican', 'NNP', 'ORGANIZATION'), ('Party', 'NNP', 'ORGANIZATION'), ('in', 'IN', 'O'), ('Dallas', 'NNP', 'LOCATION')]

当我使用外部工具对NER标记句子时,我这样做。现在你可以将这句话转换为NLTK表示法:

from nltk import Tree


def IOB_to_tree(iob_tagged):
    root = Tree('S', [])
    for token in iob_tagged:
        if token[2] == 'O':
            root.append((token[0], token[1]))
        else:
            try:
                if root[-1].label() == token[2]:
                    root[-1].append((token[0], token[1]))
                else:
                    root.append(Tree(token[2], [(token[0], token[1])]))
            except:
                root.append(Tree(token[2], [(token[0], token[1])]))

    return root


sentence = [('Andrew', 'NNP', 'PERSON'), ('is', 'VBZ', 'O'), ('part', 'NN', 'O'), ('of', 'IN', 'O'), ('the', 'DT', 'O'), ('Republican', 'NNP', 'ORGANIZATION'), ('Party', 'NNP', 'ORGANIZATION'), ('in', 'IN', 'O'), ('Dallas', 'NNP', 'LOCATION')]
print IOB_to_tree(sentence)

表示类型的变化是有道理的,因为你肯定需要用于NER标记的POS标签。

最终结果如下:

(S
  (PERSON Andrew/NNP)
  is/VBZ
  part/NN
  of/IN
  the/DT
  (ORGANIZATION Republican/NNP Party/NNP)
  in/IN
  (LOCATION Dallas/NNP))

答案 3 :(得分:1)

以下是使用 itertools groupby 迭代器对Stanford NER结果进行分组的另一个简短实现:

def grouptags(tags, ignore="O", join=" "):
    from itertools import groupby
    for c,g in groupby(tags, lambda t: t[1]):
        if ignore is None or c != ignore:
            if join is None:
                entity = [e for e,_ in g]
            else:
                entity = join.join(e for e,_ in g)
            yield(c, entity)

函数 grouptags 有两个选项:

  • 忽略:指定被忽略并从输出中省略的类(默认值:“O”)。如果为None,则返回所有实体。
  • join :指定用于连接部件的字符(默认值:“”)。如果,则部件将作为列表以未加入的方式返回。