【问题标题】:How to conduct nested named entity recognition in OpenNLP?如何在 OpenNLP 中进行嵌套命名实体识别?
【发布时间】:2015-03-16 15:52:46
【问题描述】:

我目前正在开发一个 Java Web 服务器项目,该项目需要使用自然语言处理,特别是 命名实体识别 (NER)。

我使用 OpenNLP for java,因为添加自定义训练数据很容易。它完美地工作。

但是,我还需要能够提取实体内部的实体(嵌套命名实体识别)。我尝试在 OpenNLP 中执行此操作,但出现解析错误。所以我的猜测是 OpenNLP 很遗憾不支持嵌套实体。

这是我需要解析的示例:

提醒我[START:reminder][START:contact]约翰[END][ START:contact]查理[END][END]

如果这不能通过 OpenNLP 实现,是否有任何其他 Java NLP 库可以做到这一点。如果根本没有 Java 库,是否有任何其他语言的 NLP 库可以做到这一点?

请帮忙。谢谢!

【问题讨论】:

  • 你有没有试过只训练两者?而不是嵌套它们,只需维护两个不同的模型。

标签: java nlp opennlp named-entity-recognition


【解决方案1】:

使用这个python源代码(Python 3)https://gist.github.com/ttpro1995/cd8c60cfc72416a02713bb93dff9ae6f

它会为您创建多个非嵌套版本的嵌套数据。

对于下面的输入语句(输入数据必须先tokenize,所以和周围的东西有空格)

Remind me to <START:reminder> give some presents to <START:contact> John <END> and <START:contact> Charlie <END> <END> .

它输出多个具有不同嵌套级别的句子。

Remind me to give some presents to John and Charlie .
Remind me to <START:reminder> give some presents to John and Charlie <END> .
Remind me to give some presents to <START:contact> John <END> and <START:contact> Charlie <END> .

完整的源代码在这里快速复制粘贴

import sys

END_TAG = 0
START_TAG = 1
NOT_TAG = -1

def detect_tag(in_token):
    """
    detect tag in token
    :param in_token:
    :return:
    """
    if "<START:" in in_token:
        return START_TAG
    elif "<END>" == in_token:
        return END_TAG

    return NOT_TAG

def remove_nest_tag(in_str):
    """
    với <START:ORGANIZATION> Sở Cảnh sát Phòng cháy , chữa cháy ( PCCC ) và cứu nạn , cứu hộ <START:LOCATION> Hà Nội <END> <END>
    :param in_str:
    :return:
    """
    state = 0
    taglist = []
    tag_dict = dict()
    sentence_token = in_str.split()
    ## detect token tag
    max_nest = 0

    for index, token in enumerate(sentence_token):
        # print(token + str(detect_tag(token)))
        tag = detect_tag(token)
        if tag > 0:
            state += 1
            if max_nest < state:
                max_nest = state
            token_info = (index, state, token)
            taglist.append(token_info)
            tag_dict[index] = token_info
        elif tag == 0:
            token_info = (index, state, token)
            taglist.append(token_info)
            tag_dict[index] = token_info
            state -= 1


    generate_sentences = []
    for state in range(max_nest+1):
        generate_sentence_token = []
        for index, token in enumerate(sentence_token):
            if detect_tag(token) >= 0: # is a tag
                token_info = tag_dict[index]
                if token_info[1] == state:
                    generate_sentence_token.append(token)
            elif detect_tag(token) == -1 : # not a tag
                generate_sentence_token.append(token)
        sentence = ' '.join(generate_sentence_token)
        generate_sentences.append(sentence)
    return generate_sentences


    # generate sentence
    print(taglist)

def test():
    tstr2 = "Remind me to <START:reminder> give some presents to <START:contact> John <END> and <START:contact> Charlie <END> <END> ."
    result = remove_nest_tag(tstr2)
    print("-----")
    for sentence in result:
        print(sentence)

if __name__ == "__main__":
    """
    un-nest dataset for opennlp name
    """
    # test()
    # test()
    if len(sys.argv) > 1:
        inpath = sys.argv[1]
        infile = open(inpath, 'r')
        outfile = open(inpath+".out", 'w')
        for line in infile:
            sentences = remove_nest_tag(line)
            for sentence in sentences:
                outfile.write(sentence+"\n")
        outfile.close()
    else:
        print("usage: python unnest_data.py input.txt")

【讨论】:

    【解决方案2】:

    出于名称实体识别(基于 Java)的目的,我使用以下内容:

    1. Apache UIMA
    2. 清除TK

    https://github.com/merishav/cleartk-tutorials

    您可以为您的用例训练模型,我已经针对人、地点、出生日期、职业进行了 NER 训练。 ClearTK 为您提供了 MalletCRFClassifier 的包装器。

    【讨论】:

      【解决方案3】:

      简短的回答是:

      1. 这无法使用仅适用于连续实体的 openNLP NER 实现,因为它使用BIO 标记方案。
      2. 我不知道任何语言的任何库都可以做到这一点。

      我认为你对实体的概念进行了过多的扩展,它习惯性地与人、地点、组织、基因名称等相关联。 但不能识别文本中的复杂结构。

      为此,您需要考虑一个更详细的解决方案,考虑到句子的语法结构,这可以使用像OpenNLP 中的解析器来获得,并可能将其与NER 进程。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-10-20
        • 1970-01-01
        • 1970-01-01
        • 2013-02-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多