Используя инструмент конвейера HuggingFace , я с удивлением обнаружил, что при использовании быстродействующего и медленного токенизатора была существенная разница в выходных данных.
В частности, когда я запускаю конвейер маски заполнения, вероятности, назначенные словам, которые будут заполнять маску, не одинаковы для быстрого и медленного токенизатора. Более того, хотя прогнозы быстрого токенизатора остаются постоянными независимо от количества и длины введенных предложений, то же самое нельзя сказать о медленном токенизаторе.
Вот минимальный пример:
from transformers import pipeline
slow = pipeline('fill-mask', model='bert-base-cased', \
tokenizer=('bert-base-cased', {"use_fast": False}))
fast = pipeline('fill-mask', model='bert-base-cased', \
tokenizer=('bert-base-cased', {"use_fast": True}))
s1 = "This is a short and sweet [MASK]." # "example"
s2 = "This is [MASK]." # "shorter"
slow([s1, s2])
fast([s1, s2])
slow([s2])
fast([s2])
Каждый вызов конвейера возвращает топ-5 токенов, которые могут заполнить [MASK]
, вместе с их вероятностями. Для краткости я опускаю фактические выходные данные, но вероятности, назначенные каждому слову, которое заполняет [MASK]
для s2
, не одинаковы во всех примерах. Последние 3 примера дают одинаковые вероятности, но первый дает разные вероятности. Различия настолько велики, что топ-5 не согласованы между двумя группами.
Причина этого, как я могу сказать, в том, что быстрый и медленный токенизаторы возвращают разные результаты. Быстрый токенизатор стандартизирует длину последовательности до 512, добавляя 0, а затем создает маску внимания, которая блокирует заполнение. Напротив, медленный токенизатор только дополняет длину самой длинной последовательности и не создает такую маску внимания. Вместо этого он устанавливает идентификатор типа токена отступа равным 1 (а не 0, который является типом токенов без дополнения). По моему пониманию реализации HuggingFace (найдено здесь ), они не эквивалентны.
Кто-нибудь знает, является ли это намеренным?