Боюсь, вам придется написать свое собственное преобразование, потому что кодирование IOB зависит от того, какую токенизацию будет использовать предварительно обученная модель представления (BERT, RoBERTa или любая другая предварительно обученная модель по вашему выбору).
Формат SpaCy определяет диапазон символов объекта, то есть
"Who is Shaka Khan?"[7:17]
вернет "Shaka Khan"
. Вам необходимо сопоставить это с токенами, используемыми предварительно обученной моделью.
Вот примеры того, как разные модели токенизируют пример предложения, когда вы использовали Трансформаторы Huggingface .
- BERT:
['Who', 'is', 'S', '##hak', '##a', 'Khan', '?']
- Роберт:
['Who', '_is', '_Sh', 'aka', '_Khan', '?']
- X LNet:
['▁Who', '▁is', '▁Shak', 'a', '▁Khan', '?']
Зная, как работает токенизатор, вы можно реализовать преобразование. Нечто подобное может работать для токенизации BERT.
entities = [(7, 17, "PERSON")]}
tokenized = ['Who', 'is', 'S', '##hak', '##a', 'Khan', '?']
cur_start = 0
state = "O" # Outside
tags = []
for token in tokenized:
# Deal with BERT's way of encoding spaces
if token.startswith("##"):
token = token[2:]
else:
token = " " + token
cur_end = cur_start + len(token)
if state == "O" and cur_start < entities[0][0] < cur_end:
tags.append("B-" + entitites[0][2])
state = "I-" + entitites[0][2]
elif state.startswith("I-") and cur_start < entities[0][1] < cur_end:
tags.append(state)
state = "O"
entities.pop(0)
else:
tags.append(state)
cur_start = cur_end
Обратите внимание, что фрагмент может сломаться, если один токен BERT будет содержать конец одной сущности и начало следующей. Маркер также не различает guish сколько пробелов (или других пробелов) было в исходной строке, это также потенциальный источник ошибок.