当前位置: 首页 > 知识库问答 >
问题:

如何在OpenNLP中进行嵌套命名实体识别?

莘昊
2023-03-14

我目前正在从事一个java web服务器项目,该项目需要使用自然语言处理,特别是实体识别(Entity Recognition,NER)。

我在java中使用OpenNLP,因为添加自定义训练数据很容易。它工作得很好。

然而,我还需要能够提取实体内部的实体(嵌套命名实体识别)。我试着在OpenNLP中这样做,但我遇到了解析错误。所以我猜OpenNLP很遗憾不支持嵌套实体。

下面是一个我需要解析的示例

提醒我[开始:提醒]给[开始:联系]约翰[结束]和[开始:联系]查理[结束][结束]一些礼物。

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

请帮忙。谢谢

共有3个答案

林项明
2023-03-14

使用以下python源代码(python 3)https://gist.github.com/ttpro1995/cd8c60cfc72416a02713bb93dff9ae6f

可以为您创建多个非嵌套版本的嵌套数据。

对于下面的输入句子(输入数据必须首先标记化,所以和周围的东西之间有空格)

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")
茹高义
2023-03-14

为了实现名称实体识别(基于Java),我使用以下方法:

  1. Apache UIMA
  2. ClearTK

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

您可以为您的用例培训模型,我已经为NER培训了人员、地点、出生日期和职业。ClearTK为您提供了malletcrf分类器的包装。

米丰
2023-03-14

简单的回答是:

  1. 这无法使用openNLP NER来实现,因为它使用BIO标记方案,因此仅适用于连续实体。
  2. 我不知道任何语言的图书馆能够做到这一点。

我认为你对实体的概念延伸得太多了,它通常与人、地方、组织、基因名称等联系在一起。但与文本中复杂结构的识别无关。

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

 类似资料:
  • 问题内容: 好的,我有以下代码来训练来自OpenNLP的NER标识符 我不知道我是否做错了什么,如果缺少什么,但是分类不起作用。我认为train.txt错误。 *发生 *的错误 是所有令牌仅被分类为一种类型。 我的train.txt数据类似于以下示例,但是条目的变化和数量更多。另一件事是,我每次都从文本中逐字逐句地查找,而不是所有标记。 有人可以证明我做错了吗? 问题答案: 您的训练数据不正确。

  • 有人能指出openNLP NameFinder模块使用的算法吗?代码很复杂,只有很少的文档记录,并且将其作为黑匣子(提供默认模型)使用给我的印象是它主要是启发式的。以下是一些输入和输出示例: 输入: 约翰·史密斯很沮丧。 约翰·史密斯很沮丧。 巴拉克·奥巴马感到沮丧。 乌戈·查韦斯很沮丧。(不再) 杰夫·阿特伍德很沮丧。 刘冰对openNLP NER模块感到失望。 诺姆·乔姆斯基对这个世界感到沮丧

  • 我正在尝试阿尔巴尼亚语的OpenNLP。为此,我正在使用OPenNLP并尝试用阿尔巴尼亚语构建人员、位置和组织实体识别的模型。我正在构建我自己的语料库,但我需要一位Open NLP专家来确认我以下疑问:1-我是否应该为每个模型构建一个单独的语料库,例如,对于人构建一个只有标签存在的语料库?2-是否可以在相同的语料库中标记人员、位置和组织,并使用它来训练能够提取所有三种实体类型的单个模型?3-是否有

  • 问题内容: 我正在寻找Java的简单但“足够好”的命名实体识别库(和字典),我正在处理电子邮件和文档并提取一些“基本信息”,例如:名称,地点,地址和日期 我一直在环顾四周,大多数似乎都是沉重的一面和完整的NLP项目。 有什么建议吗? 问题答案: 顺便说一句,我最近遇到了OpenCalais,它似乎具有我要照顾的功能。

  • 我知道Apache OpenNLP使用MaxEnt模型作为其NER标记器。但是Apache OpenNLP在运行其命名实体识别(NER)模型时(默认情况下)使用了哪些功能?以及我们如何在OpenNLP(Java实现)中合并/自定义新功能?

  • 我想在一个特定的领域进行NER实验,即从意大利语的旅行优惠中提取位置名称。 到目前为止,我需要自己准备训练,所以我要把 在我的培训集中的一些报价中添加标签。 但在查看OpenNLP关于如何为NER进行培训的文档时,我最终遇到了几个问题: 1) 在定义开始/结束标记时,我可以自由使用标记中的任何名称(我在上面几行写了“某物”),或者是否有要绑定的限制集? 2) 我注意到对培训工具的调用 将表示语言的