6

我一直在寻找将 Hugging Face 的管道用于 NER(命名实体识别)。但是,它返回的是 inside-outside-beginning (IOB) 格式的实体标签,但没有 IOB 标签。所以我无法将管道的输出映射回我的原始文本。此外,输出以 BERT 标记化格式进行屏蔽(默认模型是 BERT-large)。

例如:

from transformers import pipeline
nlp_bert_lg = pipeline('ner')
print(nlp_bert_lg('Hugging Face is a French company based in New York.'))

输出是:

[{'word': 'Hu', 'score': 0.9968873858451843, 'entity': 'I-ORG'},
{'word': '##gging', 'score': 0.9329522848129272, 'entity': 'I-ORG'},
{'word': 'Face', 'score': 0.9781811237335205, 'entity': 'I-ORG'},
{'word': 'French', 'score': 0.9981815814971924, 'entity': 'I-MISC'},
{'word': 'New', 'score': 0.9987512826919556, 'entity': 'I-LOC'},
{'word': 'York', 'score': 0.9976728558540344, 'entity': 'I-LOC'}]

如您所见,纽约分为两个标签。

如何将 Hugging Face 的 NER 管道映射回我的原始文本?

变形金刚版本:2.7

4

2 回答 2

17

5 月 17 日,一个新的拉取请求https://github.com/huggingface/transformers/pull/3957与您所要求的内容已合并,因此现在我们的生活变得更加轻松,您可以在管道中使用它

ner = pipeline('ner', grouped_entities=True)

并且您的输出将符合预期。目前您必须从主分支安装,因为还没有新版本。你可以通过

pip install git+git://github.com/huggingface/transformers.git@48c3a70b4eaedab1dd9ad49990cfaa4d6cb8f6a0
于 2020-05-20T09:07:36.933 回答
6

不幸的是,截至目前(2.6 版,我认为即使是 2.7 版),您不能仅使用该pipeline功能来做到这一点。由于__call__管道调用的函数只是返回一个列表,请参见此处的代码。这意味着您必须使用“外部”标记器执行第二个标记化步骤,这完全违背了管道的目的。

但是,相反,您可以使用文档中发布的第二个示例,就在与您的示例类似的下方。为了将来的完整性,这里是代码:

from transformers import AutoModelForTokenClassification, AutoTokenizer
import torch

model = AutoModelForTokenClassification.from_pretrained("dbmdz/bert-large-cased-finetuned-conll03-english")
tokenizer = AutoTokenizer.from_pretrained("bert-base-cased")

label_list = [
    "O",       # Outside of a named entity
    "B-MISC",  # Beginning of a miscellaneous entity right after another miscellaneous entity
    "I-MISC",  # Miscellaneous entity
    "B-PER",   # Beginning of a person's name right after another person's name
    "I-PER",   # Person's name
    "B-ORG",   # Beginning of an organisation right after another organisation
    "I-ORG",   # Organisation
    "B-LOC",   # Beginning of a location right after another location
    "I-LOC"    # Location
]

sequence = "Hugging Face Inc. is a company based in New York City. Its headquarters are in DUMBO, therefore very" \
           "close to the Manhattan Bridge."

# Bit of a hack to get the tokens with the special tokens
tokens = tokenizer.tokenize(tokenizer.decode(tokenizer.encode(sequence)))
inputs = tokenizer.encode(sequence, return_tensors="pt")

outputs = model(inputs)[0]
predictions = torch.argmax(outputs, dim=2)

print([(token, label_list[prediction]) for token, prediction in zip(tokens, predictions[0].tolist())])

这正是您正在寻找的东西。请注意,ConLL 注释方案在其原始论文中列出了以下内容:

每行包含四个字段:单词、词性标签、块标签和命名实体标签。用 O 标记的词在命名实体之外,而 I-XXX 标记用于 XXX 类型的命名实体内的词。每当 XXX 类型的两个实体紧挨着彼此时,第二个实体的第一个词将被标记为 B-XXX,以表明它开始另一个实体。数据包含四种类型的实体:人员 (PER)、组织 (ORG)、位置 (LOC) 和杂项名称 (MISC)。这种标记方案是最初由 Ramshaw 和 Marcus (1995) 提出的 IOB 方案。

意思是,如果您对(仍然拆分的)实体不满意,您可以连接所有后续I-标记的实体,或者B-后跟I-标记。在这个方案中,两个不同的(直接相邻的)实体都只用I-标签来标记是不可能的。

于 2020-04-01T08:41:19.540 回答