首页 > 解决方案 > 如何在 Spacy v3 中使用 BILUO 模式更新 NER 模型?

问题描述

我想在 sm NER spacy 模型中添加一些 PERSON 词汇。为此,我使用 BILUO 模式标记了取自 ProPublica API 的国会官员的姓名。我看过很多关于使用带实体格式的字典的帖子。但到目前为止,在 v3 中找不到任何使用 BILUO 模式的地方。我有我的数据作为元组列表。第一个值是字符串,第二个值是标记的实体。

data = [('Nanette Barragán', list(['B-PERSON', 'L-PERSON'])),
 ('Jack Bergman', list(['B-PERSON', 'L-PERSON'])),
 ('Andy Biggs', list(['B-PERSON', 'L-PERSON'])),
 ('Lisa Blunt Rochester', list(['B-PERSON', 'I-PERSON', 'L-PERSON'])),
 ('Anthony Brown', list(['B-PERSON', 'L-PERSON'])),
 ('Ted Budd', list(['B-PERSON', 'L-PERSON'])),
 ('Troy Balderson', list(['B-PERSON', 'L-PERSON'])),
 ('James Baird', list(['B-PERSON', 'L-PERSON'])),
 ('Tim Burchett', list(['B-PERSON', 'L-PERSON']))]

我想将这些名称添加到已加载的 NER 模型中。我一直在遵循以下步骤:我们如何使用 Spacy minibatch 和 GoldParse 使用 BILUO 标记方案训练 NER 模型?. 这指的是 v2,但是 v3 不再使用 GoldParse,如下面的 Spacy v3 文档中的文本所示:

  The Language.update, Language.evaluate and 
  TrainablePipe.update methods now all take batches of Example 
  objects instead of Doc and GoldParse objects, or raw text and a 
  dictionary of annotations.

Example 的文档显示在这里:https ://spacy.io/api/example

下面是我更新的脚本

import spacy
from spacy import displacy
import en_core_web_sm
import random 
from spacy.util import minibatch, compounding
from spacy.tokens import Doc
from spacy.training import Example

nlp = en_core_web_sm.load()


if 'ner' not in nlp.pipe_names:
    nlp.add_pipe('ner', last=True)
else:
    ner = nlp.get_pipe('ner')

ner.add_label('PERSON')

other_pipes = [pipe for pipe in nlp.pipe_names if pipe != 'ner']
with nlp.disable_pipes(*other_pipes):  # only train NER
    optimizer = nlp.create_optimizer()
    tags = dict()
    for itn in range(10):
        print("Starting iteration " + str(itn))
        random.shuffle(data)
        losses = {}
        batches = minibatch(data, size=compounding(4.0, 16.0, 1.001))
        # type 2 with mini batch
        for batch in batches:
            texts, _ = zip(*batch)
            golds = [Example(Doc(nlp.vocab, words = t), references = a) for t,a in batch]
            nlp.update(
                texts,  # batch of texts
                golds,  # batch of annotations
                drop=0.4,  # dropout - make it harder to memorise data
                losses=losses,
                sgd=optimizer)

但是,我收到错误:

   Starting iteration 0
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
/var/folders/36/j_203fcj42q9bvnlt1sl3j640000gp/T/ipykernel_162/1201951981.py in <module>
     14         for batch in batches:
     15             texts, _ = zip(*batch)
---> 16             golds = [Example(Doc(nlp.vocab, words = t),references = a) for t,a in batch]
     17             nlp.update(
     18                 texts,  # batch of texts

/var/folders/36/j_203fcj42q9bvnlt1sl3j640000gp/T/ipykernel_162/1201951981.py in <listcomp>(.0)
     14         for batch in batches:
     15             texts, _ = zip(*batch)
---> 16             golds = [Example(Doc(nlp.vocab, words = t),references = a) for t,a in batch]
     17             nlp.update(
     18                 texts,  # batch of texts

~/.pyenv/versions/3.8.3/lib/python3.8/site-packages/spacy/training/example.pyx in spacy.training.example.Example.__init__()

TypeError: __init__() takes exactly 2 positional arguments (1 given)

我还尝试像在原始代码中一样替换下面的 Doc var,但仍然是同样的错误。

 golds = [Example(nlp.make_doc(t),references = a) for t,a in batch]

我不知道如何克服这个错误。任何帮助是极大的赞赏!

标签: pythonspacynamed-entity-recognitionspacy-3

解决方案


发生该错误是因为您将关键字参数传递referencesExample类构造函数,但构造函数采用两个位置参数和一个仅关键字参数alignment. 也就是说,references不是 Example 构造函数的关键字参数。

这应该可以解决该错误。

golds = [Example(Doc(nlp.vocab, words = t), a) for t, a in batch]

我不确定您发布的数据是否代表您的实际数据。如果是这样,在其上训练 NER 可能没有太大价值,因为它只是一个实体列表,周围没有上下文。在这种情况下,您最好使用像PhraseMatcher这样的基于规则的方法


推荐阅读