我有一个句子列表,句子的每个单词都在嵌套列表中。如:
[['EU', 'rejects', 'German', 'call', 'to', 'boycott', 'British', 'lamb', '.'],
['Peter', 'Blackburn'],
['BRUSSELS', '1996-08-22']]
还有另一个列表,其中每个单词都对应一个实体标签。如:
[['B-ORG', 'O', 'B-MISC', 'O', 'O', 'O', 'B-MISC', 'O', 'O'],
['B-PER', 'I-PER'],
['B-LOC', 'O']]
这是基本的 ConLL2003 数据,但我实际上使用的是另一种语言的不同数据。我仅将这个作为示例表示。
我想将此列表列表转换为 JsonL 格式,其中格式为:
{"text": "EU rejects German call to boycott British lamb.", "labels": [ [0, 2, "ORG"], [11, 17, "MISC"], ... ]}
{"text": "Peter Blackburn", "labels": [ [0, 15, "PERSON"] ]}
{"text": "President Obama", "labels": [ [10, 15, "PERSON"] ]}
到目前为止,我已经设法将列表列表放入这种格式(json list of dicts):
[{'id': 0,
'text': 'Corina Casanova , İsviçre Federal Şansölyesidir .',
'labels': [[0, 6, 'B-Person'],
[7, 15, 'I-Person'],
[18, 25, 'B-Country'],
[26, 33, 'B-Misc'],
[34, 47, 'I-Misc']]},
{'id': 1,
'text': "Casanova , İsviçre Federal Yüksek Mahkemesi eski Başkanı , Nay Giusep'in pratiğinde bir avukat olarak çalıştı .",
'labels': [[0, 8, 'B-Person'],
[11, 18, 'B-Misc'],
[19, 26, 'I-Misc'],
[27, 33, 'I-Misc'],
[34, 43, 'I-Misc'],
[59, 62, 'B-Person'],
[63, 72, 'I-Person']]}]
但是,这样做的问题是我想将 IOB 格式合并在一起并创建一个从头到尾的单一实体。我需要这种格式才能在 doccano 注释工具上上传数据。我需要标记为一个的复合实体。
这是我为创建上述格式而编写的代码:
list_json = []
for x, i in enumerate(sentences[0:2]):
list_json.append({"id": x})
list_json[x]["text"] = " ".join(i)
list_json[x]["labels"] = []
for y, j in enumerate(labels[x]):
if j in ['B-Person', 'I-Person', 'B-Country'...(private data)]:
word = i[y]
wordStartIndex = list_json[x]["text"].find(word)
wordEndIndex = list_json[x]["text"].index(word) + len(word)
list_json[x]["labels"].append([wordStartIndex, wordEndIndex, j])
我尝试将上述格式转换为我想要的格式。IE。合并 IOB 标签。这是我迄今为止尝试过的但没有奏效的方法。
new_labels = []
for y, i in enumerate(list_json):
label_names = [item[2] for item in i["labels"]]
label_BIO = [item[0] for item in label_names]
k = 0
for index in range(len(label_BIO)-1):
if (label_BIO[index] == "B" and label_BIO[index+1] == "I") or (label_BIO[index] == "I" and label_BIO[index+1] == "I"):
k += 1
for x in range(len(i["labels"])-1):
if i["labels"][x][2][0] == "B" and i["labels"][x+1][2][0] == "I":
new_labels.append([i["labels"][x][0],i["labels"][x+k-1][1],i["labels"][x][2][2:]])
elif i["labels"][x][2][0] != "I" and i["labels"][x+1][2][0] != "I":
new_labels.append([i["labels"][x][0], i["labels"][x][1], i["labels"][x][2]])
这段代码的问题是我无法确定连续序列的序列长度。所以对于列表中的每个元素 k 总是稳定的。我需要 k 更改同一列表中的下一个序列。
这是我得到的错误:
IndexError Traceback (most recent call last)
<ipython-input-93-420750229f93> in <module>
---> 19 new_labels.append([i["labels"][x][0],i["labels"][x+k-1][1],i["labels"][x][2][2:]])
20
21 elif i["labels"][x][2][0] != "I" and i["labels"][x+1][2][0] != "I":
IndexError: list index out of range
我需要确定每次我应该在哪里计算 k。这里的 K 是 B 跟随 I 的序列的长度,依此类推。
我也试过这个,但这只会将两个标签合并在一起:
new_labels = []
for y, i in enumerate(list_json):
I_labels = []
for x, j in reversed(list(enumerate(i["labels"]))):
if j[2][0] == "I" and i["labels"][x-1][2][2:] == j[2][2:]:
new_labels.append([i["labels"][x-1][0],j[1],j[2][2:]])
elif j[2][0] != "I" and i["labels"][x+1][2][0] != "I":
new_labels.append([j[0], j[1], j[2]])
输出:
[[26, 47, 'Misc'],
[18, 25, 'Country'],
[0, 15, 'Person'],
[59, 72, 'Person'],
[27, 43, 'Misc'],
[19, 33, 'Misc'],
[11, 26, 'Misc'],
[0, 8, 'Person']]
但我需要 3 个“杂项”标签作为索引 11 到 43 的一个标签。
对于任何想知道的人:我尝试这样做的原因是,我已经标记了一些数据并测试了原型模型,它似乎给出了很好的结果。所以我想标记整个数据集并修复错误标签,而不是从头开始注释。我想这会为我节省很多时间。
ps:我知道doccano支持以ConLL格式上传。但是它坏了,所以我不能这样上传。