kekavigi.xyz

Menyusun Daftar Prioritas Artikel Matematika

Ceritanya Anda ingin membantu mengembangkan Wikipedia Bahasa Indonesia, dengan menerjemahkan artikel bertopik matematika dari versi Bahasa Inggris. Walau realitanya hanya akan mengerjakan apa yang-bisa dan yang-mau Anda terjemahkan, terbesit pertanyaan berikut: artikel mana yang paling mendesak untuk dibuat ya?

Ditulis tanggal oleh A. Keyka Vigiliant. Revisi terakhir pada tanggal . Konten diterbitkan dibawah lisensi CC BY-SA 4.0.


TL,DR; Hasil dapat dilihat di sini.

Di Wikipedia, dapat memiliki daftar artikel yang mendesak untuk dibuat-atau-diperbaiki, adalah salah satu cita-cita saya. Sekitar dua tahun yang lalu, saya mencoba melakukannya dengan membuat Google Sheet. Namun eksekusi ide itu terlalu rumit… terutama karena saya perlu berurusan dengan SQL; dan malangnya saya tidak fasih bahasa itu. Nah, mumpung saat ini saya senggang, dan karena ingin melatih merapal mantra SQL, dan karena ada teman yang bergulat memroses data Wikipedia, saya melihat sekarang adalah waktu yang pas untuk mewujudkan cita-cita saya itu.

Baik, ini latar belakangnya. Wikipedia Bahasa Indonesia (idwiki) adalah salah satu Wikipedia terbesar, setidaknya menurut total artikelnya. Malangnya, tidak semua artikel didalamnya terbagi rata. Ada topik yang konsisten diperbarui, ada pula topik yang hampir semuanya buatan (terjemahan) mesin, dan apapun yang terjadi diantara kedua sisi ekstrem itu. Topik matematika, fokus bahasan kita saat ini, banyak tidak memiliki artikel untuk konsep-konsep dasar/penting, sedangkan yang sudah ada umumnya sudah tidak terawat. Tentu ada penyebabnya, dari minimnya penyunting yang bisa mengelola, tidak ada patokan kepenulisan teks matematika, dan lain lain. Itu cerita panjang yang butuh tempatnya tersendiri. Saat ini, anggaplah ada yang ingin membantu meningkatkan artikel-artikel matematika, mungkin dengan memperbarui atau dengan membuat konten, dan mereka mau melakukannya dengan cara yang paling efisien dan efektif. Kita butuh suatu daftar, sehingga mereka punya gambaran kasar dan berkata “Ah, kalau saya fokus membuat/menerjemahkan artikel ini-ini dan itu-itu, saya bakal membuat dampak besar!”

Jika itu terasa masuk akal, mari kita lanjutkan: bagaimana cara membuat daftar itu?

Menentukan artikel-artikel

Sebelum mengurutkan artikel berdasarkan tingkat mendesaknya, kita terlebih dahulu harus punya daftar semua konsep matematika yang ada di Wikipedia. Untungnya, sejak sekitar tahun 2002 di Wikipedia Bahasa Inggris, ada komunitas WikiProject Mathematics yang mengelola apapun terkait artikel matematika di Wikipedia Bahasa Inggris. Melihat versi Wikipedia itu adalah Wikipedia tertua, dengan populasi penyunting terbanyak dan tersebar di seisi Bumi, kita aman berkesimpulan mereka punya daftar (hampir) dari semua konsep matematika – yang totalnya saat saya menulis ini, lebih dari 28,000 artikel (sekitar 700 diantaranya belum dinilai).

Tapi lebih lanjut, ternyata di dalam daftar tadi, banyak mengandung biografi tokoh matematikawan; contohnya Euler dan Dantzig. Karena saya hanya ingin fokus ke “konsep matematika,” dan karena artikel-artikel tokoh juga merupakan fokus dari WikiProject Biography (ProyekWiki Biografi di versi idwiki), kita dapat membuang mereka, agar menghasilkan “daftar artikel matematika” yang lebih sesuai dengan ekspektasi (saya).

