Siri Belajar AI : Apa itu Tokenization?
Mari kita kenal Tokenization

Dalam siri kali ini, kita nak kenal dengan lebih asas lagi pasal AI. Kita nak cuba untuk korek, untuk pecahkan kotak hitam AI supaya kita boleh faham bagaimana ia berfungsi, dan bukan setakat tahu saja bagaimana hendak menggunakannya.
Oleh kerana itulah kita mulakan dengan benda yang paling senang sekali. Kita mulakan dengan bagaimana AI, ataupun Large Language Model (LLM) memproses teks ataupun perkataan.
Komputer tak memahami bahasa
Bagi mereka yang tak mempunyai asas dalam sains komputer perlulah mengetahui bahawa komputer tak memahami bahasa. Ia tak mampu memproses perkataan (dalam bahasa komputer kita panggil ia sebagai string).Komputer tak mengenali huruf ‘A’, tak mengenali perkataan ‘ayam’, apatah lagi memahami ayat yang panjang. Apa yang mampu dilakukan komputer adalah memahami nombor, kerana asas pengiraan dalam komputer itu sendiri adalah menggunakan nombor binari, nombor 1 dan 0.
Kerana itulah sebelum memasuki komputer, huruf, ataupun ayat, ataupun perkataan perlulah ditukarkan terlebih dahulu kepada nombor. Ia merupakan proses yang dipanggil sebagai encoding. Dan kaedah encoding yang selalu digunakan pada zaman ini adalah kaedah Unicode.
Cuba kita ambil satu contoh untuk menukarkan ayat di bawah ini kepada nombor menggunakan kaedah unicode. Katakanlah ayat yang kita pakai adalah seperti di bawah:
# contoh menggunakan unicode
string = "Saya tak suka baju melayu Elrah 😡"
# Generate a single string containing Unicode ordinals separated by spaces
horizontal_list = " ".join(str(ord(s)) for s in string)
horizontal_listKita akan dapat hasilnya seperti di bawah:
Secara asasnnya, setiap huruf yang ada pada ayat di atas akan ditukarkan kepada nombor.
Kelemahan Unicode untuk AI
Unicode merupakan kaedah yang digunakan secara meluas dalam pengaturcaraan. Kebanyakan program dan aplikasi yang dibagunkan dibuat dengan mengitegrasikan unicode dalam pengaturcaraan. Namun begitu, ia sangatlah tidak sesuai untuk digunakan dalam LLM.
Pertama, kaedah unicode mengambil banyak ruang komputasi. Ia menukarkan huruf kepada nombor, sedangkan LLM perlu bermain dengan berpuluh ribu (mungkin juga berjuta) huruf. Jadi ia sangatlah tidak efisyen menggunakan unicode dalam proses melatih LLM.
Kedua, kaedah unicode mempunyai saiz perbendaharaan kata yang sudahpun tetap. Ini kerana unicode sudahpun mendaftarkan setiap huruf/karakter dari mana-mana bahasa pun dengan nombornya sendiri. Perkara ini menghasilkan saiz perbendaharaan kata yang tetap, tanpa fleksibiliti yang boleh menggangu proses melatih LLM kelak.
Oleh kerana itulah, saintis data, terutama mereka yang berada di OpenAI menggunakan kaedah lain untuk memproses perkataan. Mereka gunakan apa yang dipanggil sebagai tokenization. Dan di OpenAI, mereka gunakan algoritma yang dipanggil sebagai Byte-Pair-Encoding
Algoritma Byte Pair Encoding
Byte-Pair-Encoding ataupun BPE merupakan algoritma yang digunakan oleh OpenAI dalam model GPT mereka (sehinggalah ke GPT-4) dalam memproses perkataan dalam LLM. Algoritma ini mudah dan ringkas untuk difahami, dan secara teorinya, dapat mengurangkan jumlah token yang perlu diproses. Ianya boleh dijelaskan seperti di bawah:
1. Katakanlah kita ada satu senarai perkataan yang kita nak encode (“aaabaaadaaac”). Boleh lihat ada 12 karakter/huruf yang perlu diencod
2. Kita akan cari dalam perkataan ini apakah pasangan yang paling banyak berulang, dalam kes ini “aa” yang berulang sebanyak tiga kali
3. Yang berulang ini kita akan gantikan dengan huruf lain (“z”)
4. Dengan menggunakan cara ini perkataan itu sudah ditokenkan menjadi “zabzadzac”.
5. Kita akan ulang sehinggalah tiada lagi pasangan yang berulang dalam teks yang kita ingin proses.
Nampak ringkas dan mudah bukan? Mari kita cuba untuk aplikasikan dalam kod.
#teks boleh diambil di laman sesawang the patriots asia. anda boleh cari list sendiri
teks = "Unicode! 🅤🅝🅘🅒🅞🅓🅔‽ 🇺🇳🇮🇨🇴🇩🇪!Kinkyū Jishin Sokuhō (緊急地震速報) ialah amaran yang dikeluarkan lepas gempa bumi dikesan oleh Agensi Meteorologi Jepun (JMA) kepada orang awam untuk berlindung."
tokens = teks.encode("utf-8")
tokens = list(map(int, tokens)) # tukarkan list kepada integer dalam range ..255 untuk memudahkan pemahaman
print('---')
print(teks)
print("length:", len(teks))
print('---')
print(tokens)
print("length:", len(tokens))Mari kita ambil satu teks yang panjang seperti dalam blok kod di atas. Kita akan cuba tengok panjang teks ini jika kita menggunakan unicode.
Boleh nampak tak yang asalnya, ayat kita itu hanya ada 188 huruf sahaja. Tapi disebabkan kita menggunakan unicode, ia menjadi 272 nombor yang berbeza. Ini kerana unicode mengambil kira perkataan-perktaan yang isitimewa, seperti simbol, huruf asing (karakter jepun) kepada nombornya sendiri. Kerana itulah ianya tidak ideal untuk diproses dalam LLM.
Sekarang mari kita cuba untuk dapatkan pasangan yang wujud dalam teks ini.
#buat fungsi untuk dapatkan jumlah pair
def get_stats(ids : int):
"""Fungsi ini akan melihat pada seluruh list nombor, dan cuba untuk
mencari pasangan yang paling kerap berulang. Dia memerlukan senarai integer
sebagai input, dan akan mengeluarkan senarai integer juga sebagai output"""
counts = {}
for pair in zip(ids, ids[1:]): # cara python untuk iterate mengikut element dalam list
counts[pair] = counts.get(pair, 0) + 1
return counts
stats = get_stats(tokens)
#print (stats)
print(sorted(((v,k) for k,v in stats.items()), reverse=True))Hasilnya boleh dilihat seperti di bawah:
Boleh nampak yang pasangan paling banyak berulang adalah karakter yang dipersembahkan oleh nombor 240 dan nombor 159. Mari kita cuba tukarkan nombor tersebut kepada karakter asal.
#dan pasangan (240,159) ini merujuk pada
print240 = chr(240)
print159 = chr(159)
print(f"240 dan 159 merujuk kepada {print240} dan juga {print159}")Mari kita cuba untuk lakukan iterasi dan jalankan algoritma BPE kita pada teks tersebut. Kita dapatkan dulu pasangan maksimum dan simpan dalam variable.
#mari kita simpan pasangan maksimum
max_pair = max(stats)
#jadi mari kita kurangkan jumlah karakter yang perlu diproses
def merge(ids, pair, idx):
"""
Fungsi ini akan mencari pasangan yang berulang dan akan menggantikan pasangan itu
dengan nombor yang baru, dalam kes ini, nombor 256.
"""
newids = []
i = 0
while i < len(ids):
# kalau kita tak perada di posisi terakhir, dan ianya bukan pasangan maksimum, kita akan gantikan dengan
#token baru
if i < len(ids) - 1 and ids[i] == pair[0] and ids[i+1] == pair[1]:
newids.append(idx)
i += 2
else:
newids.append(ids[i])
i += 1
return newids
# contoh penggunaan
new_tokens = merge(tokens, max_pair, 256)
print(new_tokens)
print(f"length:{len(new_tokens)}")Dan hasilnya seperti di bawah. Boleh nampak yang kita sudahpun mengurangkan jumlah token yang perlu diproses dari 272 ke 258.
Itu sahaja, mudah kan tokenization ni? Huhu. Untuk pengetahuan anda, kalau anda dah faham tokenization ni, anda sudahpun mengekod sendiri sebahagian daripada kod ChatGPT. Tahniah.
Tapi dalam siri-siri yang akan datang, kita akan tengok lebih mendalam lagi tentang GPT. Kita akan belajar tentang model yang berdiri di sebalik ChatGPT, model transformer.







