如何导出“带有spaCy实体的文档”以在doccano中使用

时间:2019-09-12 08:00:13

标签: python json spacy

我想使用doccano或其他“开源文本注释工具”来训练我的模型,并不断改进我的模型。

据我所知,我可以按以下描述的格式将带注释的数据导入doccano: doccano import

所以第一步,我已经加载了一个模型并创建了一个文档:

text = "Test text that should be annotated for Michael Schumacher" 
nlp = spacy.load('en_core_news_sm')
doc = nlp(text)

我知道我可以从doccano导出jsonl格式(带有文本和带注释的标签)并使用它训练模型,但是我想知道如何从python中的spaCy doc导出数据,以便我可以将其导入到doccano

谢谢。

3 个答案:

答案 0 :(得分:2)

我最近有类似的任务,这是我的工作方式:

import spacy
nlp = spacy.load('en_core_news_sm')

def text_to_doccano(text):
    """
    :text (str): source text
    Returns (list (dict)): deccano format json
    """
    djson = list()
    doc = nlp(text)
    for sent in doc.sents:
        labels = list()
        for e in sent.ents:
            labels.append([e.start_char, e.end_char, e.label_])
        djson.append({'text': sent.text, "labels": labels})
    return djson

根据您的示例...

text = "Test text that should be annotated for Michael Schumacher."
djson = text_to_doccano(text)
print(djson)

...将打印出来:

[{'text': 'Test text that should be annotated for Michael Schumacher.', 'labels': [[39, 57, 'PERSON']]}]

在相关说明中,当您将结果保存到文件时,用于保存JSON的标准json.dump方法不起作用,因为它会将其写为用逗号分隔的条目列表。 AFAIK,doccano希望每行有一个条目,并且不带逗号。在解决此问题时,以下代码片段的工作方式类似于charm:

import json

open(filepath, 'w').write("\n".join([json.dumps(e) for e in djson]))

/欢呼声

答案 1 :(得分:1)

Spacy不支持开箱即用的确切格式,但是您应该能够相当容易地编写自定义函数。看看spacy.gold.docs_to_json(),它显示了与JSON类似的转换。

答案 2 :(得分:1)

Doccano 和/或 spaCy 似乎已经改变了一些事情,现在接受的答案中存在一些缺陷。截至 2021 年 8 月 1 日,此修订版与 spaCy 3.1 和 Doccano 应该更正确...

def text_to_doccano(text):
    """
    :text (str): source text
    Returns (list (dict)): deccano format json
    """
    djson = list()
    doc = nlp(text)
    for sent in doc.sents:
        labels = list()
        for e in sent.ents:
            labels.append([e.start_char - sent.start_char, e.end_char - sent.start_char, e.label_])
        djson.append({'text': sent.text, "label": labels})
    return djson

区别:

  1. labels 在 JSON 中变成单数 label (?!?)
  2. e.start_chare.end_char 实际上是(现在?)文档中的开始和结束,而不是在句子中......所以你必须通过文档中句子的位置来抵消它们.