Bagaimana cara menggunakan SVD dalam pemfilteran kolaboratif?

30

Saya agak bingung dengan bagaimana SVD digunakan dalam penyaringan kolaboratif. Misalkan saya memiliki grafik sosial, dan saya membangun matriks kedekatan dari tepi, kemudian mengambil SVD (mari kita lupakan tentang regularisasi, tingkat pembelajaran, optimasi sparsity, dll), bagaimana cara menggunakan SVD ini untuk meningkatkan rekomendasi saya?

Misalkan grafik sosial saya terkait dengan instagram, dan saya ditugasi dengan tanggung jawab merekomendasikan pengguna dalam layanan ini, hanya berdasarkan grafik sosial. Saya pertama-tama akan membangun matriks kedekatan , ambil SVD, , pilih nilai eigen pertama , lalu apa? ( m × m ) A = U s V kSEBUAH (m×m)SEBUAH=UsVk

Saya mungkin akan membuat set matriks baru: lalu apa yang dilakukan?

Unewm×ksnewk×kVnewk×m

Saya telah melihat di web, dan sebagian besar tautan berfokus pada penghitungan SVD, tetapi tidak ada yang memberi tahu Anda apa yang harus dilakukan dengannya. Jadi apa yang harus aku lakukan?

Vishal
sumber
1
Ini dapat menjawab pertanyaan Anda: datasetcience.stackexchange.com/a/16523
avli

Jawaban:

7

Namun: Dengan vanilla SVD murni Anda mungkin memiliki masalah membuat ulang matriks asli, apalagi memprediksi nilai untuk item yang hilang. Aturan praktis yang berguna dalam bidang ini adalah menghitung peringkat rata-rata per film, dan mengurangi rata-rata ini untuk setiap kombinasi pengguna / film, yaitu mengurangi bias film dari setiap pengguna. Maka disarankan Anda menjalankan SVD, dan tentu saja, Anda harus mencatat nilai bias ini di suatu tempat, untuk membuat ulang peringkat, atau memprediksi nilai yang tidak diketahui. Saya telah membaca posting Simon Funk di SVD untuk rekomendasi - ia menemukan pendekatan SVD tambahan selama kompetisi Netflix.

http://sifter.org/~simon/journal/20061211.html

Saya kira merendahkan matriks A sebelum SVD masuk akal, karena PCA sepupu dekat SVD juga bekerja dengan cara yang sama. Dalam hal perhitungan inkremental, Funk mengatakan kepada saya bahwa jika Anda tidak merendahkan, arah gradien pertama mendominasi sisa perhitungan. Saya sudah melihat ini secara langsung, pada dasarnya tanpa merendahkan hal-hal tidak bekerja.

BBDynSys
sumber
24

Saya ingin menawarkan pendapat berbeda:

Tepi yang Hilang sebagai Nilai yang Hilang

Dalam masalah pemfilteran kolaboratif, koneksi yang tidak ada (pengguna belum memberi peringkat item , orang belum berteman dengan orang ) umumnya diperlakukan sebagai nilai yang hilang untuk diprediksi, bukan sebagai nol. Yaitu, jika pengguna belum memberi peringkat item , kami ingin menebak apa yang akan dia nilai jika dia memberi nilai. Jika orang belum berteman , kami ingin menebak seberapa besar kemungkinan ia ingin berteman dengannya. Rekomendasi tersebut didasarkan pada nilai-nilai yang direkonstruksi.j x y i j x ysayajxysayajxy

Ketika Anda mengambil SVD dari grafik sosial (misalnya, hubungkan melalui svd()), Anda pada dasarnya menghitung nol di semua tempat yang hilang. Bahwa ini bermasalah lebih jelas dalam pengaturan peringkat item pengguna untuk pemfilteran kolaboratif. Jika saya memiliki cara untuk mengisi entri yang hilang secara andal, saya tidak perlu menggunakan SVD sama sekali. Saya hanya akan memberikan rekomendasi berdasarkan pada entri yang diisi. Jika saya tidak memiliki cara untuk melakukan itu, maka saya tidak harus mengisinya sebelum saya melakukan SVD. *

SVD dengan Nilai yang Hilang

