如何在没有 IOB 标签的情况下使用 Hugging Face 的转换器管道重建文本实体?
Posted
技术标签:
【中文标题】如何在没有 IOB 标签的情况下使用 Hugging Face 的转换器管道重建文本实体?【英文标题】:How to reconstruct text entities with Hugging Face's transformers pipelines without IOB tags? 【发布时间】:2020-07-11 05:44:15 【问题描述】:我一直在寻找将 Hugging Face 的管道用于 NER(命名实体识别)。但是,它以内部-外部-开始 (IOB) 格式返回实体标签,但 without the IOB labels。所以我无法将管道的输出映射回我的原始文本。此外,输出以 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
【问题讨论】:
您能否提供完整的minimal reproducible example,包括您如何加载您的nlp_bert_lg
模型?
添加了@dennlinger
【参考方案1】:
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
【讨论】:
谢谢,这非常有帮助。请注意,参数现在命名为aggregation_strategy
【参考方案2】:
不幸的是,到目前为止(2.6 版,我认为即使是 2.7 版),仅使用 pipeline
功能也无法做到这一点。由于管道调用的__call__
函数只是返回一个列表,请参见the code here。这意味着您必须使用“外部”标记器执行第二个标记化步骤,这完全违背了管道的目的。
但是,您可以改用second example posted on the documentation,就在与您类似的示例下方。为了将来的完整性,这里是代码:
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 注释方案在其original paper 中列出了以下内容:
每行包含四个字段:单词、词性标记、块标记和命名实体标记。用 O 标记的词在命名实体之外,而 I-XXX 标记用于 XXX 类型的命名实体内的词。每当 XXX 类型的两个实体紧挨着彼此时,第二个实体的第一个词将被标记为 B-XXX,以表明它开始另一个实体。数据包含四种类型的实体:人员 (PER)、组织 (ORG)、位置 (LOC) 和杂项名称 (MISC)。该标记方案是最初由 Ramshaw 和 Marcus (1995) 提出的 IOB 方案。
意思是,如果您对(仍然拆分的)实体不满意,您可以连接所有后续的I-
标记实体,或者B-
后跟I-
标记。在这个方案中,两个不同的(直接相邻的)实体不可能都只用I-
标记。
【讨论】:
感谢您的回答!你知道它什么时候用##分割单词吗? 单词是根据“子词单元”的概念进行分割的,例如this article。从本质上讲,它强制使用更小的词汇表,同时仍然能够通过组合不同的子词来重现稀有词,这些子词由##
表示。即,可能有子词byte
、-
和pair
,但没有byte-pair
,因此它将由三个“组合”标记byte
、##-
、##pair
表示。完整的词汇由模型本身定义,请参阅vocab.txt
文件。以上是关于如何在没有 IOB 标签的情况下使用 Hugging Face 的转换器管道重建文本实体?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 TSX 使 StencilJS 组件在没有组件标签的情况下呈现?
如何在没有任何类名或 ID 的情况下使用 Javascript 或 JQuery 替换 HTML 标签