我有已经以SpaCy格式标记的数据。例如:
("Who is Shaka Khan?", {"entities": [(7, 17, "PERSON")]}),
("I like London and Berlin.", {"entities": [(7, 13, "LOC"), (18, 24, "LOC")]})
但是我想尝试使用任何其他NER模型来训练它,例如BERT-NER,它需要IOB标记。从SpaCy数据格式到IOB有转换代码吗?
谢谢!
答案 0 :(得分:2)
这与https://stackoverflow.com/a/59209377/461847密切相关,并且大多是从复制而来,也请参见注释中的注释:
import spacy
from spacy.gold import biluo_tags_from_offsets
TRAIN_DATA = [
("Who is Shaka Khan?", {"entities": [(7, 17, "PERSON")]}),
("I like London and Berlin.", {"entities": [(7, 13, "LOC"), (18, 24, "LOC")]}),
]
nlp = spacy.load('en_core_web_sm')
docs = []
for text, annot in TRAIN_DATA:
doc = nlp(text)
tags = biluo_tags_from_offsets(doc, annot['entities'])
# then convert L->I and U->B to have IOB tags for the tokens in the doc
答案 1 :(得分:1)
恐怕,您将不得不编写自己的转换,因为IOB编码取决于预训练的表示模型(BERT,RoBERTa或您选择的任何预训练的模型)将使用哪种令牌化。
SpaCy格式指定实体的字符跨度,即
@Override
public ResponseEntity<List<His>> getPagosByFechaPago(String dateTo, String dateFrom) {
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
Date dateHasta = null, dateDesde = null;
try {
dateHasta = formatter.parse(dateTo);
dateDesde = formatter.parse(dateFrom);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Period diff = Period.between(LocalDate.parse(dateFrom), LocalDate.parse(dateTo));
if(diff.getYears() == 0 && diff.getMonths() <= 2 && diff.getMonths() >= -2) {
Query query = new Query();
query.addCriteria(Criteria.where("date").gte(dateHasta).lt(dateDesde));
List<His> response = mongoTemplate.find(query, His.class);
log.info(response.toString());
return new ResponseEntity<>(response, HttpStatus.OK);
} else {
return new ResponseEntity<>(null, HttpStatus.BAD_REQUEST);
}
}
将返回"Who is Shaka Khan?"[7:17]
。您需要将其与预训练模型使用的令牌相匹配。
以下是使用Huggingface's Transformers时不同模型如何标记例句的示例。
"Shaka Khan"
['Who', 'is', 'S', '##hak', '##a', 'Khan', '?']
['Who', '_is', '_Sh', 'aka', '_Khan', '?']
了解令牌生成器的工作原理后,可以实现转换。像这样的事情可以对BERT令牌化起作用。
['▁Who', '▁is', '▁Shak', 'a', '▁Khan', '?']
请注意,如果一个BERT令牌包含一个实体的末尾和下一实体的开始,则该代码段将中断。分词器也没有区分原始字符串中有多少空格(或其他空格),这也是潜在的错误来源。
答案 2 :(得分:0)
首先您需要将带注释的 json
文件转换为 csv
。
然后你可以运行下面的代码转换成spaCy V2 Binary
格式
df = pd.read_csv('SC_CSV.csv')
l1 = []
l2 = []
for i in range(0, len(df['ner'])):
l1.append(df['ner'][i])
l2.append({"entities":[(0,len(df['ner'][i]),df['label'][i])]})
TRAIN_DATA = list(zip(l1, l2))
TRAIN_DATA
现在是 TRAIN_DATA
格式的 spaCy V2
这有助于将文件从您的旧 Spacy v2
格式转换为全新的新 Spacy v3
格式。
import pandas as pd
from tqdm import tqdm
import spacy
from spacy.tokens import DocBin
nlp = spacy.blank("en") # load a new spacy model
db = DocBin() # create a DocBin object
for text, annot in tqdm(TRAIN_DATA): # data in previous format
doc = nlp.make_doc(text) # create doc object from text
ents = []
for start, end, label in annot["entities"]: # add character indexes
span = doc.char_span(start, end, label=label, alignment_mode="contract")
if span is None:
print("Skipping entity")
else:
ents.append(span)
doc.ents = ents # label the text with the ents
db.add(doc)
db.to_disk("./train.spacy") # save the docbin object