Tentu saja, svd()fungsi tidak tahu bagaimana cara mengatasi nilai yang hilang. Jadi, apa yang seharusnya Anda lakukan? Nah, ada cara untuk membingkai ulang masalahnya

"Temukan matriks peringkat yang paling dekat dengan matriks asli"k

Itu benar-benar masalah yang Anda coba selesaikan, dan Anda tidak akan menggunakannya svd()untuk menyelesaikannya. Cara yang bekerja untuk saya (pada data hadiah Netflix) adalah ini:

  • Cobalah menyesuaikan entri dengan model sederhana, misalnya, . Ini sebenarnya melakukan pekerjaan dengan baik.X^saya,j=μ+αsaya+βj

  • Menetapkan setiap pengguna a -vector dan setiap item a -vector . (Dalam kasus Anda, setiap orang mendapat vektor kanan dan kiri ). Anda pada akhirnya akan memprediksi residu sebagai produk titik:k u i j k v j k u i m v j msayakkamusayajkvjkkamusayamvjm

  • Gunakan beberapa algoritma untuk menemukan vektor yang meminimalkan jarak ke matriks asli. Misalnya, gunakan ini kertas

Semoga berhasil!

*: Apa yang direkomendasikan Tenali pada dasarnya adalah tetangga terdekat. Anda mencoba mencari pengguna yang serupa dan membuat rekomendasi untuk itu. Sayangnya, masalah sparsity (~ 99% dari matriks adalah nilai yang hilang) membuatnya sulit untuk menemukan tetangga terdekat menggunakan jarak cosinus atau kesamaan jaccard atau apa pun. Jadi, dia merekomendasikan untuk melakukan SVD dari matriks (dengan angka nol pada nilai yang hilang) untuk terlebih dahulu memampatkan pengguna ke ruang fitur yang lebih kecil dan kemudian melakukan perbandingan di sana. Melakukan SVD-tetangga terdekat baik-baik saja, tetapi saya masih akan merekomendasikan melakukan SVD dengan cara yang benar (maksud saya ... cara saya). Tidak perlu melakukan imputasi nilai yang tidak masuk akal!

Joe Pete yang kekar
sumber
Ini sebenarnya respon yang saya cari, dan ingin mendengar :) Terima kasih banyak!
Vishal
Anehnya pertanyaan yang diajukan "Saya telah melihat di web, dan sebagian besar tautan fokus pada menghitung SVD, tetapi tidak ada yang memberitahu Anda apa yang harus dilakukan dengannya. Jadi apa yang harus saya lakukan?" atau dalam hal ini judulnya berkata, "Bagaimana cara saya menggunakan SVD dalam pemfilteran kolaboratif?"
TenaliRaman
Yap, dan jawaban saya merangkum bagaimana saya menggunakannya dalam pemfilteran kolaboratif.
Stumpy Joe Pete
1
+1, seperti yang saya pahami, Anda tidak menghitung matriks peringkat rendah menggunakan SVD, tetapi metode berulang untuk meminimalkan kesalahan kuadrat, kan? Namun, jika saya ingin menggunakan SVD, maka saya harus mengisi entri yang hilang dengan beberapa nilai sebelum saya melakukan matriks faktorisasi, kan?
alpukat
1
svd()
14

Alasan tidak ada yang memberi tahu Anda apa yang harus dilakukan dengan itu adalah karena jika Anda tahu apa yang SVD lakukan, maka itu agak jelas apa yang harus dilakukan dengan itu :-).

Karena baris dan kolom Anda adalah himpunan yang sama, saya akan menjelaskan ini melalui matriks yang berbeda A. Biarkan matriks A sedemikian rupa sehingga baris adalah pengguna dan kolom adalah item yang disukai pengguna. Perhatikan bahwa matriks ini tidak perlu simetris, tetapi dalam kasus Anda, saya kira itu ternyata simetris. Satu cara untuk memikirkan SVD adalah sebagai berikut: SVD menemukan ruang fitur tersembunyi di mana pengguna dan item yang mereka sukai memiliki vektor fitur yang selaras.

A=U×s×VUV

Sekarang, jika saya memberi Anda dua vektor dari ruang fitur yang sama dan meminta Anda untuk menemukan apakah mereka mirip, apa hal paling sederhana yang dapat Anda pikirkan untuk mencapai itu? Produk titik.

