Kinerja Filter Senonoh di Jawa

9

Saya memiliki persyaratan untuk menyaring kata-kata kotor dari kiriman pengguna dalam aplikasi web berbasis Java. Klien menyadari Masalah Scunthorpe dan Masalah Clbuttic dan telah menerima konsekuensinya. Tolong, saya tidak ingin debat tentang kekurangan sensornya.

Ada dua bit data:

  1. Pengiriman pengguna, yang berpotensi mengandung 500 kata atau lebih;
  2. Tabel database satu kolom yang berisi kata-kata yang tidak diizinkan. Mungkin ada ribuan catatan dalam tabel ini.

Solusi saat ini tampaknya salah bagi saya:

  1. Seluruh tabel dimuat ke String statis [] pada startup ke Singleton (dengan demikian berada dalam memori).
  2. Untuk setiap pengiriman pengguna, kami mengulang-ulang array dan melakukan .indexOf () untuk melihat apakah ada kata yang diberikan dalam String [] muncul dalam pengiriman.
  3. Jika muncul, kami ganti dengan% $ # @% - karakter gaya. Ini dilakukan dengan tokenizing pengiriman pengguna, perulangan melalui seluruh pengiriman pengguna sebagai token (lagi), dan mengganti setiap instance dari kata yang ditemukan.

Mungkin ada kecemerlangan dalam solusi ini, tapi saya skeptis. Dan setelah melihatnya sebentar saya tidak dapat menemukan jalan saya melewatinya.

Pertanyaannya adalah, apa solusi yang akan memberikan kinerja yang baik dan semoga cukup masuk akal untuk dipelihara oleh pengembang di masa depan setelah saya dipecat karena gagal menyaring kata-kata tidak jelas yang belum pernah saya dengar?

ikan blueishgold
sumber
Anda mengatakan itu tampak salah bagi Anda, tanpa memberi tahu kami mengapa menurut Anda itu salah. Kemudian Anda meminta solusi yang tepat, tanpa memberi tahu kami, dengan cara apa solusi saat ini tidak cukup. Berapa banyak teks per detik yang Anda dapatkan, berapa banyak yang bisa Anda proses?
pengguna tidak diketahui
Saya pikir solusinya salah, terutama karena basis kode yang saya gunakan tidak memadai dan ceroboh. Mengingat bias saya, saya tidak percaya ketidakpercayaan saya sendiri. Saya merasa bahwa pendapat orang lain akan bermanfaat. Hal yang memicu alarm bagi saya adalah String [] (apa, apakah ini 1999?), Melompati String yang sangat besar [] alih-alih kumpulan data yang jauh lebih kecil yang dikirimkan pengguna, membuat lingkaran di dalam lingkaran String [] dengan pengiriman pengguna tokenized, dan sebagainya. Pemanfaatan yang diharapkan tidak ditentukan, idealnya solusi elegan dengan kinerja yang wajar akan menyenangkan.
blueishgoldfish
2
'Kinerja yang wajar' dapat berarti apa saja. Jika Anda tidak memiliki tujuan yang konkret, Anda tidak bisa tahu apakah Anda mencapainya. Jika Anda mempercepat suatu proses, sehingga prosesnya 100 kali lebih cepat - apakah ini tujuan? Jika pengguna menunggu 1 ms atau 1/10? Pengguna tidak akan mendapat manfaat dari pekerjaan Anda.
pengguna tidak diketahui

Jawaban:

18

Satu-satunya cara untuk melakukan filter kata secara cerdas adalah dengan menggunakan sistem pencocokan phonik. Saya menulis filter kata-kata kotor yang sangat efektif untuk permainan online multi-pemain besar-besaran yang sangat populer untuk remaja dan remaja beberapa tahun yang lalu di Jawa.

Itu didasarkan pada algoritma Double MetaPhone yang sangat dimodifikasi yang di-tweak untuk lebih akurat daripada default yang sesuai dengan banyak hal sebanyak mungkin. Itu sangat sangat efektif karena mengambil salah ejaan dan ejaan fonetik sama seperti kata-kata yang sebenarnya. Saya menambahkan l33tberbicara dan txtberbicara ke algoritma MetaPhone juga, menjadikannya lebih dari algoritma Triple / Quad Metaphone.

