Проблема с методом токенизатора batch_encode_plus

Я столкнулся со странной проблемой в batch_encode_plusметод токенизаторов. Я недавно перешел с трансформатора версии 3.3.0 на 4.5.1. (Я создаю свою базу данных для NER).

У меня есть 2 предложения, которые мне нужно закодировать, и у меня есть случай, когда предложения уже токенизированы, но поскольку оба предложения различаются по длине, мне нужно pad [PAD] короче предложение, чтобы моя партия была одинаковой длины.

Вот код ниже, который я сделал с версией трансформаторов 3.3.0.

      from transformers import AutoTokenizer

pretrained_model_name = 'distilbert-base-cased'
tokenizer = AutoTokenizer.from_pretrained(pretrained_model_name, add_prefix_space=True)

sentences = ["He is an uninvited guest.", "The host of the party didn't sent him the invite."]

# here we have the complete sentences
encodings = tokenizer.batch_encode_plus(sentences, max_length=20, padding=True)
batch_token_ids, attention_masks = encodings["input_ids"], encodings["attention_mask"]
print(batch_token_ids[0])
print(tokenizer.convert_ids_to_tokens(batch_token_ids[0]))

# And the output
# [101, 1124, 1110, 1126, 8362, 1394, 5086, 1906, 3648, 119, 102, 0, 0, 0, 0]
# ['[CLS]', 'He', 'is', 'an', 'un', '##in', '##vi', '##ted', 'guest', '.', '[SEP]', '[PAD]', '[PAD]', '[PAD]', '[PAD]']

# here we have the already tokenized sentences
encodings = tokenizer.batch_encode_plus(batch_token_ids, max_length=20, padding=True, truncation=True, is_split_into_words=True, add_special_tokens=False, return_tensors="pt")

batch_token_ids, attention_masks = encodings["input_ids"], encodings["attention_mask"]
print(batch_token_ids[0])
print(tokenizer.convert_ids_to_tokens(batch_token_ids[0])) 

# And the output 
tensor([ 101, 1124, 1110, 1126, 8362, 1394, 5086, 1906, 3648,  119,  102, 0, 0, 0, 0])
['[CLS]', 'He', 'is', 'an', 'un', '##in', '##vi', '##ted', 'guest', '.', '[SEP]', '[PAD]', [PAD]', '[PAD]', '[PAD]']

Но если я попытаюсь имитировать то же поведение в трансформаторе версии 4.5.1, я получу другой результат.

      from transformers import AutoTokenizer
    
pretrained_model_name = 'distilbert-base-cased'
tokenizer = AutoTokenizer.from_pretrained(pretrained_model_name, add_prefix_space=True)

sentences = ["He is an uninvited guest.", "The host of the party didn't sent him the invite."]

# here we have the complete sentences
encodings = tokenizer.batch_encode_plus(sentences, max_length=20, padding=True)
batch_token_ids, attention_masks = encodings["input_ids"], encodings["attention_mask"]
print(batch_token_ids[0])
print(tokenizer.convert_ids_to_tokens(batch_token_ids[0]))

# And the output
#[101, 1124, 1110, 1126, 8362, 1394, 5086, 1906, 3648, 119, 102, 0, 0, 0, 0]
#['[CLS]', 'He', 'is', 'an', 'un', '##in', '##vi', '##ted', 'guest', '.', '[SEP]', '[PAD]', '[PAD]', '[PAD]', '[PAD]']

# here we have the already tokenized sentences, Note we cannot pass the batch_token_ids 
# to the batch_encode_plus method in the newer version, so need to convert them to token first
tokens1 = tokenizer.tokenize(sentences[0], add_special_tokens=True)
tokens2 = tokenizer.tokenize(sentences[1], add_special_tokens=True)

encodings = tokenizer.batch_encode_plus([tokens1, tokens2], max_length=20, padding=True, truncation=True, is_split_into_words=True, add_special_tokens=False, return_tensors="pt")

batch_token_ids, attention_masks = encodings["input_ids"], encodings["attention_mask"]
print(batch_token_ids[0])
print(tokenizer.convert_ids_to_tokens(batch_token_ids[0]))

# And the output (not the desired one)
tensor([  101,  1124,  1110,  1126,  8362,   108,   108,  1107,   108,   108,
          191,  1182,   108,   108, 21359,  1181,  3648,   119,   102])
['[CLS]', 'He', 'is', 'an', 'un', '#', '#', 'in', '#', '#', 'v', '##i', '#', '#', 'te', '##d', 'guest', '.', '[SEP]']

Не знаю, как с этим справиться, или что я здесь делаю не так.

2 ответа

Чтобы использовать список целочисленных токенов, вам нужен небыстрый токенизатор.

tokenizer = AutoTokenizer.from_pretrained(pretrained_model_name, add_prefix_space=True, use_fast=False)

use_fast Флаг был включен по умолчанию в более поздних версиях.

Из документации HuggingFace,

batch_encode_plus(batch_text_or_text_pairs: ...)

batch_text_or_text_pairs (List [str], List [Tuple [str, str]], List [List [str]], List [Tuple [List [str], List [str]]], а для не-быстрых токенизаторов также List [Список [int]], Список [Кортеж [Список [int], Список [int]]])

Пишу сюда, потому что не могу комментировать сам вопрос. Я предлагаю посмотреть результат каждой токенизации (token1 и token2) и сравнить его с batch_token_ids. Странно, что вывод не содержит токенов из второго предложения. Может там проблема.