Tokenizer karakter: encode dan decode
Diberikan vocab (list karakter, token ke-i adalah vocab[i]). Ubah text menjadi list id (encode), lalu ubah kembali menjadi string (decode). Kembalikan [ids, teks_hasil_decode]. Semua karakter di text dijamin ada di vocab.
text = "halo", vocab = ["a", "h", "l", "o"] → [[1, 0, 2, 3], "halo"]
Dua tabel
stoi = {ch: i for i, ch in enumerate(vocab)}
itos = {i: ch for i, ch in enumerate(vocab)}
encode = lambda s: [stoi[c] for c in s]
decode = lambda ids: "".join(itos[i] for i in ids)Sifat terpenting tokenizer: decode(encode(s)) == s. Kalau sifat ini rusak, misalnya karena huruf kapital diubah atau spasi dibuang, teks yang dihasilkan model tidak akan pernah bisa sama persis dengan data latihnya.
Dari id ke vektor
Id hanyalah nomor urut. Angka 3 tidak “lebih besar” dari angka 1 dalam arti apa pun. Karena itu id tidak dimasukkan ke jaringan sebagai angka, tetapi dipakai sebagai indeks untuk mengambil baris dari tabel embedding. Itu soal berikutnya.
Penjelasan
Yang diminta. Ubah teks menjadi id (encode), lalu ubah kembali id menjadi teks (decode), memakai vocab.
Langkah di kode:
stoi = {ch: i for i, ch in enumerate(vocab)}(“string to int”): karakter ke nomor urutnya.itos = {i: ch for i, ch in enumerate(vocab)}: kebalikannya.ids = [stoi[ch] for ch in text]."".join(itos[i] for i in ids)menyusun kembali teksnya.
Sifat yang diuji. decode(encode(s)) == s untuk setiap s. Elemen kedua hasil harus sama persis dengan text, termasuk spasi dan baris baru.
Kenapa dict, bukan vocab.index(ch)? list.index mencari dari awal setiap kali, sehingga encode teks sepanjang n butuh O(n⋅V). Dict mencari dalam O(1).
Yang dikembalikan: [list id, string].
Topik
Petunjuk 1
Buat dua dict: stoi = {karakter: indeks} dan itos = {indeks: karakter}.
Petunjuk 2
encode: [stoi[c] for c in text]. decode: ''.join(itos[i] for i in ids).
Nilai ditulis sebagai JSON. Output yang diharapkan dihitung dari solusi referensi.