训练自己的模型并使用 spacy 添加新实体

Training own model and adding new entities with spacy

我一直在尝试使用与#887 相同的方法训练模型,只是为了测试用例。 我有一个问题,在 spacy 中导入训练语料库的最佳格式是什么。我有一个文本文件,其中包含需要新实体进行标记的实体列表。 让我解释一下我的情况,我遵循这样的 update.training 脚本:

nlp = spacy.load('en_core_web_md', entity=False, parser=False)

ner= EntityRecognizer(nlp.vocab, entity_types=['FINANCE'])

for itn in range(5):
    random.shuffle(train_data)
    for raw_text, entity_offsets in train_data:
        doc = nlp.make_doc(raw_text)
        gold = GoldParse(doc, entities=entity_offsets)

        nlp.tagger(doc)
        ner.update(doc, gold)
ner.model.end_training()

我将训练数据添加为 entity_offsets:

train_data = [
    ('Monetary contracts are financial instruments between parties', [(23, 44, 'FINANCE')])
]

这对于一个示例和新的实体标签来说工作正常。显然我希望能够添加多个示例。我的想法是创建一个带有标记句子的文本文件,问题是 spacy 需要什么格式的训练数据,我应该保持示例中的 entity_offset(这对于 1000 个句子来说将是一项非常乏味的任务)或是否有另一种方法来准备文件,例如:

financial instruments   FINANCE
contracts   FINANCE
Product OBJ
of O
Microsoft ORG
etc ...

以及如何使用上述方法在 spcay 中传递语料库?我必须使用新创建的模型还是可以将新实体添加到旧模型,如何实现?

更新 我设法导入了一个包含训练数据的文件,该文件可以被上述训练方法识别。 该列表将如下所示:

Financial instruments can be real or virtual documents, 0 21 FINANCE
The number of units of the financial instrument, 27 47 FINANCE
or the number of derivative contracts in the transaction, 17 37 BANKING
Date and time when the transaction was executed, 23 34 ORDER
...

但训练效果不佳,我想这是因为训练数据太少了。我将测试语料库中的所有条目都标记为 FINANCE 或全部标记为 BANKING。我的训练数据需要多大才能获得更好的性能?

我想我将不得不为可能的训练数据注释更大的语料库。可以用不同的方式完成吗?

spacy 命名实体识别器背后的算法是什么?

感谢您的帮助。

我的环境

spaCy 版本:1.7.3 平台:Windows-7-6.1.7601-SP1 Python版本:3.6.0 安装型号:en, en_core_web_md

要为实体识别器提供训练示例,您首先需要创建一个 GoldParse 实例 class。您可以以独立格式或令牌标记指定注释。

import spacy
import random
from spacy.gold import GoldParse
from spacy.language import EntityRecognizer

train_data = [
    ('Who is Chaka Khan?', [(7, 17, 'PERSON')]),
    ('I like London and Berlin.', [(7, 13, 'LOC'), (18, 24, 'LOC')])
]

nlp = spacy.load('en', entity=False, parser=False)
ner = EntityRecognizer(nlp.vocab, entity_types=['PERSON', 'LOC'])

for itn in range(5):
    random.shuffle(train_data)
    for raw_text, entity_offsets in train_data:
        doc = nlp.make_doc(raw_text)
        gold = GoldParse(doc, entities=entity_offsets)

        nlp.tagger(doc)
        ner.update(doc, gold)
ner.model.end_training()

或者为了简化这个你可以试试这个代码

doc = Doc(nlp.vocab, [u'rats', u'make', u'good', u'pets'])
gold = GoldParse(doc, [u'U-ANIMAL', u'O', u'O', u'O'])
ner = EntityRecognizer(nlp.vocab, entity_types=['ANIMAL'])
ner.update(doc, gold)