为 SpaCy NER 格式化训练数据集

Posted

技术标签:

【中文标题】为 SpaCy NER 格式化训练数据集【英文标题】:Formatting training dataset for SpaCy NER 【发布时间】:2018-05-06 17:44:45 【问题描述】:

我想用我自己的实体为 NER 训练一个空白模型。为此,我需要使用一个数据集,该数据集当前为 .csv 格式,并具有以下格式的实体标签(我将为每个相关列提供一个示例行):


列:句子

价值:我想要苹果


列:数据

值:['want;@command;2;6','apples';@fruit;7;13']


列:实体

值:我@command @fruit


列:实体类型

值:@bot/@command;@bot/@food/@fruit


为了训练 SpaCy 的 NER,我需要以下格式的 json 格式的训练数据:

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

Link to the relevant part in the SpaCy Docs

我试图找到一种解决方案,以解决如何将 csv 中的数据重新格式化为 SpaCy 所需的格式,但到目前为止我还没有成功。数据集确实包含所有必要的信息 - 文本字符串、实体名称、实体类型、实体偏移量 - 但我根本不知道如何以正确的形式获取它们。

我将不胜感激有关如何完成此任务的任何和所有帮助!

【问题讨论】:

【参考方案1】:

您的问题不是 100% 清楚您是否还询问 CSV 提取 - 所以我假设这不是问题。 (如果是,这应该很容易使用csv 模块实现。如果 CSV 数据很混乱并且包含一堆组合在一个字符串中的东西,您可能需要调用split 并执行哈克方式。)

如果您能够以这样的格式提取“句子”和“数据”列,那么您实际上已经非常接近 spaCy 的训练格式了:

[ 
    'sentence': 'I want apples'
    'data': [('want', '@command', 2, 6) ('apples', '@fruit', 7, 13)]
]

与 spaCy 相比,您的数据对结束字符的计数似乎不同,并且偏移量为 +1。所以你必须通过减去1 来调整它。我可能会让这比它应该的更冗长,但我希望这会让它更容易理解:

TRAIN_DATA = []

for example in your_extracted_data:  # see example above
    entities = []
    for entity in example['data']:  # iterate over the entities
        text, label, start, end = entity  # ('want', '@command', 2, 6)
        label = label.split('@')[1].upper()  # not necessary, but nicer
        end = end - 1  # correct the end character index
        entities.append((start, end, label))
    # add training example of (text, annotations) tuple
    TRAIN_DATA.append((example['sentence'], 'entities': entities))

这应该会为您提供如下所示的训练数据:

[
    ('I want apples', 'entities': [(2, 5, 'COMMAND'), (7, 12, 'FRUIT')])
]

【讨论】:

非常感谢,您的回答确实帮助了我,这正是我想要弄清楚的!我可以看到代码如何处理提取的数据,但我仍然缺少 CSV 提取过程中的一个步骤,如果您或其他任何阅读本文的人可以为我指明正确的方向,我将不胜感激:正如您所说, CSV 确实在一个字符串中包含一堆东西,但我设法破解了所有内容,给我留下了一个 pandas df,其中包含一个 sentence 列和 10 个 data 列(因为有些句子包含多达 10 个不同的实体。跨度> 因此,data 单元格包含'want', '@command', 2, 6NaN 之类的内容。我仍然不清楚的是我如何将这个 pandas 数据框转换为您作为示例提供的格式。或者,更具体地说,这种格式是什么,我应该用谷歌搜索哪些术语来了解如何将 df 转换为它。我是否正确地假设它由嵌套在字典中的列表中嵌套的元组组成? 是的——所需的格式是一个元组列表,包含一个字符串(文本)和一个字典。字典有一个条目'entities',它的值是一个由两个整数(开始和结束索引)和一个字符串(标签)组成的元组(三元组)列表。我对 pandas 数据框不是很熟悉,但它绝对是一个常见的用例——所以我相信你能弄清楚这一点。即使你只能提取长字符串——只要它们的格式一致,你总是可以使用splitstrip等在Python中编写一个hacky转换器脚本。

以上是关于为 SpaCy NER 格式化训练数据集的主要内容,如果未能解决你的问题,请参考以下文章

使用自定义数据集训练 SpaCy NER

Spacy 2.0 NER培训

为什么spacy遗忘了旧的训练数据以及如何解决

使用 spaCy 3 进行自定义 NER 训练会引发 ValueError

我是否需要提供培训Spacy NER的句子或段落是否合适?

每次迭代后保存spacy的NER模型