Ini adalah salah satu proyek penelitian yang sedang saya jalani. Persyaratannya hampir persis seperti milik Anda, dan kami telah mengembangkan algoritme yang bagus untuk menyelesaikan masalah.
Masukan
Masukannya adalah aliran kata atau frasa bahasa Inggris yang tak ada habisnya (kami menyebutnya sebagai tokens
).
Hasil
- Output token N teratas yang telah kita lihat sejauh ini (dari semua token yang telah kita lihat!)
- Keluarkan token N teratas di jendela historis, katakanlah, hari terakhir atau minggu lalu.
Aplikasi dari penelitian ini adalah untuk menemukan topik hangat atau trend topik di Twitter atau Facebook. Kami memiliki perayap yang merayapi situs web, yang menghasilkan aliran kata-kata, yang akan dimasukkan ke dalam sistem. Sistem kemudian akan mengeluarkan kata atau frase frekuensi teratas baik secara keseluruhan atau secara historis. Bayangkan dalam beberapa minggu terakhir kalimat "Piala Dunia" akan muncul berkali-kali di Twitter. Begitu juga dengan "Paul si gurita". :)
String menjadi Integer
Sistem memiliki ID integer untuk setiap kata. Meskipun ada kemungkinan kata yang hampir tak terbatas di Internet, tetapi setelah mengumpulkan sekumpulan besar kata, kemungkinan menemukan kata-kata baru menjadi semakin rendah. Kami telah menemukan 4 juta kata yang berbeda, dan memberikan ID unik untuk masing-masing kata. Seluruh kumpulan data ini dapat dimuat ke dalam memori sebagai tabel hash, memakan sekitar 300MB memori. (Kami telah mengimplementasikan tabel hash kami sendiri. Implementasi Java membutuhkan overhead memori yang besar)
Setiap frase kemudian dapat diidentifikasi sebagai array bilangan bulat.
Ini penting, karena pengurutan dan perbandingan pada bilangan bulat jauh lebih cepat daripada pada string.
Arsipkan Data
Sistem menyimpan data arsip untuk setiap token. Pada dasarnya itu adalah pasangan (Token, Frequency)
. Namun, tabel yang menyimpan data akan sangat besar sehingga kita harus mempartisi tabel secara fisik. Setelah skema partisi didasarkan pada ngram token. Jika token adalah satu kata, itu adalah 1 gram. Jika token adalah frase dua kata, itu adalah 2gram. Dan ini terus berlanjut. Secara kasar pada 4gram kami memiliki 1 miliar rekaman, dengan ukuran tabel sekitar 60GB.
Memproses Arus Masuk
Sistem akan menyerap kalimat yang masuk sampai memori digunakan sepenuhnya (Ya, kita membutuhkan MemoryManager). Setelah mengambil N kalimat dan menyimpannya dalam memori, sistem akan berhenti sejenak, dan mulai mengubah setiap kalimat menjadi kata dan frasa. Setiap token (kata atau frase) dihitung.
Untuk token yang sangat sering, mereka selalu disimpan dalam memori. Untuk token yang lebih jarang, mereka diurutkan berdasarkan ID (ingat kita menerjemahkan String ke dalam array bilangan bulat), dan diserialkan ke dalam file disk.
(Namun, untuk masalah Anda, karena Anda hanya menghitung kata, maka Anda dapat meletakkan semua peta frekuensi kata di memori saja. Struktur data yang dirancang dengan cermat hanya akan menggunakan memori 300MB untuk 4 juta kata yang berbeda. Beberapa petunjuk: gunakan karakter ASCII untuk mewakili Strings), dan ini lebih dapat diterima.
Sementara itu, akan ada proses lain yang diaktifkan setelah menemukan file disk yang dihasilkan oleh sistem, lalu mulai menggabungkannya. Karena file disk diurutkan, penggabungan akan mengambil proses yang sama seperti merge sort. Beberapa desain perlu diperhatikan di sini juga, karena kami ingin menghindari pencarian disk yang terlalu banyak secara acak. Idenya adalah untuk menghindari membaca (proses penggabungan) / menulis (keluaran sistem) pada saat yang sama, dan membiarkan proses penggabungan membaca dari satu disk saat menulis ke disk yang berbeda. Ini mirip dengan menerapkan penguncian.
Akhir hari
Pada akhirnya, sistem akan memiliki banyak token yang sering disimpan dalam memori, dan banyak token lain yang lebih jarang disimpan dalam beberapa file disk (dan setiap file diurutkan).
Sistem membersihkan peta dalam memori ke dalam file disk (urutkan). Sekarang, masalahnya adalah menggabungkan satu set file disk yang diurutkan. Dengan menggunakan proses serupa, kami akan mendapatkan satu file disk yang diurutkan di bagian akhir.
Kemudian, tugas akhir adalah menggabungkan file disk yang telah diurutkan ke dalam database arsip. Bergantung pada ukuran database arsip, algoritme bekerja seperti di bawah ini jika cukup besar:
for each record in sorted disk file
update archive database by increasing frequency
if rowcount == 0 then put the record into a list
end for
for each record in the list of having rowcount == 0
insert into archive database
end for
Intuisi adalah bahwa setelah beberapa saat, jumlah penyisipan akan menjadi semakin kecil. Semakin banyak operasi hanya akan memperbarui. Dan pembaruan ini tidak akan dikenakan sanksi oleh indeks.
Semoga penjelasan lengkap ini bisa membantu. :)
what is the most frequent item in the subsequence [2; 2; 3; 3; 3; 4; 4; 4; 4; 5; 5] of your sequence?