Kueri SQL

Oke, hanya tahu judul halaman di enwiki saja tidak cukup untuk membuat peringkat; kita butuh beberapa metrik dari setiap halaman, seperti: hal-hal seperti ukuran halaman, berapa banyak versi Wikipedia yang membahas konsep artikel tersebut, berapa banyak artikel lain yang merujuk ke artikel itu; dan hal-hal semacamnya. Lagipula, karena fokus kita mengembangkan idwiki, kita perlu mengetahui padanan (kalau ada) idwiki dari setiap halaman di enwiki. Nah, untungnya ada Quarry, alat dari Wikimedia yang memungkinkan kita menjalankan kueri SQL di (replika) basis data Wikipedia.

Lebih dalam tentang basis data, semua informasi terkait halaman-halaman di Wikipedia tersusun dalam banyak tabel; kita dapat mengambil banyak hal, dan batasannya hanyalah kemampuan merapal SQL (juga beberapa batasan teknis, tentunya). Setelah melihat-lihat susunan tabel, saya melihat beeberapa tabel berikut yang berguna:

Setelah membaca itu, mungkin sudah mulai terbayang oleh Anda apa saja “metrik” yang saya anggap berperan dalam membuat/menentukan daftar prioritas:

Nah, setelah beberapa hari belajar dan berpikir dan men-debug, akhirnya saya menulis kueri yang Anda dapat baca di Quarry#84057. Saya tidak menyalinnya ke sini karena kueri yang saya buat cukup panjang. Setelah dijalankan (butuh beberapa menit), kita selanjutnya perlu mengunduh hasil kueri, lalu mulai mencari cara mengurutkan prioritas artikel.

Menambahkan data versi Indonesia

Halo, bagian ini ditambahkan oleh Keyka dari masa depan. Oke, kueri SQL tadi sebenarnya hanya berurusan dengan artikel yang ada di enwiki, dan hal yang sama perlu dilakukan di idwiki. Pertimbangannya, karena ada kemungkinan versi artikel di idwiki sama/lebih bagus dari enwiki, dan dalam kasus seperti itu, artikel tidak perlu diprioritaskan. Nah sialnya, ada masalah besar muncul: Wikipedia memisahkan idwiki dan enwiki ke dua basis data berbeda, dan kita tidak bisa membuat kueri SQL yang menggunakan dua basis data berbeda (lihat berita ini).

Cukup celaka.

Baik, setelah mempertimbangkan kesulitan mengelola program dan kualitas hasil yang didapatkan, saya memutuskan kompromi berikut: saya membuat alternatif kueri SQL yang mendaftar artikel-artikel yang dicatat oleh ProyekWiki Matematika. Kueri ini ringan dan dapat diselesaikan Quarry dengan cepat. Sedangkan untuk artikel yang belum tercatat oleh ProyekWiki, yang jumlahnya ada banyak sekali dan tidak jelas cara menyelesaikannya menggunakan Quarry, saya memilih memproses manual data dumps Wikipedia. Kekurangannya, data ini hanya diperbarui sekali (atau dua kali) setiap bulannya.

Untuk detailnya, saya menjalankan mantra bash ini, yang mengubah berkas basis data MySQL menjadi CSV (karena saya malas kalau kodingan nantinya perlu import-transform-export):

gzip -d idwiki-20241001-page.sql.gz
parallel -a idwiki-20241001-page.sql -k --block 32M --pipe-part \
"grep \"INSERT INTO\" 
	| sed \"s/),(/\n/g\"
	| sed -r \"s/^.*VALUES \ (//g\" 
	| sed -r \"s/\);$//g\""
> page.csv

# Sebenarnya tidak ada spasi antara '\' dengan '(//g\'
# saya menambahkannya untuk menghindari galat ketika
# memproses tampilan halaman ini >_<

Jika menggunakan Pandas di Python, kita cukup membaca berkas CSV yang dihasilkan, fokus ke artikel non-pengalihan di ruang nama Utama, lalu mengambil semua data page_title dan page_len-nya.

