如何在没有 IOB 标签的情况下使用 Hugging Face 的转换器管道重建文本实体?

问题描述 投票:0回答:4

我一直在寻找使用 Hugging Face 的管道进行 NER(命名实体识别)。但是,它以内部-外部开始 (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 Pipeline 映射回我的原始文本?

变形金刚版本:2.7

nlp tokenize transformer-model named-entity-recognition huggingface-transformers
4个回答
24
投票

编辑 12/2023: 如前所述,

grouped_entities
参数已被弃用。正确的方法是使用
源代码
中指出的aggregation_strategy参数。 例如:

text = 'Hugging Face is a French company based in New York.'
tagger = pipeline(task='ner', aggregation_strategy='simple')
named_ents = tagger(text)
pd.DataFrame(named_ents)

给出以下输出

[
   {
      "entity_group":"ORG",
      "score":0.96934015,
      "word":"Hugging Face",
      "start":0,
      "end":12
   },
   {
      "entity_group":"MISC",
      "score":0.9981816,
      "word":"French",
      "start":18,
      "end":24
   },
   {
      "entity_group":"LOC",
      "score":0.9982121,
      "word":"New York",
      "start":42,
      "end":50
   }
]

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

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

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

来完成
pip install git+git://github.com/huggingface/transformers.git@48c3a70b4eaedab1dd9ad49990cfaa4d6cb8f6a0

11
投票

如果你在 2022 年看到这个:

  • grouped_entities
    关键字现已弃用
  • 您应该使用
    aggregation_strategy
    :默认为
    None
    ,您正在寻找
    simple
    first
    average
    max
    -> 请参阅 AggregationStrategy
     类的 
    文档
from transformers import pipeline
import pandas as pd

text = 'Hugging Face is a French company based in New York.'

tagger = pipeline(task='ner', aggregation_strategy='simple')
named_ents = tagger(text)
pd.DataFrame(named_ents)
[{'entity_group': 'ORG',
  'score': 0.96934015,
  'word': 'Hugging Face',
  'start': 0,
  'end': 12},
 {'entity_group': 'MISC',
  'score': 0.9981816,
  'word': 'French',
  'start': 18,
  'end': 24},
 {'entity_group': 'LOC',
  'score': 0.9982121,
  'word': 'New York',
  'start': 42,
  'end': 50}]

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-
标签进行标记。


0
投票

截至 2024 年,我发现在

aggregation_strategy
NER 管道链接
中使用 pipeline
参数 您可以使用
first
average
max
---> 对 NER 预测分数进行操作(softmax 输出)

我在下面提供了一个小例子,其中

aggregation_strategy
average

# imports

from transformers import AutoTokenizer, AutoModelForTokenClassification
from transformers import pipeline
import warnings
warnings.filterwarnings("ignore")
import torch
model_id = "dslim/bert-base-NER" # hugging face

tokenizer_ner = AutoTokenizer.from_pretrained(model_id) # hugging face model

ner_model = AutoModelForTokenClassification.from_pretrained(model_id)

nlp = pipeline('ner',
              model = ner_model,
              tokenizer = tokenizer_ner,
              aggregation_strategy = 'average',
              device= None)

x = nlp('Hugging Face is a French company based in New York.')

print(x)

#output
#[{'entity_group': 'ORG', 'score': 0.72114974, 'word': 'Hugging Face', #'start': 0, 'end': 12}, {'entity_group': 'MISC', 'score': 0.99963593, 'word': #'French', 'start': 18, 'end': 24}, {'entity_group': 'LOC', 'score': #0.99922967, 'word': 'New York', 'start': 42, 'end': 50}]
© www.soinside.com 2019 - 2024. All rights reserved.