Ini menampilkan pra-prosesor yang mengompresi surat-surat yang berjalan dan mendeteksi hal-hal seperti anak-anak menempatkan hal-hal seperti w o r d sdengan secara cerdas mengompresi surat-surat dan menghilangkan duplikat yang sedang berjalan seperti wwoorrddss, itu sangat khusus untuk bahasa Inggris saja.

Itu cukup cepat 8 tahun yang lalu untuk digunakan dalam aliran sistem obrolan real-time tanpa latensi nyata dengan puluhan ribu pengguna pada sistem CPU single core.

Kami memiliki daftar kata-kata yang disandikan Metafon dalam tabel dalam database, dan itu dimuat ke dalam Peta statis yang mengejutkan kecil dan kami tidak pernah harus melakukan sesuatu yang khusus untuk mengakses daftar kata-kata yang dilarang, saya dapat menambahkan deteksi frase menggunakan teknik yang sama hampir gratis.

Tentu saja saya memiliki log yang sedang berjalan dari semua obrolan dari ribuan anak yang mencoba memecahkan sistem secara real time sehingga saya memiliki satu set data yang cukup komprehensif untuk dikerjakan. Cara saya melakukan pencatatan adalah ketika seseorang memicu filter dengan positif, saya mencatat beberapa pesan obrolan berikutnya yang tidak memicu filter dari mereka, seperti itu jika mereka menemukan jalan di sekitar kata atau frasa tertentu, saya bisa menyesuaikan sistem saya dan menangkapnya. Saya cukup bukti setelah beberapa minggu.


sumber
3
Solusi ini tampaknya yang terbaik. Masalahnya adalah (atau saat ini) bahwa saya harus menyelesaikannya dalam satu sore. Jika ada waktu yang cukup, saya akan mengambil pendekatan Double MetaPhone, atau mempekerjakan Anda untuk melakukannya. :-)
blueishgoldfish
Jadi, saya kira setengah dari orang akan berhenti memainkan permainan sekarang: D
Davor Ždralo
2

Jika Anda ingin melakukan pencocokan secara efisien, algoritma Aho Corasick adalah opsi yang cukup bagus (saya yakin Anda dapat menemukan implementasi Java yang beredar).