Menambahkan data total kunjungan

Halo kembali, dari kekavigi di masa depan. Ada satu satu metrik lain yang menurut saya penting: banyaknya total kunjungan ke artikel tersebut (setidaknya versi enwiki). Berikut pertimbangan saya: kalau artikel di versi enwiki banyak dibaca sedangkan di idwiki sedikit, artikel itu kandidat yang bagus untuk diperbaiki. Kalau ada artikel di idwiki banyak dibaca tapi kualitasnya lebih buruk ketimbang enwiki, artikel itu kandidat yang bagus untuk diperbaiki. Nah, untungnya Wikimedia menyusun data kunjungan yang sesuai dengan kebutuhan kita itu.

Wikimedia menyediakan dua jenis data, data kunjugan harian, dan versi bulanan. Saya memilih yang kedua, untuk menghemat total transfer via Internet. Perhatian khusus diperlukan, walau terlihat kecil (sekian gigabita saja), ukuran decompress dari setiap data bulanan bisa mencapai lebih dari 20GB. Walau saya memiliki banyak memori SSD yang kosong di laptop, sialnya saya juga memiliki memori RAM dan total core CPU yang kecil. Cara ini saya gunakan untuk memroses data kunjungan, setelah mencoba sekian banyak cara yang mungkin secara teori:

# pertama download semua data, saya memilih
# selang waktu September 2023 - Agustus 2024
aria2c -x 16 -s 16 -c \
	--auto-file-renaming=false \
	--retry-wait=600 -i list-to-download.txt

# Lalu decompress semuanya, kode ini bisa dilakukan
# karena saya punya banyak memori SSD yang kosong
ls *.bz2 | parallel "pbzip2 -d"

# Ekstrak hanya versi "id.wikipedia" dan "en.wikipedia" saja
for wiki in 'id' 'en'; do
	for file in pageviews*; do
		echo "processing $wiki-$file"
		parallel -a $file --block 64M --pipe-part \
		"grep ^$wiki\\.wikipedia | awk '{print \$2,\$5}'"
		> "$file-$wiki";
		rm $file
 	done;
done;

# Berbeda dengan sebelumnya, kode ini tidak bisa di parallel-kan
# tanpa merusak laptop. trim2tsv adalah hasil kompilasi kode Python
for file in pageviews*; do
	echo "processing $file"
	./trim2tsv $file "$file.tsv"
done;

Mengurutkan artikel-artikel

Setelah hasil dari kode-kode di atas didapatkan, kita dapat memroses dan menggabungkannya menjadi satu tabel. Kolom-kolom di tabel ini adalah:

Baik, sebelum mengotori tangan lebih lanjut, sambil melihat tabel saat ini, ada baiknya kita berpikir “mendesak-untuk-diprioritas” seperti apa yang kita inginkan. Sejujurnya, pertanyaan ini malah mengingatkan pada masalah skripsi saya, tentang pemrograman tujuan (goal programming, GP). Itu adalah salah satu metode dalam optimisasi multiobjektif, yang bertujuan untuk mencari solusi optimal dari masalah yang perlu mempertimbangkan banyak objektif/aspek. Nah, kalau dihubungkan, kita saat ini ingin mencari pengurutan artikel (peringkat pertama bisa dianggap paling optimal) yang mempertimbangkan banyak aspek: apakah seharusnya kita lebih berfokus pada artikel yang sering dirujuk, atau artikel yang kontennya banyak, atau artikel yang punya padanan di banyak bahasa, atau yang kualitasnya bagus, atau bagaimana?

Hal yang menyenangkan dari GP adalah kita hanya perlu merancang suatu “fungsi objektif” yang membuat pengambil keputusan puas (dalam kasus ini saya), ketimbang mencari suatu cara optimal yang mungkin hanya diketahui Tuhan. Lagipula, kita dan mereka yang membutuhkan datar ini nantinya, kemungkinan besar sudah memiliki preferensi pribadi terkait aspek-aspek tadi, walaupun mungkin tidak mendetail. Selain itu, kita tidak terlalu peduli perbedaan antara artikel yang posisi peringkatnya bersebelahan (misal peringkat 11 dan 12). Namun kita berharap, sebagai contoh, artikel peringkat 10 masuk akal bila dianggap lebih penting ketimbang artikel peringkat 100, dan dianggap jauh lebih penting daripada artikel peringkat 1000.

