Menjelajahi 40 Juta Postingan dan Komentar HN dalam Peta Embedding
(blog.wilsonl.in)- Proyek pencarian, peta, dan analisis yang mengumpulkan lebih dari 40 juta item dari API publik Hacker News, lalu menambahkan embedding, metadata, dan isi teks ke lebih dari 30 juta komentar dan 4 juta postingan
- Pendekatan awal yang hanya membuat embedding dari judul memiliki keterbatasan karena judul yang ambigu dan bias Ask HN/Show HN, sehingga diubah menjadi pendekatan yang juga memakai isi halaman web tertaut, komentar teratas, dan konteks leluhur komentar
- Seiring skala pemrosesan membesar, proyek ini menggabungkan sekitar 150 GPU RunPod, layanan antrean Rust, proxy DB HTTP/2, UMAP, rendering Canvas, dan server edge; setelah mengganti model, waktu embedding per input turun dari sekitar 600 ms menjadi 6 ms
- Peringkat pencarian tidak hanya memakai kecocokan string sederhana, tetapi menggabungkan cosine similarity, skor HN, dan bobot waktu untuk mencerminkan relevansi semantik, sinyal sosial, dan kebaruan
- Demo publik hanya mencakup data hingga sekitar 10 April 2024, sementara seluruh data dan kode dirilis di GitHub agar dapat dimanfaatkan untuk eksperimen pencarian, rekomendasi, analisis pengguna, dan pembaruan real-time
Cakupan proyek dan data publik
- Membuat peta yang menempatkan semua postingan Hacker News dalam ruang makna, sekaligus membangun alat pencarian, analisis, dan visualisasi
- Eksperimen embedding teks menjadi titik awalnya, dan HN dipilih sebagai dataset yang sesuai karena memiliki banyak konten yang terkurasi serta menyediakan seluruh kontennya secara terprogram
- Embedding merepresentasikan teks sebagai titik dalam ruang berdimensi tinggi, dan jarak relatif antar titik lebih berguna daripada posisi absolut
- Ada tiga penggunaan yang diharapkan
- Pencarian berbasis makna dari konten HN yang telah terakumulasi
- Rekomendasi personal yang disesuaikan dengan area minat
- Analisis sentimen, popularitas, dan sudut pandang berlawanan berdasarkan topik di dalam komunitas
- Lebih dari 30 juta komentar dan 4 juta postingan dirilis sebagai rilis dataset
- Mencakup metadata seperti ID, skor, dan penulis
- Mencakup embedding
- Mencakup teks komentar dan teks halaman web yang di-crawl
- Kodenya dirilis di repositori GitHub hackerverse
Pengumpulan data Hacker News
- HN menyediakan API publik yang sederhana, dan semua objek diambil sebagai
item maxitem.jsonmenyediakan ID terbesar, dan pada saat penulisan ID maksimumnya sudah melewati 40 juta- Meski waktu respons rata-rata 10 ms, crawling 40 juta item secara berurutan akan memakan lebih dari 4 hari, sehingga diperlukan pemrosesan paralel
- Layanan pengumpulan cepat dibuat dengan Node.js, tetapi pendekatan semaphore dan antrean Promise lambat karena sebagian besar waktu CPU dihabiskan pada kode JS di user space
- Setelah itu, pekerjaan fetch didistribusikan ke semua CPU dengan API
worker_threads, dan performa ditingkatkan dengan cara memenuhi seluruh core - Pengumpulan paralel membuat urutan menjadi acak, sehingga marker penyelesaian dicatat berdasarkan urutan ID agar tidak ada item yang terlewat saat proses terhenti
- Ada juga beberapa karakteristik yang diamati dari API HN
- Skor tampaknya tidak turun di bawah -1
- Downvote pada postingan dan jumlah vote pada komentar tidak dapat diambil
- Sebagian postingan dan komentar memiliki judul, teks, dan URL kosong meski tidak berstatus dihapus atau di-flag
- ID komentar bisa lebih kecil daripada leluhurnya, kemungkinan karena pemindahan pohon komentar
- Crawler HN juga dipisahkan sebagai proyek TypeScript tersendiri bernama crawler-toolkit-hn
Embedding pertama dan infrastruktur
- Awalnya, embedding dibuat dengan asumsi bahwa judul postingan saja sudah cukup untuk representasi makna
- Perbandingan model mengacu pada Massive Text Embedding Benchmark, dan model pertama yang dipilih adalah BGE-M3
- Selain embedding padat umum, BGE-M3 juga dapat menghasilkan lexical weights, sehingga bisa digunakan untuk pencarian hibrida yang digabungkan dengan metode seperti BM25
- Infrastruktur pembuatan embedding tidak sederhana
- Model yang bagus bisa memiliki ratusan juta hingga miliaran parameter
- Jauh lebih efisien di GPU, tetapi klaster GPU mahal
- Jika inferensi memakan ratusan ms per input, memproses 40 juta input dengan satu GPU akan mendekati skala 1 tahun
- Karena data/server dan GPU berjauhan, pipeline harus dijaga agar GPU tidak menganggur
- RunPod digunakan untuk mendistribusikan mesin GPU yang berjalan di data center sebagai container, memanfaatkan GPU yang relatif murah seperti RTX 4090
- Karena GPU tersebar di seluruh dunia sehingga latensi koneksi DB dan overhead koneksi menjadi masalah, dibuatlah db-rpc
- Mem-proxy kueri SQL ke DB lokal melalui HTTP/2
- Menggunakan pool koneksi bersama yang besar
- Menangani banyak kueri dalam satu koneksi melalui multiplexing HTTP/2
- AWS SQS memiliki batas kecepatan yang rendah dan biaya per pesan yang membebani untuk jutaan pesan tugas kecil, sehingga dibuat layanan antrean Rust berbasis RocksDB bernama queued
- Menangani 100K+ op/s pada satu node
- Mengurangi beban batching, ukuran pesan, batas kecepatan, dan biaya
- Setelah diskalakan hingga sekitar 150 GPU, embedding untuk 40 juta postingan dan komentar selesai dalam beberapa jam
- Saat itu biaya waktu embedding per input sekitar 600 ms, dan utilisasi GPU tetap tinggi sepanjang waktu
Memperkaya konteks dengan crawling halaman web
- Pendekatan embedding hanya dari judul ternyata tidak cukup
- Banyak postingan memiliki judul yang aneh, kreatif, atau ambigu
- Frasa
Ask HNdanShow HNmengambil porsi besar dari keseluruhan judul, sehingga cenderung terklaster bersama tanpa terkait topiknya
- Postingan teks dan komentar bisa memakai teksnya sendiri, tetapi sebagian besar postingan tautan perlu melakukan crawling halaman web yang ditautkan
- Sebuah layanan Rust mengambil URL dan mem-parsing metadata seperti judul, gambar, penulis, dan teks isi dari HTML
- Versi awal Node.js 10 kali lebih lambat daripada versi Rust pada pekerjaan yang intensif CPU, dan performa ditingkatkan lewat penulisan ulang dengan Rust
- Ekstraksi teks dilakukan dengan mem-parsing HTML menggunakan scraper, menghapus elemen HTML5 yang secara semantik bukan konten utama, lalu menelusuri tree yang tersisa
- Link rot juga cukup besar
- Sekitar 200 ribu URL gagal karena 404, kegagalan lookup DNS, atau timeout koneksi
- Ini kurang dari 5% dari 4 juta halaman
- Untuk mengurangi data yang hilang, sebagian artikel lama diambil melalui Wayback API milik Internet Archive
- Batas kecepatan Internet Archive sangat rendah, sekitar 5 permintaan per menit
Strategi embedding kedua
- Halaman web panjang, tetapi BGE-M3 mendukung context window 8192 token
- Namun karena BGE-M3 lambat, model diganti ke jina-embeddings-v2-small-en
- Jumlah parameternya jauh lebih sedikit
- Performanya juga baik berdasarkan MTEB
- Waktu inferensi turun menjadi sekitar 6 ms, 100 kali lebih cepat
- Karena input panjang, memperbesar ukuran batch menyebabkan OOM sehingga GPU tidak bisa dipenuhi sepenuhnya
- Untuk melengkapi halaman yang teksnya sedikit atau tidak berhasil diambil, komentar HN teratas dari postingan ditambahkan setelah isi teks
- Komentar level teratas digunakan dengan asumsi
item.kidssudah diperingkat - Komentar yang dihapus, dead, atau berskor negatif dikecualikan
- Input dibatasi maksimal 64 KiB
- Komentar level teratas digunakan dengan asumsi
- Karena komentar bisa kurang bermakna jika berdiri sendiri, konteks yang lebih panjang disusun dengan menelusuri hingga komentar leluhur dan judul postingan
- Nilai besar seperti embedding dan teks disimpan dalam tabel
kvterpisah- Jika disimpan bersama di dalam baris, baris menjadi terlalu gemuk
- Pembaruan kolom kecil pun menjadi mahal
- Perubahan skema juga menjadi mahal
Membuat peta semantik 2D dengan UMAP
- UMAP adalah teknik reduksi dimensi yang berupaya mempertahankan hubungan makna sambil menurunkan embedding berdimensi tinggi ke dimensi yang lebih rendah
- Vektor embedding 1024 dimensi direduksi menjadi titik 2D untuk digunakan dalam scatter plot dan visualisasi peta
- UMAP menerima graf PyNNDescent dan embedding asli sebagai input, serta menggunakan
metric="cosine",n_components=2 - Pelatihan input berdimensi tinggi berjumlah jutaan memakan waktu lama, sehingga digunakan VM
c7i.metal-48xldi EC2- Memaksimalkan penggunaan prosesor 96 core
- Setelah sekitar 1 jam 30 menit, matriks 2D dihasilkan
- Embedding 2D yang dihasilkan dan model UMAP yang telah dilatih disimpan agar embedding baru nantinya juga dapat ditransformasikan tanpa pelatihan ulang
- Scatter plot pertama memiliki terlalu banyak titik, lalu kepadatan dikurangi dengan hanya memilih postingan berskor tertinggi per sel grid untuk menampilkan judul
- Pada embedding kedua yang memasukkan lebih banyak konteks, postingan yang sulit diposisikan hanya dari judul ditempatkan lebih akurat di dekat konten terkait
Cosine similarity dan peringkat pencarian
- Inti pemanfaatan embedding adalah menemukan kemiripan antara dua embedding
- Dalam embedding teks, cosine distance/similarity lebih sering digunakan daripada jarak Euclidean umum
- Cosine distance berguna ketika arah lebih penting daripada magnitudo
- Diskusi panjang terkait X seharusnya lebih mirip dengan X daripada diskusi panjang terkait Y
- Jika magnitudo ikut diperhitungkan, hubungan seperti ini bisa menyesatkan
- Perhitungan inti yang digunakan adalah dot product antara matriks embedding dan embedding kueri
- Jika vektornya adalah vektor satuan, tidak diperlukan pembagian magnitudo terpisah
- Hasil pencarian tidak diurutkan hanya berdasarkan kemiripan murni
- Cosine similarity adalah faktor besar, tetapi bukan satu-satunya faktor
- Skor HN digunakan sebagai bukti sosial
- Bobot waktu direfleksikan sebagai faktor negatif yang sebanding dengan
log(age)agar konten lama cepat tergeser pada kueri yang mengutamakan kebaruan
Aplikasi peta di browser
- Tujuannya adalah membuat peta interaktif yang memungkinkan ruang embedding HN dijelajahi seperti Google Maps
- Perilaku yang diinginkan sudah jelas
- Saat diperbesar dengan pinch atau roda mouse, lebih banyak titik ditampilkan
- Jarak antartitik juga ikut membesar
- Sebagian titik memiliki label, tetapi tidak semuanya
- Saat titik diklik, detail postingan ditampilkan
- Mendukung touch dan mouse baik di mobile maupun desktop
- Mengirim semua titik sekaligus ke klien tidak cocok karena jumlahnya jutaan
- Digunakan struktur yang membagi ruang peta menjadi tile grid, dan klien hanya mengambil tile yang diperlukan
- Tile dapat diidentifikasi dengan koordinat
(x, y) - Dapat disimpan di penyimpanan KV seperti S3
- Mudah dideploy tanpa logika sisi server
- Tile dapat diidentifikasi dengan koordinat
- Level pembesaran ditangani dengan pendekatan LOD
- Di setiap level, grid cell per sumbu dibagi menjadi 2 kali lebih banyak
- Titik yang dipilih pada level sebelumnya juga disalin ke level berikutnya agar titik tidak menghilang saat diperbesar
- Ukuran tile ditargetkan di bawah 20KiB saat dikompresi
- Dibatasi sekitar 1.500 titik
- Menggunakan 8 byte untuk
(x, y), 4 byte untuk ID, dan 2 byte untuk skor per titik
- Dalam rendering aplikasi web, pendekatan ribuan elemen DOM sangat merusak performa
- Implementasi akhir menggunakan Canvas dan menggambar ulang setiap kali viewport diperbarui
- Meski menggambar ulang ribuan titik di setiap frame, tetap berjalan mulus dan sederhana
- Pelabelan dilakukan dengan berulang kali memilih postingan berskor tertinggi, tetapi mengecualikannya jika bertumpang tindih dengan label yang sudah ada
- Pemeriksaan tabrakan menggunakan implementasi R-tree RBush
- Panjang label diperkirakan dengan array byte panjang judul dan rumus yang disesuaikan, bukan
measureText()browser
- Perhitungan kotak label awal dan tabrakan bersifat CPU-intensive, sehingga dipindahkan ke Web Workers
- OffscreenCanvas juga dicoba, tetapi tidak banyak berdampak karena logika renderingnya sudah efisien
Medan, batas, dan label kota
- Jika peta hanya berisi titik, orientasi dan daya tarik visualnya kurang, sehingga konsep medan dan kota ditambahkan
- Karena tidak ada geografi nyata atau batas politik, medan dianalogikan sebagai cara untuk menunjukkan kepadatan titik
- Kepadatan titik digunakan sebagai sinyal yang dengan cepat menunjukkan area dengan banyak aktivitas, minat, konten, partisipasi, popularitas, dan diskusi
- Awalnya Kernel Density Estimation dipertimbangkan, tetapi percobaan dengan library standar memakan waktu terlalu lama
- Sebagai gantinya, setiap titik dipetakan ke sel grid besar, jumlah per sel dihitung, lalu Gaussian blur diterapkan
- Nilai kepadatan linear membuat sebagian besar area terlihat mendekati 0, sehingga petanya kurang bagus
- Setelah menerapkan
log(density + 1), terbentuk hierarki yang jauh lebih alami, dan tempat bertemunya level kepadatan berbeda tampak seperti batas implisit - Alih-alih gambar raksasa, dibuat path SVG agar klien menggambarnya sebagai poligon
- Efisien karena hanya ada 4 warna
- Batas tetap tajam meski diperbesar
- Kurva tertutup per level dihitung dengan fungsi contour OpenCV
- Label kota merepresentasikan topik umum dalam radius tertentu
- Nama kota di-embed, lalu posisi
(x, y)diperoleh dengan model UMAP yang tersimpan - Pembuatan otomatis juga dicoba
- Mencoba membuat nama kota dengan LLM, tetapi sulit mendapatkan output yang diinginkan secara stabil lewat prompt
- K-means tidak menemukan banyak cluster bermakna seperti yang mungkin dikelompokkan manusia
- Pada akhirnya, beberapa kota dicatat secara manual sambil menjelajahi peta langsung, dan memakan waktu sekitar 1 jam
Deploy di edge dan responsivitas
- Eksplorasi peta harus cepat dan responsif, sehingga mengurangi latensi fetch data menjadi penting
- Awalnya semua data peta ditempatkan di region ENAM Cloudflare R2, tetapi latensinya berkisar dari 600ms hingga beberapa detik
- Meski latensi fisik sekitar 200ms, itu belum cukup baik mengingat 100ms adalah ambang ketika sesuatu terasa seperti merespons seketika
- Untuk mengurangi latensi, data dipindahkan lebih dekat ke pengguna
- Server kecil ditempatkan di Virginia, San Jose, London, dan Sydney, dengan server Rust untuk menyajikan data
- Klien memanggil
/healthzdari beberapa edge beberapa kali, lalu memilih server yang merespons paling cepat - Pendekatan seperti Anycast atau CDN juga memungkinkan, tetapi tidak digunakan karena biaya dan kompleksitas berlebihan
- Penggunaan memori proses server edge 2–4 kali lebih besar daripada data mentah, sehingga masih menjadi tanda tanya
- Kemungkinan penggunaan tipe yang keliru
- struct padding
- Over-allocation pada
Vec,HashMap - Kemungkinan fragmentasi atau inefisiensi memory allocator
Hasil pencarian semantik dan batasannya
- Pada kueri sederhana seperti “entering the tech industry”, hasil dengan banyak upvote dan hasil yang kurang mendapat perhatian sama-sama muncul, dan relevansi serta kegunaannya terlihat baik
- Dibandingkan layanan pencarian HN yang sudah ada, pencarian embedding semantik menemukan hasil meski tidak cocok secara literal
- Kueri berbentuk pertanyaan seperti “what happened to wework” juga menampilkan hasil dari berbagai tahun tentang PHK, penurunan harga saham, kebangkrutan WeWork, dan sebagainya
- Hasil pencarian tetap cocok meski tidak benar-benar memuat kata “what happened” atau tidak berbentuk pertanyaan
- Salah satu masalahnya adalah hasil bawah yang benar-benar tidak relevan ikut masuk karena hasil yang tidak cukup mirip tidak difilter
- Ini diperlakukan sebagai masalah yang mudah diperbaiki
- Pada pencarian “career growth”, muncul esai-esai kreatif dan beragam yang tidak memuat kata tersebut secara literal
- Kualitas kurasi dan skor HN membantu kualitas pencarian
- Aplikasi ini memiliki saran kueri yang di-hardcode seperti “linus rants”, “self bootstrapping”, “cool things with css”
Menganalisis komunitas virtual dan komentar
- Embedding dapat digunakan untuk membuat fitur subkomunitas virtual
- Saat pengguna memasukkan nama atau deskripsi komunitas, postingan yang melampaui ambang kemiripan tertentu langsung dikelompokkan
- Karena HN tidak memiliki fitur untuk memecah postingan menjadi kategori yang lebih rinci, ini adalah cara untuk langsung membuat kurasi yang berpusat pada minat tertentu
- Cuplikan dan gambar pada kartu hasil diambil dari metadata halaman yang disimpan oleh web crawler
- Ikon situs disederhanakan dengan mengambil
/favicon.icodomain di sisi klien, alih-alih melakukan parsing metadata yang rumit - Thread komentar juga dapat ditampilkan dengan cara yang sama
- Skor komentar tidak disediakan oleh HN API, sehingga hanya pengurutan kronologis yang memungkinkan
- Untuk pemeringkatan tanpa skor komentar, pendekatan yang memanfaatkan riwayat komentar pengguna, partisipasi di sekitar komentar tersebut, postingan, topik, konten, dan sebagainya dinilai memungkinkan
- Menemukan pengguna yang berpengaruh atau aktif dalam topik tertentu juga dimungkinkan
- Pada kueri “cloudflare”,
jgrahamcdaneastdakotamuncul di posisi teratas - Kedua pengguna tersebut masing-masing adalah CTO dan CEO Cloudflare
- Pada kueri “cloudflare”,
- Pekerjaan ini diproses dengan operasi matriks, tanpa mengklasifikasikan komentar secara terpisah atau menggunakan pencarian kata kunci
- Post-filtering biasanya lebih cepat dan sudah memadai dibanding pre-filtering
- Pre-filtering harus menghapus baris yang sesuai dari matriks embedding, sehingga mungkin membutuhkan penyalinan memori berukuran besar atau komputasi vektorisasi parsial yang lambat
- Lebih baik mencari baris yang mirip terlebih dahulu, lalu memfilter hasilnya
- Ambang minimum itu penting
- Item yang tidak relevan pun bisa memiliki tingkat kemiripan sekitar 0,6
- Tanpa ambang, pengguna dengan jumlah komentar sangat besar dapat mendominasi peringkat hanya karena skala
Analisis sentimen dan popularitas seluruh data komentar
- Analisis skala besar yang ingin dilakukan dengan 30 juta komentar adalah popularitas dan sentimen
- Tujuannya adalah melihat bagaimana perasaan HN terhadap topik tertentu seiring waktu, bagaimana peristiwa besar memengaruhi sentimen, serta bagaimana topik minat tumbuh dan menurun
- Karena tidak ada data sentimen, digunakan model klasifikasi sentimen open source dari Hugging Face
- Model yang dipilih adalah TweetEval, model yang dilatih pada konten media sosial
- Karena TweetEval adalah model untuk tweet pendek, hanya komentar itu sendiri yang digunakan sebagai input, tanpa menambahkan konteks leluhur seperti saat embedding
- Komentar dimasukkan ke antrean, diproses di cluster GPU, lalu hasilnya disimpan
- Karena modelnya kecil, ukuran batch diperbesar untuk meningkatkan efisiensi GPU
- Peningkatan ukuran batch memakai lebih banyak VRAM, tetapi dapat mengurangi transfer memori host-GPU dan meningkatkan paralelisme
- Pada model Transformer, input batch harus berbentuk persegi panjang, sehingga diberi padding mengikuti panjang input terpanjang
- Jika satu input panjang bercampur dengan beberapa input pendek, ukuran keseluruhan input dan state internal dapat meningkat besar
- Akibatnya, spike memori dan OOM dapat terjadi
- Dalam contoh analisis sentimen Rust, sentimen positif terhadap Rust secara umum cukup banyak
- Ada spike positif sekitar waktu pengumuman Rust 1.0
- Postingan yang lebih negatif berkorelasi dengan banyak komentar negatif menurut model
- Popularitas per bahasa juga diperkirakan dengan memberi bobot pada skor dan kemiripan
- HN tidak menyediakan skor komentar, sehingga skor komentar tidak dapat digunakan
- Rust berjalan baik, tetapi tampaknya belum sepopuler beberapa bahasa lain
- Ambang kemiripan mungkin perlu disesuaikan, sehingga hasilnya bisa saja keliru
Mengakselerasi komputasi numerik skala besar dengan GPU
- Kueri analisis membutuhkan 10–30 detik bahkan di mesin 32-core, terlalu lambat untuk eksperimen interaktif
- Setelah mempertimbangkan indeks atau preprocessing, pendekatannya dialihkan ke penggunaan GPU untuk komputasi numerik tervirtualisasi
- CuPy dan cuDF masing-masing menyediakan API yang mirip NumPy dan pandas, tetapi berjalan di GPU
- Proses porting relatif sederhana, dan waktu kueri turun ke kisaran ratusan ms
- Karena kecepatannya sudah cukup tinggi, graf ANN pun tidak digunakan
- Bagian yang sulit adalah memuat matriks embedding besar ke GPU
- Matriks embedding komentar berukuran 30M x 512
- Sulit menampung lebih dari 1 salinan matriks di memori sistem maupun memori video
- Cara loading sederhana dapat membuat beberapa salinan
- Membaca byte dari disk
- Memuatnya sebagai array NumPy
- Mengonversinya menjadi array CuPy
- Menyalinnya ke GPU
- Proses ini dapat membuat total 4 salinan, dan 3 di antaranya berada di memori
- Cara akhirnya adalah memetakan matriks di disk ke memori, mengalokasikan lebih dulu matriks tak terinisialisasi berukuran sama di GPU, lalu menyalinnya per chunk
- Cara ini menghindari pembacaan terlebih dahulu ke memori Python, dan hanya memakai masing-masing tepat 1 salinan di RAM sistem dan VRAM
Demo dan langkah berikutnya
- Aplikasi demo tersedia di hn.wilsonl.in
- Halaman utama berisi peta dan pencarian, sementara tombol di kanan atas memberi akses ke komunitas dan alat analisis
- URL komunitas atau hasil analisis menyimpan kueri di URL, sehingga dapat dibagikan dengan orang lain
- Dataset demo berhenti sekitar 10 April 2024 dan tidak mencakup postingan serta komentar live terbaru
- Ada beberapa ide yang ingin dieksplorasi ke depan
- Data live yang terus diperbarui
- Sistem rekomendasi berbasis deep learning yang berjalan di atas web terkurasi HN
- Meningkatkan hasil pencarian melalui pelatihan reranker
- Jalur dan perjalanan menarik di atas peta
- Analisis hubungan kemiripan dan pertentangan antar-pengguna
- Analisis pengguna yang paling ahli di niche tertentu
- Seluruh data dan kode dapat dilihat di GitHub
2 komentar
Opini Hacker News
Untuk proyek satu orang, ini pekerjaan yang sangat mengesankan
Grafik analisis sentimen dari waktu ke waktu menonjol, dan menarik karena ini pertama kalinya saya melihat Rust dengan cara seperti ini. Saya juga penasaran topik apa yang paling positif seiring waktu, dan apakah ada topik yang tiba-tiba turun tajam
Kalimat “secara umum HN tampaknya punya banyak sentimen negatif” juga terasa sesuai dengan pengalaman saya tentang media sosial. Akan menarik juga melihat perbandingan sentimen menurut platform media sosial dan periode waktu
Sentimen negatif terlihat menonjol karena awalnya saya mengharapkan grafik sentimen yang lebih jelas. Saya membayangkan umumnya netral hingga positif, lalu melonjak ke positif di sekitar tulisan positif dan ke negatif di sekitar tulisan negatif. Namun, di hampir semua kueri, sentimennya nyaris selalu negatif. Bahkan tulisan positif tampaknya menarik banyak negativitas menurut model dan pendekatan ini; bisa jadi keduanya keliru, jadi saya ingin menggalinya lebih lanjut dalam tulisan blog berikutnya
https://openpipe.ai/blog/hn-ai-crypto
Tanpa dasar kuat, tapi saya merasa para engineer umumnya kritis, sementara umpan balik positif cenderung diberikan dengan menekan +1 daripada ditulis berulang-ulang. Kritik lebih sering ditulis langsung :)
Ini contoh yang bagus bagi orang yang tidak terbiasa dengan data engineering/MLOps
Saya menyarankan membuat klaster hierarkis atas titik-titik dengan HDBSCAN, lalu menggunakan model untuk membuat nama klaster internal. Dengan begitu, topik bisa lebih mudah dijelajahi sampai ke daun dengan menampilkan subbagian berdasarkan keterhubungannya dengan node saat ini
Warna grup harus lebih jelas, dan keberadaan klaster akan membantu. Ukuran teks untuk tiap tulisan sebaiknya berubah berdasarkan kepentingan atau relevansinya, baik terhadap keseluruhan maupun terhadap pencarian saat ini. Jika ada lebih banyak ringkasan klaster internal, beberapa tulisan bisa digantikan oleh ringkasan grup sampai pengguna memperbesar tampilan, sehingga kepadatan teks juga berkurang
https://docs.rapids.ai/api/cuml/stable/api/#clustering / https://developer.nvidia.com/blog/faster-hdbscan-soft-cluste...
Masukan tentang membuat peta lebih jelas juga bagus, dan saya rasa ada cukup banyak pendekatan mudah untuk memperbaikinya. Ini juga masuk daftar pekerjaan :)
Cakupan proyeknya luar biasa besar
Namun, entah itu jina atau bge-3/flag, embedding dan tokenizer-nya tampaknya kurang cocok untuk topik teknis. Kata-kata bahasa alami tidak masalah, tetapi saat mencari konsep teknis seperti “xaml” atau “simd”, setelah input ditokenisasi, hasilnya cenderung mencari kata-kata yang terdengar mirip
Sebagai masukan konstruktif, akan bagus jika ada cara agar hasil “papan peringkat HN” yang sama tidak terus ditampilkan ketika topiknya terlalu niche sehingga tidak ada hasil. Jika mencari kata yang tidak familier bagi embedding, “Stephen Hawking has died” sering muncul
Saya juga tidak yakin seberapa baik analisis sentimennya bekerja. Sentimen negatif tampak terlalu banyak dan tidak sesuai realitas; bahkan ketika mencari sesuatu seperti “Mr Rogers”, yang kemungkinan besar akan dipandang sangat positif oleh HN, muncul puncak negatif yang besar. Jika mencari “Carter”, ada puncak negatif besar terkait wafatnya Rosalynn Carter, padahal tulisan aslinya adalah submit yang membahas hal-hal hebat yang dilakukan pasangan Carter
“Popularitas dari waktu ke waktu” sepertinya perlu dinormalisasi berdasarkan median jumlah suara tulisan pada bulan/tahun tersebut. Jika hanya menggambar jumlah tulisan, garis trennya akan terus naik. Popularitas “diesel” memperlihatkan maksud saya: istilah ini mencapai puncak 10 tahun lalu. Atau mungkin metriknya seharusnya berupa tingkat kemunculan kata kunci, atau jumlah item yang indeks kemiripan kosinusnya terhadap kueri lebih kecil dari x, bukan skor tulisan
Fitur dinamis untuk menghapus tulisan dengan mengekliknya lalu menghitung ulang ambang kemiripan sangat bagus
Ada alat hebat yang melakukan hal yang hampir sama untuk dataset apa pun: https://github.com/enjalot/latent-scope
Tentu saja, skala proyek asli menambahkan banyak kompleksitas yang menarik, dan alat ini tidak dapat menangani skala sebesar itu, tetapi bagus untuk dataset berukuran menengah
Ingin menganalisis apakah promosi diri meningkat di HN
Di sini promosi diri didefinisikan bukan sebagai tulisan berbentuk “Show HN: Something ...”, melainkan “Show HN: I ...”
Dari 100 teratas saat ini, misalnya “Show HN: Exploring HN by mapping and analyzing 40M posts and comments for fun” dan “Show HN: Browser-based knitting (pattern) software” bukan judul promosi diri. Subjeknya masing-masing adalah eksplorasi dan perangkat lunak
Sebaliknya, “Show HN: I built a non-linear UI for ChatGPT” dan “Show HN: I created 3,800+ Open Source React Icons” adalah judul promosi diri. Subjeknya masing-masing adalah “I”
Jika secara sederhana memeriksa judul yang dimulai dengan “Show HN: I” untuk setiap tahun mulai 1 April di hasil pencarian Algolia, lalu membaginya dengan jumlah hasil sepanjang tahun tersebut dan menggambarkannya sebagai grafik, hasilnya seperti berikut
2023 ****************************************
2022 ***********************************
2021 ***************************
2020 **************************************
2019 *************************
2018 *************
2017 *******
2016 **********
2015 ********
2014 ************
2013 *********************
2012 *****************
2011 *********
2010 ***
Saat saya tumbuh besar, rasanya promosi diri umumnya dianggap sebagai sifat yang buruk. Saya diajari bahwa tindakanlah yang seharusnya mempromosikan diri kita, bukan dengan sengaja menarik perhatian ke sana; rasanya budaya itu sedang berubah
Jika promosi diri memang benar-benar meningkat, saya penasaran apakah itu pengaruh media sosial dan sejenisnya. Di YouTube saya juga merasakan kenaikan serupa, tetapi hanya sebatas kesan bahwa ada banyak video rekomendasi yang dimulai dengan “I.....”, tanpa data
Jadi pembagian Anda antara promosi diri dan bukan promosi diri, menurut saya, lebih tepatnya adalah kasus ketika judulnya sangat jelas menunjukkan promosi diri versus kurang jelas menunjukkannya. Namun, frasa “Show HN” sendiri tampaknya hanya dipakai untuk promosi diri, jadi orang yang tahu konvensinya akan paham bahwa itu promosi diri meskipun tidak ada “I”
Semuanya berarti “lihat, saya membuat sesuatu yang keren, bagaimana menurutmu?”
Misalnya, orang Jerman menuduh Einstein melakukan promosi diri, sementara di Amerika ada budaya selebritas. Bisa jadi ini fenomena siklus
Sepertinya ini tulisan paling keren yang saya lihat di HN tahun ini
Saat pertama melihatnya, tidak langsung jelas, tetapi aplikasi sebenarnya ada di sini: https://hn.wilsonl.in/
Saya tidak menyindir; menurut saya itu ide yang bagus
Saya juga penasaran apakah frasa pencarian di-embedding per kata, dan apakah memakai model yang sama dengan yang digunakan untuk dokumen. Saya mencari “lead generation”, yang seharusnya dipahami oleh embedding frasa non-kata-tunggal yang benar, tetapi malah keluar hasil tentang keracunan timbal
Rekomendasi modern untuk UMAP adalah Parametric UMAP: https://umap-learn.readthedocs.io/en/latest/parametric_umap....
Ini melatih MLP Keras kecil untuk melakukan reduksi dimensi ke 2D sambil meminimalkan loss UMAP. Keuntungannya, model ini kecil sehingga bisa disimpan dan digunakan kembali untuk memprediksi data baru yang belum dikenal. Model UMAP yang dilatih secara tradisional berukuran besar. Selain itu, karena memakai GPU, secara teori pelatihannya jauh lebih cepat
Kekurangannya, implementasi di paket Python UMAP tidak terlalu bagus, dan membuat serta memasukkan seluruh dataset node/edge yang diperluas ke GPU. Karena itu, pelatihan hanya bisa sampai sekitar 100 ribu embedding sebelum kehabisan memori
Pipeline yang sepenuhnya tanpa supervisi dari UMAP → HDBSCAN → pelabelan klaster AI sangat berguna, jadi saya jadi ingin membuat implementasi Parametric UMAP yang lebih skalabel
Untuk sesuatu yang terlihat seperti proyek hobi eksploratif, ini pekerjaan yang luar biasa besar. Bukan bermaksud meremehkan pencapaiannya—ini benar-benar keren—tetapi saya terkejut dengan besarnya upaya yang dikeluarkan
Mereka memakai 150 GPU hanya untuk menghitung embedding, dan mengembangkan dua sistem kustom bernama db-rpc dan queued untuk komunikasi antarserver. Ada juga banyak pekerjaan pendukung dan komputasi lainnya
Saya penasaran dengan konteks proyek ini. Saya juga ingin tahu bagaimana mereka mendapatkan dana dan waktu yang dibutuhkan untuk riset semacam ini
Dari sudut pandang saya yang sudah cukup sering mengerjakan hal serupa secara profesional, saya pernah memetakan lanskap makalah akademik dan paten, dan saya tidak yakin 150 GPU benar-benar diperlukan. Kalau pada akhirnya hanya proyeksi 2D dan clustering, pendekatan tradisional seperti bag-of-words atau topic modeling jauh lebih mudah dan murah, dan saya rasa perbedaan kualitasnya hampir tidak terasa. Memakai grafik penulis dan thread komentar juga bisa menghasilkan hasil serupa
GPU ternyata murah, dan sebagian besar skalanya saya naikkan hanya karena saya tidak sabar :) Seluruh klaster juga hanya berjalan beberapa jam
Kalau ada tautan ke pekerjaan yang pernah Anda lakukan, saya ingin melihatnya. Kelihatannya menarik, jadi saya ingin membaca lebih lanjut
Dari sisi dana dan waktu, mungkin ia sedang berada di antara pekerjaan atau perusahaan berikutnya, dan berhasil secara finansial dari karier atau bisnis sebelumnya sehingga mengerjakannya dengan biaya sendiri. Pemanfaatan GPU-nya juga sangat efisien, jadi biayanya tampaknya tidak terlalu besar
Dengan menerapkan machine learning klasik seperti SVM dengan kalibrasi probabilitas pada embedding semacam ini, kita bisa mendapatkan hasil bagus untuk klasifikasi dan clustering, dengan kecepatan lebih dari 100 kali lebih cepat dibanding fine-tuning LLM
Biasanya orang tidak melakukannya seperti demo ini, melainkan menormalisasi vektor
Saat menggunakan vektor yang sudah dinormalisasi, jarak Euclidean mengukur jarak antara ujung dua vektor. Sebaliknya, jarak kosinus mengukur panjang proyeksi satu vektor ke vektor lainnya
Vektor 2D yang dinormalisasi sebenarnya hanyalah vektor 1D. Jika ingin menunjukkan hubungan 2D, kita perlu memakai vektor 3D agar kembali memiliki 2 derajat kebebasan
Judulnya terlewat ya.