Tentu saja Anda mungkin ingin melakukan pra-proses pengiriman untuk mengganti penyimpangan ejaan ('$' -> 's', '@' -> 'a', '| <<->' k ', dll.)

Dmitri
sumber
Persis apa yang saya cari, terima kasih! Berikut ini adalah implementasi Java: hkn.eecs.berkeley.edu/~dyoo/java
Remi Mélisson
0

Alih-alih memuat ke String statis [], gunakan HashMap [] atau jenis pohon biner lainnya (jika Anda ingin meningkatkan pencarian) menjadikan string sebagai kunci Anda dalam hash. Pisahkan String Anda dengan spasi dan hapus tanda baca. Kemudian Anda dapat meminta HashMap untuk setiap kata dalam string split Anda; jika hashmap kembali dengan non null maka Anda tahu Anda memiliki kata yang buruk.

Hal yang gagal di sini adalah masalah Clbuttic di mana seseorang menambahkan karakter acak di sekitar kata buruk ex. bhassda

Suroot
sumber
Saya pikir peringatan terakhir adalah yang membuat solusi ini sangat tidak berguna - tidak ada cara untuk memperluasnya ke apa pun kecuali kecocokan seluruh kata.
Itu pernyataan yang adil; tetapi menjadi sulit untuk menangkap setiap hal yang mungkin muncul dalam pikiran manusia untuk menghindari filter yang tidak senonoh. Anda selalu dapat membuat ekspresi reguler yang sangat besar dengan pernyataan ATAU untuk menggabungkan semua opsi dan kemudian mencocokkan regex dengan input. ATAU Anda bisa melakukan pilih dari database dengan "bidang kata yang buruk" dari database dengan RLIKE terhadap input. Kembali menunjukkan kata yang buruk dan juga akan mengembalikan kata yang buruk.
@ Jalankan tidak sulit untuk menangkap hampir semua kata atau frasa dengan pencocokan fonetik seperti yang dibicarakan oleh pertanyaan saya. Pencocokan absolut tidak akan pernah berhasil atau skala, tetapi pencocokan fonetik bekerja hampir 100% dari waktu setelah Anda menyetel sebanyak mungkin.
-1

Menggunakan sistem phonic bukan satu-satunya solusi dengan cara apa pun, tetapi itu mungkin yang paling sederhana karena ada banyak perpustakaan open source yang melakukan hal semacam itu.

Bagian yang sulit selalu akan menjadi bagian yang cocok dari algoritma apa pun dan kedengarannya seperti pertandingan Anda sangat lambat dan naif. Anda tidak dapat mengasumsikan bahwa indexOf akan cocok dengan benar tanpa beberapa bentuk pemeriksaan tambahan.

Selain itu, Anda akan berakhir mengulang seluruh string N kali, di mana N adalah jumlah kata dalam daftar hitam Anda. Saran untuk menggunakan Set atau HashMap pasti akan sedikit memperbaiki keadaan.

Dalam kebanyakan kasus, algoritma berbasis keadaan linier adalah yang terbaik dan tercepat. Saya menulis solusi untuk Clean Speak dan menggunakan algoritme jenis ini dengan sistem pencocokan phonik pra-proses. Ini adalah satu-satunya solusi yang tidak menjadi rumit ketika kata-kata kotor tertanam (jika foo adalah kata-kata kotor, embedding adalah foosucker) dan mampu mempertahankan tingkat kinerja yang tinggi. Ini juga skala baik untuk bahasa lain tanpa implementasi codex baru.

Terakhir, pra-pemrosesan bentuk apa pun umumnya adalah sesuatu yang harus dihindari. Dalam kebanyakan kasus, Anda dapat melakukan hal yang sama dalam mode linier saat Anda menangani setiap karakter dalam string.

Tentu saja, saya sarankan melihat solusi lain dalam jangka panjang karena di sebagian besar aplikasi penanganan konten yang dibuat pengguna lebih kompleks daripada hanya penyaringan kata-kata kotor. Seringkali Anda ingin juga memfilter informasi pribadi seperti email dan nomor jaminan sosial dan kadang-kadang hal-hal seperti URL. Plus, kami telah menemukan bahwa sebagian besar aplikasi memerlukan beberapa bentuk sistem moderasi dan pencarian konten. Ini meningkatkan kompleksitas.

Brian Pontarelli
sumber
-2

Apa yang ingin Anda lakukan dalam kasus seperti ini adalah menentukan mana dari dua daftar kata yang lebih kecil. Katakanlah daftar "verboten" Anda berisi 2000 kata dan pengiriman maksimum pengguna adalah 500 kata. Dalam hal ini, Anda akan mengulangi daftar kata-kata dalam pengiriman pengguna dan mencarinya satu per satu dalam daftar kata-kata terlarang dan sebaliknya.

Perubahan lain yang akan saya buat adalah bahwa Anda tidak menyimpan daftar kata-kata terlarang dalam String [] - jika Anda mencari dalam array, Anda mendapat pencarian O (n) per kata dalam pengiriman pengguna. Itu sangat buruk. Saya akan mencoba untuk menempatkan struktur data yang Anda cari ke dalam semacam wadah asosiatif atau struktur pohon yang memiliki kinerja pencarian yang lebih baik (log n bukannya n). Tantangannya di sini adalah bahwa jika Anda memasukkan kiriman pengguna ke dalam wadah ini, Anda harus melacak posisi kata sehingga Anda dapat merekonstruksi input atau memperbarui string input jika Anda memiliki hit pencarian.

Timo Geusch
sumber