word2vec melatih jaringan kecil pada sebuah korpus sehingga setiap kata mendapat vektor padat (dense), dan kemiripan makna tinggal dihitung dari kedekatan antarvektor. Topik ini memperkenalkan dua arsitekturnya, skip-gram dan CBOW, pada tingkat intuisi, menyebut trik negative sampling yang membuat pelatihannya terjangkau, lalu melatih keduanya dengan Gensim pada korpus kecil yang deterministik. Keluaran sandbox ditampilkan apa adanya, termasuk bagian yang masih bising, agar cara membaca skor embedding tetap realistis.
Dua arsitektur: skip-gram dan CBOW#
Skip-gram melatih model untuk menebak kata konteks dari satu kata pusat. Pada kalimat mahasiswa membaca buku di perpustakaan dengan kata pusat buku, model ditugaskan menebak membaca dan di, lalu jendela digeser ke kata berikutnya dan tugas yang sama diulang. CBOW melakukan sebaliknya, yaitu menebak satu kata pusat dari gabungan tetangganya. Keduanya memakai jendela yang sama dan menghasilkan vektor dengan struktur informasi yang sama, tetapi arah tugasnya berlawanan.
| Aspek | skip-gram | CBOW |
|---|---|---|
| Tugas pelatihan | menebak konteks dari kata pusat | menebak kata pusat dari konteks |
| Kecepatan pelatihan | lebih lambat, satu pasangan per tetangga | lebih cepat, satu prediksi per jendela |
| Karakter hasil | menguntungkan kata jarang dan data kecil | menghaluskan konteks menjadi satu masukan |
Perbedaan karakter tersebut berasal dari jumlah sinyal yang dilewati setiap kata. Pada skip-gram, setiap kemunculan kata pusat memunculkan satu pasangan latihan per tetangga, sehingga kata jarang tetap dilatih dari beberapa pasangan sekaligus. Pada CBOW, tetangga dirata-rata menjadi satu masukan, sehingga detail kata pusat mudah tertelan konteksnya. Pada korpus sangat kecil, keduanya sering menghasilkan skor yang nyaris sama, dan hal itu juga terlihat pada demo di bawah.
Negative sampling sebagai trik pelatihan#
Menebak satu kata dari seluruh kosakata berarti menghitung skor untuk setiap kata kosakata pada setiap pasangan latihan, dan biaya itu berlipat ganda pada korpus besar. word2vec tidak melakukannya. Trik yang dipakai bernama negative sampling, yakni pelatihan klasifikasi biner: pasangan kata pusat dan konteks yang benar diberi label positif, lalu beberapa kata acak dipilih sebagai sampel negatif. Model hanya ditugaskan membedakan pasangan asli dari sampel negatif tersebut, sehingga biaya per pembaruan turun dari sebesar kosakata menjadi sebesar jumlah sampel.
Jumlah sampel negatif per pasangan positif biasa dilambangkan dengan k, dan Gensim menetapkan nilai 5 secara default. Kualitas hasilnya dijaga oleh mekanisme pembobotan, yaitu kata berfrekuensi sangat tinggi dipilih sebagai sampel negatif dengan peluang yang ditekan, sehingga kata seperti di tidak mendominasi. Ketebalan sinyalnya juga bergantung pada k: sampel negatif yang terlalu sedikit membuat batas kelas kasar, sedangkan yang terlalu banyak mengembalikan biaya komputasi. Dengan trik ini, pelatihan pada jutaan kalimat menjadi terjangkau, dan inilah alasan word2vec dapat dilatih di mesin biasa pada masanya.
Melatih word2vec pada korpus kecil#
Skrip berikut membangun 39 kalimat sintetis dari tiga tema, yaitu perpustakaan, pasar, dan jadwal belajar, lalu melatih model skip-gram dan CBOW dengan parameter identik. Korpusnya kecil dan templatnya tetap, sehingga keluarannya dapat direproduksi secara persis oleh pembaca di sandbox yang sama.
import warnings
warnings.filterwarnings("ignore")
import logging
logging.getLogger("gensim").setLevel(logging.ERROR)
from gensim.models import Word2Vec
def buat_korpus():
kalimat = []
# tema perpustakaan
for nama in ["Budi", "Citra", "Dewi"]:
for objek in ["buku", "majalah"]:
kalimat.append(f"{nama} membaca {objek} di perpustakaan")
kalimat.append(f"{nama} meminjam {objek} di perpustakaan")
kalimat.append("petugas menata buku di rak")
kalimat.append("petugas menata majalah di rak")
kalimat.append("Budi mencari buku di rak")
kalimat.append("Citra mencari majalah di rak")
# tema pasar
for nama in ["Budi", "Citra", "Dewi"]:
for objek in ["sayur", "buah"]:
kalimat.append(f"{nama} membeli {objek} di pasar")
kalimat.append(f"{nama} memilih {objek} di pasar")
kalimat.append("Citra menghitung harga sayur")
kalimat.append("Dewi menghitung harga buah")
# tema jadwal belajar
for nama in ["Budi", "Citra", "Dewi"]:
kalimat.append(f"{nama} mencatat materi pelajaran")
kalimat.append(f"{nama} mengerjakan latihan soal")
kalimat.append("Citra menyalin jadwal belajar")
kalimat.append("Dewi menempel jadwal belajar di dinding")
kalimat.append("Budi mengisi jadwal belajar")
return [k.split() for k in kalimat]
kalimat_token = buat_korpus()
print("jumlah kalimat:", len(kalimat_token))
skipgram = Word2Vec(
sentences=kalimat_token,
vector_size=100,
window=2,
min_count=1,
workers=1,
seed=42,
sg=1,
epochs=30,
)
print()
print("skip-gram, kata paling mirip dengan buku:")
for kata, skor in skipgram.wv.most_similar("buku", topn=5):
print(f" {kata}: {skor:.3f}")
print("kemiripan buku-majalah:", round(skipgram.wv.similarity("buku", "majalah"), 3))
print("kemiripan buku-sayur :", round(skipgram.wv.similarity("buku", "sayur"), 3))
cbow = Word2Vec(
sentences=kalimat_token,
vector_size=100,
window=2,
min_count=1,
workers=1,
seed=42,
sg=0,
epochs=30,
)
print()
print("CBOW, kata paling mirip dengan buku:")
for kata, skor in cbow.wv.most_similar("buku", topn=5):
print(f" {kata}: {skor:.3f}")
print("kemiripan buku-majalah:", round(cbow.wv.similarity("buku", "majalah"), 3))
print("kemiripan buku-sayur :", round(cbow.wv.similarity("buku", "sayur"), 3))jumlah kalimat: 39
skip-gram, kata paling mirip dengan buku:
memilih: 0.206
majalah: 0.187
mencari: 0.155
Dewi: 0.133
mengerjakan: 0.122
kemiripan buku-majalah: 0.187
kemiripan buku-sayur : -0.119
CBOW, kata paling mirip dengan buku:
memilih: 0.202
majalah: 0.190
mencari: 0.149
Dewi: 0.126
mengerjakan: 0.112
kemiripan buku-majalah: 0.19
kemiripan buku-sayur : -0.116Pasangan buku-majalah memperoleh skor 0.187 pada skip-gram, sedangkan buku-sayur bernilai negatif, -0.119. Arahnya sesuai hipotesis distribusional, tetapi skornya kecil dan daftar tetangga buku justru diawali memilih. Korpus 39 kalimat memang belum cukup untuk geometri yang bersih: tetangga seperti memilih dan Dewi muncul dari sisa-sisa kebetulan pelatihan, bukan dari makna. Yang dapat diandalkan pada tahap ini hanyalah urutan relatif, yaitu buku-majalah lebih tinggi daripada buku-sayur, sedangkan pada korpus berisi jutaan kalimat skor yang sama biasanya naik dan daftar tetangganya semakin sesuai makna.
Keluaran CBOW hampir tidak berbeda dari skip-gram, dengan urutan tetangga yang sama dan skor yang bergeser tipis. Pada skala data sekecil ini, perbedaan arsitektur belum terasa, dan perbedaan keduanya baru menonjol ketika korpus membesar.
Parameter yang menjaga hasil dapat direproduksi#
Parameter pada skrip ada demi kestabilan hasil. workers=1 memaksa pelatihan berjalan satu benang, karena pembaruan dari banyak benang tumpang tindih dengan urutan yang tidak dapat dijamin, sehingga hasilnya berubah dari satu eksekusi ke eksekusi berikutnya. seed=42 menetapkan titik awal acak untuk inisialisasi vektor dan pengambilan sampel negatif, dan kombinasi keduanya membuat dua eksekusi menghasilkan angka yang sama persis. vector_size=100 menetapkan panjang vektor, window=2 menetapkan jarak tetangga yang dihitung, dan epochs=30 menetapkan jumlah lintasan penuh atas korpus. min_count=1 dipakai karena korpusnya kecil, yaitu setiap kata yang pernah muncul ikut dilatih, sedangkan korpus nyata biasanya memakai 5 atau 10 agar kata yang muncul sekali tidak mengacaukan vektor. Nilai-nilai itu juga membuat pelatihan selesai dalam hitungan detik pada korpus kecil.
Kesalahan umum#
- Melatih dengan
workers>1lalu membandingkan hasilnya antareksekusi. Urutan pembaruan antarbenang menentukan vektor akhir, sehingga skor berubah tanpa sebab yang jelas. Gunakanworkers=1setiap kali hasil perlu dibandingkan. - Menilai kualitas embedding dari nilai absolut skornya. Angka 0.187 pada korpus kecil bukan skor lemah yang gagal, melainkan skor rendah yang urutannya benar. Kemiripan dibandingkan antarpasangan pada model yang sama, bukan dibaca sebagai kebenaran mutlak.
- Mengulang pelatihan dengan harapan hasil identik tanpa menetapkan
seed. Tanpaseedyang tetap, titik awal inisialisasi berubah dan seluruh vektor ikut berpindah. Tetapkanseeddi awal dan catat nilainya bersama kode pelatihan.
Ringkasan#
- skip-gram menebak konteks dari kata pusat, sedangkan CBOW menebak kata pusat dari konteksnya.
- Negative sampling mengganti prediksi atas seluruh kosakata dengan klasifikasi biner terhadap beberapa sampel negatif.
- Pada korpus 39 kalimat, buku-majalah memperoleh skor 0.187 dan buku-sayur -0.119, dengan urutan yang sesuai makna walaupun skornya kecil.
workers=1danseedtetap membuat pelatihan dapat direproduksi, sedangkan korpus kecil membuat perbedaan skip-gram dan CBOW nyaris tidak terlihat.
Referensi#
- Topik word2vec asli — Google Code Archive — Penjelasan resmi Mikolov tentang arsitektur skip-gram, CBOW, dan perbandingan keduanya.
- Gensim Documentation — RaRe Technologies — Dokumentasi kelas Word2Vec beserta parameter workers, seed, dan negative.