Saya sendiri, secara umum punya preferensi untuk mengurutkan artikel sebagai gabungan tingkat kepentingannya di enwiki, di idwiki, dan secara “global”. Untuk enwiki, preferensi saya seperti berikut (simbol “>” mengartikan “lebih penting daripada”): priority > quality > pageview_en > article_length > total_inlink > talk_length > total_outlink. Namun preferensi itu tidak tegas: ada kalanya artikel yang banyak dibaca lebih pantas diutamakan ketimbang artikel dengan kualitas tinggi; untuk aspek-aspek yang lebih rendah (seperti inlink dan outlink) saya tidak terlalu peduli bagaimana mereka diurutkan (karena apakah artikel seperti itu mendesak tuk diutamakan?). Sedangkan untuk idwiki, saya menganggap size_diff menjadi aspek yang lebih mendesak ketimbang pageview_id(walau tidak yakin seberapa mendesaknya). Lalu secara “global”, konsep matematika yang tersedia di banyak versi bahasa Wikipedia pastilah penting untuk diutamakan, ketimbang yang cuma ada di satu-dua versi saja. Mengabaikan beberapa (banyak) hal yang takutnya membuat suasana tulisan ini menjadi membaca skripsi, berikut adalah fungsi skor yang saya pilih:

Skor=f(Skoren,Skorid,Skorww)=SkorenSkoridSkorww=g(26P+25Q+24Ven+23A+22I+2T+O)g(3ΔA+Vid)1.2g(L)\begin{align*} \textsf{Skor} &= f(\textsf{Skor}_\textsf{en}, \textsf{Skor}_\textsf{id}, \textsf{Skor}_\textsf{ww}) \\ &= \textsf{Skor}_\textsf{en} \cdot \textsf{Skor}_\textsf{id} \cdot \textsf{Skor}_\textsf{ww} \\ &= g\Big(2^6P + 2^5Q + 2^4V_\textsf{en} + 2^3A + 2^2I + 2T + O\Big) \cdot g\Big(3\Delta A + V_\textsf{id}\Big)^{1.2} \cdot g(L) \end{align*}

Berikut beberapa penjelasan tambahan. Setiap variabel di rumus tersebut, kecuali LL, dinormalisasi nilainya oleh fungsi norm\text{norm} di bawah, agar berada di rentang nilai [0,1][0,\,1]. Secara matematis, untuk suatu himpunan bilangan XX, kita definisikan fungsi normalisasi sebagai

norm(X):=log(XminXmaxXminX+1)\text{norm}(X) := \log \left( \frac{X - \min X}{\max X - \min X} + 1 \right)

Fungsi g(X)g(X) saya buat dari dasar berpikir seperti ini. Nilai g(X)g(X) perlu ada di rentang [0,)[0, \infty), dan g(MedianX)g(\text{Median}\,X) perlu sama dengan 11. Semakin besar selisih xMedianXx-\text{Median}\,X, maka semakin penting elemen xx untuk diprioritaskan. Hasil perkalian g(X)g(Y)g(X)g(Y) secara kualitatif perlu mengartikan: artikel yang mendesak di XX dan di YY akan menjadi lebih mendesak, artikel yang biasa saja di keduanya tidak berubah status prioritasnya, dan yang kurang penting di keduanya menjadi lebih kurang penting lagi. Setelah bermain-main sejenak, saya memilih mendefinisikan gg sebagai

