BertWordPieceTokenizer против BertTokenizer от HuggingFace

У меня есть следующие фрагменты кода, и я пытаюсь понять разницу между BertWordPieceTokenizer и BertTokenizer.

BertWordPieceTokenizer (на основе Rust)

from tokenizers import BertWordPieceTokenizer

sequence = "Hello, y'all! How are you Tokenizer  ?"
tokenizer = BertWordPieceTokenizer("bert-base-uncased-vocab.txt")
tokenized_sequence = tokenizer.encode(sequence)
print(tokenized_sequence)
>>>Encoding(num_tokens=15, attributes=[ids, type_ids, tokens, offsets, attention_mask, special_tokens_mask, overflowing])

print(tokenized_sequence.tokens)
>>>['[CLS]', 'hello', ',', 'y', "'", 'all', '!', 'how', 'are', 'you', 'token', '##izer', '[UNK]', '?', '[SEP]']

BertTokenizer

from transformers import BertTokenizer
tokenizer = BertTokenizer("bert-base-cased-vocab.txt")
tokenized_sequence = tokenizer.encode(sequence)
print(tokenized_sequence)
#Output: [19082, 117, 194, 112, 1155, 106, 1293, 1132, 1128, 22559, 17260, 100, 136]
  1. Почему в обоих случаях кодирование работает по-разному? В BertWordPieceTokenizer он предоставляет объект Encoding, а в BertTokenizer - идентификаторы словаря.
  2. В чем принципиальная разница между BertWordPieceTokenizer и BertTokenizer, потому что, как я понимаю, BertTokenizer также использует WordPiece под капотом.

Благодарность

1 ответ

Решение

Они должны давать одинаковый результат, когда вы используете один и тот же словарь (в вашем примере вы использовали bert-base-uncased-vocab.txt и bert-base-cased-voiceab.txt). Основное отличие состоит в том, что токенизаторы из пакета токенизаторов быстрее токенизаторов из трансформаторов, потому что они реализованы в Rust.

Когда вы измените свой пример, вы увидите, что они производят одинаковые ids и другие атрибуты (объект кодирования), в то время как токенизатор трансформаторов только создал список ids:

from tokenizers import BertWordPieceTokenizer

sequence = "Hello, y'all! How are you Tokenizer  ?"
tokenizerBW = BertWordPieceTokenizer("/content/bert-base-uncased-vocab.txt")
tokenized_sequenceBW = tokenizerBW.encode(sequence)
print(tokenized_sequenceBW)
print(type(tokenized_sequenceBW))
print(tokenized_sequenceBW.ids)

Выход:

Encoding(num_tokens=15, attributes=[ids, type_ids, tokens, offsets, attention_mask, special_tokens_mask, overflowing])
<class 'Encoding'>
[101, 7592, 1010, 1061, 1005, 2035, 999, 2129, 2024, 2017, 19204, 17629, 100, 1029, 102]
from transformers import BertTokenizer

tokenizerBT = BertTokenizer("/content/bert-base-uncased-vocab.txt")
tokenized_sequenceBT = tokenizerBT.encode(sequence)
print(tokenized_sequenceBT)
print(type(tokenized_sequenceBT))

Выход:

[101, 7592, 1010, 1061, 1005, 2035, 999, 2129, 2024, 2017, 19204, 17629, 100, 1029, 102]
<class 'list'>

Вы упомянули в комментариях, что ваши вопросы больше касаются того, почему полученный результат отличается. Насколько я могу судить, это дизайнерское решение, принятое разработчиками, и для этого нет особой причины. Это также не тот случай, когда BertWordPieceTokenizer от токенизаторов является заменой на месте BertTokenizer от трансформаторов. Они по-прежнему используют оболочку, чтобы сделать ее совместимой с API токенизатора трансформаторов. Существует класс BertTokenizerFast, у которого есть метод очистки _convert_encoding, чтобы сделать BertWordPieceTokenizer полностью совместимым. Поэтому вам нужно сравнить приведенный выше пример BertTokenizer со следующим:

from transformers import BertTokenizerFast

sequence = "Hello, y'all! How are you Tokenizer  ?"
tokenizerBW = BertTokenizerFast.from_pretrained("bert-base-uncased")
tokenized_sequenceBW = tokenizerBW.encode(sequence)
print(tokenized_sequenceBW)
print(type(tokenized_sequenceBW))

Выход:

[101, 7592, 1010, 1061, 1005, 2035, 999, 2129, 2024, 2017, 19204, 17629, 100, 1029, 102]
<class 'list'>

С моей точки зрения, они создали библиотеку токенизаторов независимо от библиотеки трансформеров, чтобы быть быстрыми и полезными.

Другие вопросы по тегам