Токенізація підслова — BPE, WordPiece і те, як текст стає токеном
https://anirudhology.com/blog/demystifying-tokenization-part-1-why-tokenization-matters
Нейронні мережі працюють з числами. Текст - це рядки. Щось має зіставлятися між ними, і це виробляє одиницю, яку насправді бачить ваша модель — токен.
Наївна відповідь полягає в тому, щоб розділити пробіли та призначити кожному унікальному слову ціле число. Це не працює з реальним текстом в абзаці: постійно з’являються нові слова (covid, chatgpt, kubernetes), різні форми одного слова (run, ran, running) стають непов’язаними записами, а мовам без пробілів (китайська, японська, тайська) нема чого розділяти. Кожна сучасна модель використовує щось більш складне, і сімейство рішень — BPE, WordPiece, SentencePiece, BPE на рівні байтів — виглядає як одна ідея з чотирма різними шапками.
Ця стаття розповідає про цю сім’ю. Ми побачимо, чому обидва рівні слів і символів порушуються, що насправді робить токенізація підслів, чим відрізняються найпоширеніші варіанти та що означає вибір токенізера для всього подальшого потоку — розміру моделі, вартості виклику API, міжмовної справедливості, навіть дивних збоїв, які демонструють моделі. Ми навчимо токенізатор BPE з нуля на приблизно п’ятдесяти рядках Python, а потім порівняємо результат із чотирма робочими токенізаторами на тому самому вході.
Чому б просто не розділити пробіли?
Токенізація на рівні слова є очевидною відправною точкою. Візьміть корпус, розділіть на пробіли, призначте кожному унікальному слову ціле число, створіть словниковий запас. Одразу виявляються три проблеми.
Розмір словникового запасу. Англійська мова містить десь від 200 тисяч до 1 мільйона слів залежно від того, як ви підраховуєте рідкісні форми, власні іменники та флексії. Якщо кожен запис вбудовано як 768-вимірний вектор (розмір bert-base), словник із мільйона слів коштує ~3 ГБ лише для таблиці вбудовування — більшість параметрів моделі витрачаються на слова, які з’являються один раз у всьому корпусі. І це лише вхідна сторона: великий словниковий запас також робить рівень виводу дорогим, тому що остаточний softmax нормалізується для всіх записів на кожному кроці — вартість , яка в епоху рівня слів була досить болючою, щоб породжувати обхідні шляхи, такі як ієрархічний і вибірковий softmax (див. стаття word2vec). Згортання словникового запасу до одиниць підслів робить звичайний softmax достатньо дешевим, щоб ці трюки більше не були потрібні — можливо, те, що вилучене з експлуатації ієрархічне softmax для мовних моделей робило більше, ніж будь-яке конкуруюче наближення.
Слова поза словниковим запасом. Яке б обмеження ви не вибрали, слова під ним згортаються в один маркер [UNK]. Модель не може відрізнити «токенізацію» від «антидистаблішменту», якщо обидва невідомі. Слова, вигадані після навчання, назавжди невидимі — модель, яка пройшла навчання у 2017 році, поняття не має, що таке covid, і ніколи не знатиме.
Втрачена морфологія. «Бігати», «бігти», «бігати», «бігати» очевидно пов’язані. Токенізація на рівні слів бачить чотири непов’язані записи, і модель має заново вивчити зв’язок з нуля — окремо для кожного дієслова. Те саме стосується префіксів (un-, re-, pre-), суфіксів (-ation, -ing, -ed) і сполук (birthday, notebook, whiteboard).
Рівень Word працює для завдань закритого домену — класифікатор спаму в новинах англійською мовою з фіксованим словниковим запасом — але не для моделей загального призначення, навчених у відкритому Інтернеті.
Інша крайність: символи
Якщо на рівні слова забагато маркерів, чому б не спуститися до кінця? Словник рівня символів невеликий — ~100 записів охоплюють ASCII плюс загальну пунктуацію, ~5000 обробляють більшість Юнікоду. Кожне слово в лексиці за будовою. Морфологія випадає безкоштовно: run і running мають чотири символи.
Проблема протилежна до рівня слова. Символи самі по собі майже не мають значення — лексема r нічого не означає без контексту. Модель має навчитися зв’язувати символи в значущі одиниці, перш ніж вона зможе робити щось інше, а для цього потрібно багато шарів і багато даних. Послідовності також стають у 4–5 разів довшими (середнє англійське слово містить близько п’яти символів), що безпосередньо збільшує обчислення уваги (квадратичну довжину послідовності).
Моделі персонажів працюють, але вони дорогі. Домінуючим компромісом є токенізація підслова: словниковий запас фрагментів між словом і символом. Загальні слова отримують один жетон; рідкісні слова, розбиті на жменю; справді невідомі слова завжди розкладаються на символи в гіршому випадку. Словниковий запас залишається невеликим (зазвичай 30–100 тисяч), кожен введений текст міститься у словнику, а морфологія частково зберігається, оскільки спільні префікси та суфікси стають своїми власними лексемами.
Цікаве питання: які частини підслова?
BPE: злиття частих пар
Кодування пар байтів (Sennrich et al., 2016) є найпростішою схемою підслів. Ця ідея старша за NLP — BPE розпочався як алгоритм стиснення тексту в 1994 році — але застосування її до словників нейронних мереж було новим.
Процедура навчання складається з чотирьох етапів:
- Ініціалізація за допомогою словника рівня символів. Кожне слово в корпусі поділено на окремі символи, а також маркер кінця слова (ми будемо використовувати
</w>). - Підрахуйте, як часто кожна сусідня пара символів з’являється в корпусі.
- Знайдіть найчастішу пару. Об’єднайте: додайте новий символ до словника, що представляє пару, і перепишіть корпус, щоб усі входження пари було замінено цим символом.
- Повторюйте кроки 2–3, доки не виконаєте цільову кількість об’єднань (зазвичай 30–50 тисяч).
Результатом є словник плюс впорядкований список правил злиття. Щоб токенізувати новий текст під час висновку, ви розділяєте його на символи та застосовуєте правила злиття в їхньому вивченому порядку.
Спрацьований приклад
Візьмемо цей крихітний корпус, де кожен рядок — це слово, а число — його частота:
low ×5
lower ×2
newest ×6
widest ×3Після кроку 1 (розділення символів за допомогою </w>):
l o w </w> ×5
l o w e r </w> ×2
n e w e s t </w> ×6
w i d e s t </w> ×3Пара підраховується (кожна пара зважена за частотою слова, у якому вона з’являється):
| пара | розраховувати |
|---|---|
e,s | 9 |
s,t | 9 |
t,</w> | 9 |
w,e | 8 |
l,o | 7 |
o,w | 7 |
n,e | 6 |
e,w | 6 |
| … | … |
Три пари мають рівний результат 9. BPE розриває зв’язки фіксованим, але довільним способом — скажімо, за порядком появи перших пар. Об’єднати e,s → es. Корпус стає:
l o w </w> ×5
l o w e r </w> ×2
n e w es t </w> ×6
w i d es t </w> ×3Тепер es,t з’являється 9 разів — об’єднайте його. Потім est,</w> з’являється 9 разів — об’єднайте його. Після трьох об’єднань словник містить впізнавану морфологічну одиницю: est</w>, суфікс, спільний для «найновіших» і «найширших».
Ще кілька ітерацій, і l,o зливається з lo, а потім lo,w зливається з low — іншою морфологічною одиницею, яка виникла лише в результаті частотного підрахунку, без лінгвістичного контролю.
Щоб токенізувати нове слово, наприклад lowest, застосуйте злиття в порядку:
l o w e s t </w> (initial split)
→ l o w es t </w> (merge e,s)
→ l o w est </w> (merge es,t)
→ l o w est</w> (merge est,</w>)
→ lo w est</w> (merge l,o)
→ low est</w> (merge lo,w)Два токени: low і est</w>. Слово не було в навчальному корпусі, але його частини були, і вони збираються знову в те, що може використовувати модель. Ось і вся суть алгоритму.
Що BPE насправді робить на практиці
Real BPE додає практичні деталі на додаток до основного циклу, жодна з яких не змінює основної ідеї:
- Нормалізація. Зазвичай текст нормалізується перед будь-чим іншим — канонічною формою Юнікод, а іноді — згортанням регістру чи видаленням наголосу. Кожен вибір є компромісом: нижній регістр скорочує словниковий запас, але стирає відмінності
US/usі CamelCase, які важливі для коду; видалення акцентів упорядковує деякі європейські мови та руйнує значення в’єтнамської чи арабської. - Попередня токенізація. Перед запуском циклу злиття корпус розділяється на пробіли та знаки пунктуації, щоб злиття не могло випадково перетинати межі слів. Без цього
the.catбув би кандидатом на об’єднання. - Спеціальні маркери. Такі маркери, як
[CLS],[SEP],[MASK],<|endoftext|>, додаються безпосередньо до словника й ніколи не беруть участь у злиттях. - Порогові значення частоти. Деякі реалізації пропускають пари нижче мінімальної частоти, щоб уникнути запам’ятовування одноразових артефактів.
- Резервний варіант на рівні байтів (розглянемо пізніше) — оперуйте необробленими байтами замість символів Юнікоду, щоб ніщо ніколи не вичерпало словниковий запас.
Базовий цикл складається з п’ятдесяти рядків Python; виробничі токенізатори обгортають це кількома тисячами рядків обробки крайових випадків.
WordPiece: оптимізуйте ймовірність замість частоти
WordPiece (Schuster & Nakajima, 2012, популяризований BERT у 2018) зберігає той самий цикл. Єдиною зміною є крок 3: замість об’єднання найпоширенішої пари, об’єднайте пару, чиє злиття максимально підвищить вірогідність корпусу в мовній моделі уніграми.
Конкретно, для кожної пари кандидатів (x, y) оцінка така:
score(x, y) = freq(x, y) / ( freq(x) × freq(y) )Це поточкова взаємна інформація пари. Пари, які зустрічаються разом частіше, ніж випадково, отримують високі бали; пари, які випадково зустрічаються часто (наприклад, the, за яким іде будь-що), отримують нижчі результати, оскільки знаменник великий.
Практичний ефект: BPE зливає жадібні частотно-керовані пари, що схиляє до поглинання дуже поширених службових слів. WordPiece надає перевагу злиттям, де компоненти мають більше значення разом, ніж окремо, що, як правило, створює більш морфологічно узгоджені частини.
WordPiece також явно позначає фрагменти продовження. Перша частина слова залишається як є; наступні твори отримують префікс ##. Отже, tokenization стає token і ##ization. Це робить детокенізацію однозначною (конкатенація, видалення маркерів ##) і дає моделі позиційну підказку: фрагмент ## ніколи не може бути першим за словом.
Для більшості англійських вводів ви не можете відрізнити BPE та WordPiece на око — розділення виглядає схожим. Вони розходяться щодо рідкісних слів із сильною морфологічною структурою, де WordPiece, швидше за все, знайде мовну межу, і щодо підслів, які є дуже поширеними (BPE поглинає їх; WordPiece чинить опір).
SentencePiece + Unigram: скорочення замість об’єднання
SentencePiece (Kudo & Richardson, 2018) — це інша філософія. BPE та WordPiece працюють знизу вгору: починають із символів, об’єднують угору. Найпоширеніший варіант SentencePiece — модель мови Unigram — це згори-вниз: починайте з великого словникового запасу, обрізайте, доки не досягнете цільового розміру.
Процедура навчання:
- Створіть великий початковий словник частих підрядків (часто за допомогою швидкого проходу BPE або простого підрахунку n-грамів). На замовлення 1М кандидатів.
- Оцініть мовну модель уніграми над словником за допомогою EM. Кожен маркер має ймовірність; будь-який рядок можна сегментувати кількома способами, кожен з різною загальною ймовірністю.
- Для кожного маркера обчисліть, наскільки зменшується ймовірність журналу корпусу, якщо ви його видалите. Токени, видалення яких майже не завдає шкоди, ймовірно, мало сприятимуть.
- Видаліть найменші 10–20% токенів за вірогідним внеском.
- Повторюйте кроки 2–4, доки словниковий запас не досягне цільового розміру.
Перевага під час висновку: уніграмна модель дає вам імовірнісну сегментацію. Те саме слово можна токенізувати кількома дійсними способами, і ви можете взяти вибірку з розповсюдження під час навчання (трюк регуляризації, який називається регуляризація підслова). BPE та WordPiece завжди виробляють однакову токенізацію для певного введення.
SentencePiece також не залежить від мови. BPE та WordPiece зазвичай попередньо токенізують пробіли, що не працює для китайської та японської. SentencePiece розглядає пробіли як звичайні символи (закодовані як ▁, U+2581) і працює безпосередньо з необробленим Unicode. T5, ALBERT, XLNet і сімейство Llama використовують варіанти SentencePiece.
Якщо SentencePiece може внутрішньо використовувати BPE або Unigram, то чим це насправді відрізняється?
SentencePiece — це навчальний конвеєр — частина, яка відрізняється від BPE та WordPiece, це попередня токенізація (точніше, її відсутність) і угода про пробіли як символи. Усередині конвеєра ви можете вибрати BPE або Unigram як фактичний алгоритм сегментації. Llama використовує SentencePiece-with-BPE; T5 використовує SentencePiece-with-Unigram. Три назви збігаються, оскільки дві з них стосуються алгоритмів, а одна – бібліотеки.
BPE на рівні байтів: символи, які не є символами
GPT-2 представив ще одну складку. Замість того, щоб працювати з символами Unicode, оперуйте з байтами — необробленим кодуванням UTF-8.
Переваги:
- Ніколи немає OOV. Кожне введення — це послідовність байтів, кожен байт міститься в базовому словнику з 256 записів, тому будь-який вхід — емодзі, некоректний Юнікод, двійкові дані — має представлення.
- Компактний базовий словниковий запас. Unicode містить ~150 тисяч символів; UTF-8 представляє всі з них у 256 байтах. Починаючи з байтів, базовий словник залишається малим.
- Узгодженість між сценаріями. Емодзі, китайська, арабська, гінді розкладаються на байти однаково — один токенізер охоплює все.
Недолік: токени можуть розбиватися посередині символу. Символ 中 — це три байти в UTF-8 (0xE4 0xB8 0xAD). Токенізатор BPE на рівні байтів може дізнатися один маркер для 0xE4 0xB8 і окремий маркер для 0xAD — жодна частина сама по собі не є дійсним символом. Модель має навчитися їх рекомбінувати, що добре працює на практиці, але ускладнює перевірку токенізації, а це означає, що кількість токенів для нелатинських текстів може бути дуже високою.
Одна тонкість ховається в байтах: той самий видимий рядок може мати більше однієї послідовності байтів. café може надходити як é (одна кодова точка, NFC) або як e, а потім комбінований наголос (дві кодові точки, NFD) — різні байти, тому токенізер на рівні байтів розглядає їх як різні вхідні дані та витрачає словниковий запас на вивчення обох варіантів написання одного слова. Ось чому конвеєри нормалізуються до канонічної форми Unicode (зазвичай NFC) перед токенізацією, навіть якщо BPE на рівні байтів може технічно представляти будь-які байти, які він отримує.
BPE на рівні байтів — це те, що використовують моделі GPT-2, GPT-3, GPT-4 і більшість моделей лінійки OpenAI, доступних лише для декодування, доступ до яких здійснюється через бібліотеку tiktoken. Лама використовує SentencePiece. Claude використовує власний токенизатор у тому самому сімействі BPE на рівні байтів.
Спробуйте
Наведений нижче віджет токенізує те саме введення за допомогою чотирьох робочих токенізаторів — bert-base-uncased (WordPiece), gpt2 (BPE на рівні байтів), t5-small (SentencePiece + Unigram) і Llama-3 (SentencePiece + BPE). Виберіть речення, подивіться, як кожен токенізер розрізає його.
The quick brown fox jumps over the lazy dog.##; bert-base-uncased outputs them when present.Кілька речей, на які варто звернути увагу:
- Для звичайних англійських слів усі чотири токенізери створюють по одній лексемі на слово. Відмінності ховаються в рідкісних словах, технічному жаргоні, коді та неанглійському тексті.
- WordPiece позначає продовження
##; SentencePiece позначає слово, що починається з▁. Та сама інформація, протилежна конвенція. - Спробуйте неанглійське речення. WordPiece і GPT-2 токенизатор рівня байтів сильно фрагментуються; Варіанти SentencePiece фрагментуються менше, тому що вони були навчені на багатомовних корпусах.
- Спробуйте blob JSON або фрагмент коду. Токенізатори у стилі GPT були частково навчені на коді та токенізації структурної пунктуації (
{,:,()) ефективніше, ніж токенізатор BERT, який навчався здебільшого на прозі. - Спробуйте слово, яке було рідкісним у 2018 році —
kubernetes,bitcoin,chatgpt. Старі токенізатори фрагментують їх на багато частин; новіші часто містять їх як окремі жетони.
Що змінюється вниз за течією
Вибір токенізера проходить через усе інше.
Вартість. Ціна API указана за маркер. Той самий запит може бути на 30% довшим або коротшим залежно від токенізера. Для англійської програми це незначна різниця; для неанглійського тексту це може бути 3–5x.
Міжмовна справедливість. Петров та ін., 2023 виміряли, скільки токенів різні токенізери використовують для того самого вмісту 22 мовами. Англійська мова незмінно найкоротша; мови з нелатинським шрифтом (бірманська, амхарська, кхмерська) використовують у 5–15 разів більше лексем для еквівалентного значення. Люди, які розмовляють цими мовами, платять більше, швидше досягають контекстних обмежень і отримують повільніші відповіді — виключно через вибір токенізера.
Довжина послідовності – це налаштування стиснення. Це допомагає бачити розмір словника як диск стиснення. Невеликий словниковий запас (скажімо, 8 Кб) змушує більшість слів розбивати на кілька частин — словниковий запас сильно стиснутий, але послідовності токенів стають довшими, і більша частина можливостей моделі йде на повторне збирання значення з фрагментів. Великий словниковий запас (100 тис.+) зберігає короткі послідовності, але витрачає параметри на рідкісні записи, вбудовування яких майже не навчаються. Виробничі моделі в діапазоні 30–100 тисяч — це емпірична найкраща точка, так само як якість JPEG розподіляється між «крихітним файлом, видимими артефактами» та «чистим, величезним файлом». Циферблат нижче дозволяє відчути компроміс.
Словниковий запас «знань». Словниковий запас моделі – це знімок корпусу, на якому вона навчалася. Слова, створені після навчання, не отримують власного маркера; вони розкладаються на частини. Це рідко є проблемою для розуміння (фрагменти все ще мають значення), але це означає, що параметри витрачаються на розподіл, який існував під час навчання, а не на той, на якому ви використовуєте модель.
Витік токенізера. Токени є доказами навчального корпусу. Наявність маркера імені користувача, як-от petertodd, у ранніх словниках GPT-2 говорить вам про відносну вагу певних форумів у WebText. Іноді ці маркери викликають неочікувану поведінку, оскільки модель рідко бачила їх у будь-якому іншому контексті — знамениті маркери «SolidGoldMagikarp», які GPT-3.5 відмовлявся повторювати або реагував на дивні завершення. Токени існували (оскільки навчання BPE на рівні байтів їх підібрало), але модель ніколи не навчилася їх належного представлення.
Сліпота на рівні символів. Оскільки звичайні слова є окремими лексемами, модель ніколи не бачить їхні букви. Запитайте модель, скільки r міститься в «полуничці», і вона може помилитися — не тому, що не вміє порахувати, а тому, що strawberry надходить у вигляді одного або двох непрозорих жетонів, усередині яких не видно r. Та сама сліпота проявляється в правописі, римуванні, анаграмах і реверсуванні рядків: будь-яке завдання, яке потребує структури субтокена, бореться з токенізатором. Це головна причина того, що токенізери на рівні символів і байтів продовжують з’являтися знову, незважаючи на їхню вартість — для виконання цих завдань мають бути присутні атомні одиниці.
Обробка чисел. Числа є яскравим прикладом тієї ж проблеми. Якщо 2024 є одним токеном, але 2025 розділяється на 20 і 25, модель не може бачити два роки як одне окремо — структура цифрового рівня, яка забезпечує арифметичну роботу, зашифрована частотно-керованими злиттями, і «що більше, 9,11 чи 9,9?» перетворюється на пошук неузгоджених частин. Ось чому кілька останніх токенізаторів навмисно розбивають числа на однозначні або фіксовані 3-значні фрагменти: вони обмінюють довші послідовності на арифметику, яку модель може навчитися. Вибір токенізера безпосередньо обмежує можливості.
Блокування. Токенізатор вибирається один раз, перед попереднім навчанням, а потім заморожується на час існування моделі. І таблиця вбудовування, і вихідний softmax індексуються за ідентифікатором маркера, тому зміна словника означає перенавчання з нуля — ви не можете поміняти маркери на навченій моделі так, як ви можете поміняти швидкість навчання або температуру дискретизації. Токенізатор, який на 20% менш ефективний, ніж міг би бути, постійно обкладається податком у розмірі 20% з кожного виклику висновку до наступного повного запуску навчання. З усіх рішень у наборі це одне з небагатьох, яке фактично є незворотним — варто подумати годину, перш ніж прийняти рішення.
Побудуйте самі
Наведений нижче сценарій навчає токенізатор BPE з нуля на невеликому корпусі, а потім токенізує пропущене слово. Реалізація коротка, тому що алгоритм короткий — близько п’ятдесяти рядків для повного навчального циклу плюс кодування.
from collections import Counter, defaultdict
def get_pair_counts(corpus):
"""Count adjacent symbol pairs across the corpus."""
counts = Counter()
for word, freq in corpus.items():
symbols = word.split()
for a, b in zip(symbols, symbols[1:]):
counts[(a, b)] += freq
return counts
def merge_pair(corpus, pair):
"""Replace every occurrence of the pair with the merged symbol."""
a, b = pair
merged = a + b
new_corpus = {}
for word, freq in corpus.items():
symbols = word.split()
out = []
i = 0
while i < len(symbols):
if i < len(symbols) - 1 and (symbols[i], symbols[i + 1]) == pair:
out.append(merged)
i += 2
else:
out.append(symbols[i])
i += 1
new_corpus[" ".join(out)] = freq
return new_corpus
def train_bpe(words, num_merges):
"""Train BPE on a {word: freq} dict. Returns the merge list."""
corpus = {" ".join(list(w) + ["</w>"]): freq for w, freq in words.items()}
merges = []
for _ in range(num_merges):
pairs = get_pair_counts(corpus)
if not pairs:
break
best = max(pairs, key=pairs.get)
corpus = merge_pair(corpus, best)
merges.append(best)
return merges
def encode(word, merges):
"""Tokenize a word by applying learned merges in order."""
symbols = list(word) + ["</w>"]
for a, b in merges:
out = []
i = 0
while i < len(symbols):
if i < len(symbols) - 1 and symbols[i] == a and symbols[i + 1] == b:
out.append(a + b)
i += 2
else:
out.append(symbols[i])
i += 1
symbols = out
return symbols
# Train on the toy corpus from the worked example.
words = {"low": 5, "lower": 2, "newest": 6, "widest": 3}
merges = train_bpe(words, num_merges=10)
print(merges)
# [('e', 's'), ('es', 't'), ('est', '</w>'), ('l', 'o'), ('lo', 'w'), ...]
print(encode("lowest", merges))
# ['low', 'est</w>']Ось і весь алгоритм. Сучасні бібліотеки — HuggingFace tokenizers, sentencepiece від Google, tiktoken від OpenAI — обробляють усі практичні деталі (нормалізація, попередня токенізація, спеціальні маркери, швидкий висновок із підтримкою Rust), але основний цикл полягає саме в цьому.
Чи хороший токенізатор? Чотири числа
Якщо у вас є токенізатор, «добре» — це не відчуття — його можна виміряти на зразку тексту, який ви насправді збираєтеся проганяти. Чотири числа виконують більшу частину роботи, і всі чотири слід обчислювати на основі даних із вашого справжнього дистрибутива, а не з навчального корпусу.
Коефіцієнт стиснення (байтів на маркер). Підрахуйте байти UTF-8 у збереженому корпусі та поділіть на кількість токенів, створених токенізатором. Приблизно 4–6 байт/токен є нормальним для англійської мови; вище означає, що токенізер пакує більше тексту в кожен маркер, що означає коротші послідовності та меншу вартість. Число падає з обриву на тексті, для якого токенізер не був навчений — виконайте те саме вимірювання на своїх медичних довідках, коді, цільовій мові та порівняйте.
Плодючість (жетони на слово). На скільки частин розбивається середнє слово? Близький до 1 означає, що більшість слів є окремими лексемами; підйом до 2–3 означає сильну фрагментацію. Англійська в домені зазвичай знаходиться біля 1.1–1.3; той самий токенізер на спеціалізованому домені або нелатинським шрифтом може подвоїти або потроїти це — той самий вміст, більше токенів, більше грошей.
Ставка одного токена. Частка ваших загальних слів, які зберігаються як рівно один токен. Це практична версія питання OOV: не «чи слово представлено» (байтовий рівень гарантує так), а «чи воно представлено добре». Якщо менше половини термінів вашого загального домену є окремими маркерами, словниковий запас не відповідає вашим даним, і ви платите за це за кожен виклик.
Розподіл словникового запасу є нульовою сумою. Усі ці цифри свідчать про один факт: словниковий запас є фіксованим бюджетом, і кожен маркер, витрачений на один фрагмент, є маркером, який не надається іншому. Токенізатор, навчений на 60% англійського тексту, витрачає приблизно 60% свого бюджету на англійські фрагменти — саме тому міжмовна невідповідність, яка була раніше, є не помилкою, а обліковою ідентифікацією. Виправити це означає змінити те, на чому навчений токенізер — надмірну вибірку недостатньо представленої мови або домену — не налаштовувати алгоритм.
Куди це веде
Тепер у вас є одиниці. Наступне запитання полягає в тому, який вектор представляє кожну одиницю, і як цей вектор кодує значення — відповідь, яка еволюціонувала від «одного фіксованого вектора на лексему, отриманого з того, як слова зустрічаються разом» (word2vec, GloVe) до «вектора, який залежить від навколишнього речення» (BERT, GPT).
Це паралельний потік, а не наступний крок у цьому. word2vec і GloVe працюють на рівні слів: розділити на пробіли, зберегти часті слова, викинути решту. Питання токенізації тут майже не існує — кожне слово є окремою одиницею, і все невідоме просто ігнорується. Токенізація підслів має значення для того, що відбулося пізніше: BERT і GPT вбудовують фрагменти, а не слова, саме для того, щоб кожен вхід мав представлення, а рідкісні слова розкладалися на те, що модель все ще може використовувати. Тож «як текст стає токенами» та «який вектор отримує кожен токен» — це два потоки, які працюють паралельно та сходяться в контекстних моделях — Стаття BERT — це місце, де вони зустрічаються.