#
Normalisasi dan Pra-tokenisasi

Sebelum kita menyelami lebih dalam tiga algoritma tokenisasi subkata yang paling umum digunakan pada model Transformer (Byte-Pair Encoding [BPE], WordPiece, dan Unigram), kita akan terlebih dahulu melihat tahap praproses yang dilakukan oleh setiap tokenizer terhadap teks. Berikut gambaran umum tingkat tinggi tentang langkah-langkah dalam pipeline tokenisasi:

Sebelum membagi teks menjadi subtoken (sesuai dengan modelnya), tokenizer menjalankan dua langkah: normalisasi dan pra-tokenisasi.

##
Normalisasi

Langkah normalisasi mencakup pembersihan umum, seperti menghapus spasi yang tidak perlu, mengubah huruf menjadi huruf kecil (lowercasing), dan/atau menghapus aksen. Jika kamu familiar dengan normalisasi Unicode (seperti NFC atau NFKC), tokenizer mungkin juga menerapkannya.

Tokenizer dari 🤗 Transformers memiliki atribut `backend_tokenizer` yang memberikan akses ke tokenizer dasar dari pustaka 🤗 Tokenizers:

    from transformers import AutoTokenizer

    tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")
    print(type(tokenizer.backend_tokenizer))

    <class 'tokenizers.Tokenizer'>

Atribut `normalizer` dari objek `tokenizer` memiliki metode `normalize_str()` yang bisa kita gunakan untuk melihat bagaimana proses normalisasi dilakukan:

    print(tokenizer.backend_tokenizer.normalizer.normalize_str("Héllò hôw are ü?"))

    'hello how are u?'

Dalam contoh ini, karena kita menggunakan checkpoint `bert-base-uncased`, proses normalisasi mencakup perubahan huruf ke huruf kecil dan penghapusan aksen.

✏️ Coba sendiri! Muat tokenizer dari checkpoint `bert-base-cased` dan berikan contoh yang sama. Apa perbedaan utama yang kamu lihat antara versi `cased` dan `uncased` dari tokenizer?

##
Pra-tokenisasi

Seperti yang akan kita lihat pada bagian berikutnya, tokenizer tidak bisa langsung dilatih pada teks mentah. Kita perlu membagi teks terlebih dahulu menjadi entitas kecil seperti kata. Di sinilah langkah pra-tokenisasi berperan. Seperti yang telah dibahas di Bab 2, tokenizer berbasis kata dapat membagi teks menjadi kata berdasarkan spasi dan tanda baca. Kata-kata ini akan menjadi batasan bagi subtoken yang akan dipelajari tokenizer saat pelatihan.

Untuk melihat bagaimana tokenizer cepat (fast tokenizer) melakukan pra-tokenisasi, kita bisa menggunakan metode `pre_tokenize_str()` dari atribut `pre_tokenizer`:

    tokenizer.backend_tokenizer.pre_tokenizer.pre_tokenize_str("Hello, how are  you?")

    [('Hello', (0, 5)), (',', (5, 6)), ('how', (7, 10)), ('are', (11, 14)), ('you', (16, 19)), ('?', (19, 20))]

Perhatikan bahwa tokenizer sudah mencatat offset, yang memungkinkan kita mendapatkan pemetaan offset seperti yang digunakan pada bagian sebelumnya. Di sini tokenizer mengabaikan dua spasi dan menggantinya dengan satu, tetapi offset tetap mencerminkan jarak sebenarnya.

Karena kita menggunakan tokenizer BERT, proses pra-tokenisasi mencakup pemisahan berdasarkan spasi dan tanda baca. Tokenizer lain dapat memiliki aturan berbeda. Misalnya, jika kita menggunakan tokenizer GPT-2:

    tokenizer = AutoTokenizer.from_pretrained("gpt2")
    tokenizer.backend_tokenizer.pre_tokenizer.pre_tokenize_str("Hello, how are  you?")

Tokenizer ini juga membagi berdasarkan spasi dan tanda baca, tetapi mempertahankan spasi dan menggantinya dengan simbol `Ġ`, memungkinkan pemulihan spasi asli saat mendekode token:

    [('Hello', (0, 5)), (',', (5, 6)), ('Ġhow', (6, 10)), ('Ġare', (10, 14)), ('Ġ', (14, 15)), ('Ġyou', (15, 19)),
     ('?', (19, 20))]