sayajsayaUj

TenaliRaman
sumber
Dua pertanyaan: 1) Apakah Anda mengisi nilai yang hilang dengan nol (item j tidak ditinjau oleh pengguna i) sebelum menjalankan SVD? 2) Bagaimana Anda menghitung jika pengguna baru akan menyukai item j?
B_Miner
1
@ B_Miner Hai, maaf atas tanggapan yang tertunda. Jawabannya: 1) Baiklah, ya, kami biasanya mengisi nilai yang hilang dengan nol sebelum menjalankan SVD. Namun, saya biasanya menyarankan untuk mengisinya dengan peringkat bukan nol - misalnya, Anda dapat mengisi nilai yang hilang dengan peringkat rata-rata yang telah diberikan pengguna sejauh ini. 2) Pendekatan berbasis SVD hanya untuk pengguna yang diketahui dan item yang dikenal. Itu tidak dapat menangani pengguna baru atau item baru. Dan bagaimana bisa, jika pengguna baru masuk, kami tidak tahu apa-apa tentang dia dalam kerangka ini untuk diprediksi.
TenaliRaman
1
@B_Miner Jika Anda ingin bekerja dengan pengguna / item baru, kami harus berasumsi bahwa kami memiliki akses ke beberapa fitur pengguna dan fitur item. Kemudian, Anda dapat menggunakan model yang lebih canggih seperti PDLF (model Predictive Discrete Latent Factor). Ini akan memungkinkan Anda untuk menangani pengguna / item baru karena berfungsi dengan ruang fitur yang dikenal.
TenaliRaman
@TenaliRaman Tidak yakin apakah Anda akan melihat ini, tapi begini saja. Jadi saya telah menggunakan model topik (LDA) untuk membangun fitur untuk pengguna (secara harfiah pengguna) berdasarkan dokumen yang telah mereka baca. Saya hanya rata-rata vektor topik untuk mendapatkan "vektor topik pengguna". Saya ingin melakukan sesuatu yang mirip dengan SVD (atau ALS mungkin). Katakanlah saya menghitung SVD menggunakan data item-pengguna yang diketahui, dan kemudian saya memiliki pengguna baru yang "mengunjungi" beberapa item yang diketahui. Dalam hal ini vektor item diketahui tetapi vektor pengguna tidak diketahui. Bisakah saya menggunakan vektor item untuk menghitung vektor pengguna atau apakah saya perlu menghitung SVD lagi menggunakan semua data?
thecity2
jawaban bagus tenali. sangat membantu untuk memahami konsep
Nihal
3

Ini untuk mencoba dan menjawab bagian "bagaimana" dari pertanyaan bagi mereka yang ingin menerapkan rekomendasi SVD jarang atau memeriksa kode sumber untuk detailnya. Anda dapat menggunakan perangkat lunak FOSS yang tidak tersedia untuk memodelkan sparse-SVD. Sebagai contoh, vowpal wabbit, libFM, atau redsvd.

vowpal wabbitmemiliki 3 implementasi algoritma "mirip SVD" (masing-masing dapat dipilih oleh salah satu dari 3 opsi baris perintah). Sebenarnya ini harus disebut "perkiraan, iteratif, faktorisasi matriks" daripada SVD "klasik" murni tetapi mereka terkait erat dengan SVD. Anda mungkin menganggapnya sebagai faktorisasi SVD perkiraan yang sangat efisien secara komputasional dari faktor jarang (kebanyakan nol) matriks.

Inilah resep lengkap dan bekerja untuk melakukan rekomendasi film gaya Netflix dengan vowpal wabbitdan --lrqopsi "kuadrat rendah" ( ) yang tampaknya bekerja paling baik untuk saya:

File format kumpulan data ratings.vw(setiap peringkat pada satu baris menurut pengguna dan film):

5 |user 1 |movie 37
3 |user 2 |movie 1019
4 |user 1 |movie 25
1 |user 3 |movie 238
...

Di mana nomor 1 adalah peringkat (1 hingga 5 bintang) diikuti oleh ID pengguna yang memberi peringkat dan dan ID film yang diberi peringkat.