g(X)=(XminXMedianXminX)g(X') = \left( \frac{X' - \min X'}{\text{Median}\, X' - \min X'} \right)

dengan X=log(X+1)X'=\log(X+1).

Tidak ada alasan selain tebakan awal, saya menetapkan rumus seperti itu; saya memilihnya karena daftar yang dihasilkan sesuai dengan harapan saya. (Oke, sebenarnya ada, tetapi saya tidak punya bukti rigor hal tersebut, dan saya sedang tidak ingin kembali mengenang masa menulis skripsi). Fungsi skor ini sangat bisa untuk ditingkatkan, tetapi melihat hasil yang didapatkan sudah oke, saya malas melakukannya.

Karena itu rumus membutuhkan angka, mari kita ubah priority dan quality menjadi angka. Kita tetapkan Top-priority bernilai 5, lalu menurun secara berurut, sampai ke NA-priority Unknown-priority yang keduanya diberi nilai 1. Hal yang serupa dilakukan untuk kualitas, dengan FA-Class dan FL-Class bernilai 7 (karena keduanya sama-sama (F)eatured, lalu menurun berurut, sampai ke Stub yang kita beri nilai 2. Ini menyisakan artikel dengan kualitas List, Disambig, Redirect, dan Unassessed, yang menurut saya pribagi tidak penting in the grand scheme of things: saya secara berurutan memberi skor 1.6, 1.3, 1, dan 1 bagi mereka.

Hasil

Anda dapat melihat daftar “artikel paling mendesak untuk ada” dalam bentuk halaman HTML di sini (ukuran sekitar 7.4 megabita uncompressed) Melihat sekilas isi tabel tersebut, saya menemukan banyak sekali konsep penting, terutama terkait statistika, yang belum dibuat di WBI. Whoa. Kita benar-benar dapat melihat realita yang terjadi, mungkin sambil terkejut/terheran “Oh artikel itu belum ada di WBI?”.

Oiya, ada baiknya saya juga menyampaikan kekurangan dari daftar ini. Jika ada artikel (baik versi enwiki atau idwiki) yang dialihkan ke judul baru, total pageview selama satu tahun hampir pasti berkurang drastis, menyebabkan peringkat artikel ikut turun dengan tajam. Selain itu, karena kita tidak melakukan analisis kebahasaan ke setiap konten artikel di idwiki, daftar ini tidak dapat memprioritaskan perbaikan artikel idwiki yang seluruhnya hasil terjemahan buruk mesin.

Untungnya, proses yang saya lakukan ini dapat mudah ditingkatkan (entah dengan mengubah metrik-metrik atau rumus peringkat). Selain itu, proses ini juga dapat diubah agar berguna untuk proyek-proyek Wiki lainnya. Saya juga sedang mempertimbangkan menggunakan PAWS atau Toolforge untuk mempermudah pembuatan daftar ini. Akhir kata semoga apa yang saya kerjakan ini, dapat digunakan untuk mempermudah mengembangkan artikel bertopik matematika di Wikipedia Bahasa Indonesia. Salam, kekavigi.

Tambahan: artikel ini saya sertakan di kolom diskusi Warung Kopi Wikipedia ini. Jika ingin berdiskusi, ada baiknya ditulis disana agar para penyunting lain juga dapat menuangkan pendapat / membantu mengembangkan ide Anda.

Saran peningkatan

  1. Apakah anda penutur asli bahasa SQL? dapatkah Anda membuat kueri yang “memecah” total_inlink, agar kita bisa mendapatkan banyaknya inlink yang datang dari artikel dengan prioritas/kualitas tertentu? Jika ini bisa dilakukan, kita dapat membuat hampiran algoritma PageRank yang pernah dipakai Google dalam mengurutkan hasil pencarian mereka.
  2. Jika total_inlink bisa dipecah berdasarkan prioritas/kualitas artikel-artikel yang merujuk, seharusnya hal yang sama juga dapat dilakukan untuk total_outlink… kan?

Catatan kaki

  1. Kedepannya, di versi baru MediaWiki akan ada kolom pagelinks.pl_title yang mencatat judul artikel dari target pranala. Namun, setelah membaca dokumentasi, mungkin tetap menggunakan kedua tabel itu akan menghasilkan data yang lebih baik, daripada berharap pada kualitas data di kolom pagelinks.pl_title. Entahlah.