Juga perhatikan bahwa tidak seperti tokenizer BERT, tokenizer ini tidak mengabaikan spasi ganda.

Sebagai contoh terakhir, mari kita lihat tokenizer T5 yang berbasis pada algoritma SentencePiece:

    tokenizer = AutoTokenizer.from_pretrained("t5-small")
    tokenizer.backend_tokenizer.pre_tokenizer.pre_tokenize_str("Hello, how are  you?")

    [('▁Hello,', (0, 6)), ('▁how', (7, 10)), ('▁are', (11, 14)), ('▁you?', (16, 20))]

Seperti tokenizer GPT-2, tokenizer ini mempertahankan spasi dan menggantinya dengan token khusus (`▁`), tetapi tokenizer T5 hanya membagi berdasarkan spasi, bukan tanda baca. Ia juga menambahkan spasi di awal kalimat (sebelum `Hello`) dan mengabaikan spasi ganda.

Setelah melihat bagaimana beberapa tokenizer memproses teks, kita bisa mulai menjelajahi algoritma dasarnya. Kita akan mulai dengan meninjau sekilas SentencePiece; kemudian, dalam tiga bagian berikutnya, kita akan mempelajari bagaimana tiga algoritma utama tokenisasi subkata bekerja.

##
SentencePiece

SentencePiece adalah algoritma tokenisasi untuk praproses teks yang dapat digunakan dengan model apa pun yang akan kita bahas. Algoritma ini memperlakukan teks sebagai rangkaian karakter Unicode, dan mengganti spasi dengan karakter khusus, `▁`. Digunakan bersama algoritma Unigram (lihat bagian 7), algoritma ini bahkan tidak memerlukan langkah pra-tokenisasi, yang sangat berguna untuk bahasa yang tidak menggunakan spasi seperti Bahasa Tionghoa atau Jepang.

Fitur utama lain dari SentencePiece adalah tokenisasi yang dapat dibalik (reversible tokenization): karena tidak ada perlakuan khusus untuk spasi, proses decoding token cukup dilakukan dengan menggabungkan kembali token dan mengganti `▁` dengan spasi — ini akan menghasilkan teks yang telah dinormalisasi. Seperti yang sudah kita lihat, tokenizer BERT menghapus spasi ganda, sehingga tokenisasi miliknya tidak dapat dibalik.

##
Tinjauan Algoritma

Pada bagian berikutnya, kita akan membahas tiga algoritma utama tokenisasi subkata: BPE (digunakan oleh GPT-2 dan lainnya), WordPiece (misalnya digunakan oleh BERT), dan Unigram (digunakan oleh T5 dan lainnya). Sebelum mulai, berikut adalah ringkasan cara kerja masing-masing. Jangan ragu untuk kembali ke tabel ini setelah membaca setiap bagian jika masih belum sepenuhnya memahami.

Model | BPE | WordPiece | Unigram
--- | --- | --- | ---
Pelatihan | Mulai dari kosakata kecil dan mempelajari aturan penggabungan token | Mulai dari kosakata kecil dan mempelajari aturan penggabungan token | Mulai dari kosakata besar dan mempelajari aturan penghapusan token
Langkah pelatihan | Menggabungkan pasangan token paling sering muncul | Menggabungkan pasangan dengan skor terbaik berdasarkan frekuensi, mengutamakan pasangan dengan token individual yang lebih jarang | Menghapus semua token dalam kosakata untuk meminimalkan loss pada seluruh korpus
Yang dipelajari | Aturan penggabungan dan kosakata | Hanya kosakata | Kosakata dengan skor untuk tiap token
Proses encoding | Membagi kata menjadi karakter, lalu menggabungkan sesuai aturan | Mencari subkata terpanjang dari awal yang ada di kosakata, lalu lanjutkan | Mencari pembagian token paling mungkin berdasarkan skor pelatihan

Sekarang, mari kita mulai dengan BPE!

< > Update on GitHub