Data uji dalam format yang sama tetapi dapat (secara opsional) menghilangkan kolom peringkat:

 |user 1 |movie 234
 |user 12 |movie 1019
...

opsional karena untuk mengevaluasi / menguji prediksi kita perlu peringkat untuk membandingkan prediksi. Jika kami mengabaikan peringkat, vowpal wabbitmasih akan memperkirakan peringkat tetapi tidak akan dapat memperkirakan kesalahan prediksi (nilai prediksi vs nilai aktual dalam data).

Untuk melatih, kami meminta vowpal wabbituntuk menemukan serangkaian Nfaktor interaksi laten antara pengguna dan film yang mereka sukai (atau tidak suka). Anda dapat berpikir tentang hal ini sebagai menemukan tema umum di mana pengguna yang sama memberi peringkat subset film dengan cara yang sama dan menggunakan tema umum ini untuk memprediksi bagaimana pengguna akan menilai film yang belum diperingkatnya.

vw opsi dan argumen yang perlu kita gunakan:

  • --lrq <x><y><N> menemukan faktor laten "peringkat rendah".
  • <x><y>: "um" berarti menyeberangi u [sers] dan m [ovie] ruang-nama dalam kumpulan data. Perhatikan bahwa hanya huruf 1 di setiap ruang nama yang digunakan dengan --lrqopsi.
  • <N>: di N=14bawah ini adalah jumlah faktor laten yang ingin kita temukan
  • -f model_filename: tulis model akhir menjadi model_filename

Jadi perintah pelatihan penuh sederhana adalah:

    vw --lrq um14 -d ratings.vw -f ratings.model

Setelah kami memiliki ratings.modelfile model, kami dapat menggunakannya untuk memprediksi peringkat tambahan pada set data baru more_ratings.vw:

    vw -i ratings.model -d more_ratings.vw -p more_ratings.predicted

Prediksi akan ditulis ke file more_ratings.predicted.

Menggunakan demo/movielensdi vowpalwabbitpohon sumber, saya mendapatkan ~ 0,693 MAE (Mean Absolute Error) setelah pelatihan pada 1 juta pengguna / film peringkat ml-1m.ratings.train.vwdengan 14 faktor laten (berarti bahwa matriks tengah SVD adalah 14x14 baris x kolom matriks) dan pengujian pada independen set-tes ml-1m.ratings.test.vw. Seberapa baik 0,69 MAE? Untuk rentang penuh dari kemungkinan prediksi, termasuk case (0) [0 hingga 5] tanpa kesalahan, kesalahan 0,69 adalah ~ 13,8% (0,69 / 5.0) dari kisaran penuh, yaitu sekitar akurasi 86,2% (1 - 0,138).

Anda dapat menemukan contoh dan demo lengkap untuk kumpulan data yang serupa (movielens) dengan dokumentasi di vowpal wabbitpohon sumber di github:

Catatan:

  • The movielensdemo menggunakan beberapa pilihan saya dihilangkan (untuk kesederhanaan) dari contoh saya: khususnya --loss_function quantile, --adaptivedan--invariant
  • The --lrqimplementasi dalam vwjauh lebih cepat daripada --rank, khususnya ketika menyimpan dan memuat model.

Kredit:

  • --rank Opsi vw diimplementasikan oleh Jake Hofman
  • --lrq Opsi vw (dengan dropout opsional) diterapkan oleh Paul Minero
  • vowpal wabbit (alias vw) adalah anak otak John Langford
diri sendiri
sumber
1

Saya akan mengatakan bahwa nama SVDitu menyesatkan. Bahkan, SVDmetode dalam sistem rekomendasi tidak secara langsung menggunakan faktorisasi SVD. Sebaliknya, ia menggunakan keturunan gradien stokastik untuk melatih bias dan vektor faktor.

Rincian SVDdan SVD++algoritme untuk sistem rekomendasi dapat ditemukan di Bagian 5.3.1dan 5.3.2buku ini Francesco Ricci, Lior Rokach, Bracha Shapira, and Paul B. Kantor. Recommender Systems Handbook. 1st edition, 2010.

Dalam Python, ada paket mapan mengimplementasikan algoritma yang dinamai ini surprise. Dalam dokumentasinya , mereka juga menyebutkan rincian dari algoritma ini.

lenhhoxung
sumber