Come si usa SVD nel filtro collaborativo?


30

Sono un po 'confuso da come viene utilizzato SVD nel filtro collaborativo. Supponiamo di avere un grafico sociale e di costruire una matrice di adiacenza dai bordi, quindi prendere un SVD (dimentichiamoci di regolarizzazione, tassi di apprendimento, ottimizzazioni di sparsità, ecc.), Come posso usare questo SVD per migliorare i miei consigli?

Supponiamo che il mio grafico sociale corrisponda a Instagram, e mi è stato assegnato il compito di consigliare gli utenti nel servizio, basato solo sul grafico sociale. Vorrei prima costruire una matrice di adiacenza A (m×m) , prendere SVD, , scegliere i primi autovalori, quindi cosa?A=UsVk

Presumibilmente creerei un nuovo set di matrici: quindi cosa si fa?

Unewm×ksnewk×kVnewk×m

Ho guardato sul web e la maggior parte dei link si concentra sul calcolo dell'SVD, ma nessuno ti dice cosa farne. Quindi cosa dovrei fare?


1
Questo potrebbe rispondere alla tua domanda: datascience.stackexchange.com/a/16523
avli

Risposte:


7

Tuttavia: con SVD puro alla vaniglia potresti avere problemi a ricreare la matrice originale, e tanto meno prevedere i valori per gli elementi mancanti. L'utile regola empirica in quest'area è il calcolo della valutazione media per film e la sottrazione di questa media per ogni combinazione utente / film, ovvero sottraendo la distorsione del film da ciascun utente. Quindi si consiglia di eseguire SVD e, naturalmente, è necessario registrare questi valori di errore in qualche luogo, al fine di ricreare le valutazioni o prevedere valori sconosciuti. Avevo letto il consiglio di Simon Funk su SVD per consigli: ha inventato un approccio SVD incrementale durante la competizione Netflix.

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

Immagino che la matrice umiliante A prima di SVD abbia un senso, dal momento che anche il cugino stretto SVA PCA funziona in modo simile. In termini di calcolo incrementale, Funk mi ha detto che se non si sminuisce, la prima direzione del gradiente domina il resto del calcolo. L'ho visto in prima persona, praticamente senza cose umilianti non funzionano.


24

Vorrei offrire un parere dissenziente:

Bordi mancanti come valori mancanti

In un problema di filtro collaborativo, le connessioni che non esistono (l'utente non ha valutato l'elemento j , la persona x non ha una persona amica y ) sono generalmente trattate come valori mancanti da prevedere, anziché come zeri. Cioè, se l'utente che non ha valutato elemento j , vogliamo immaginare cosa potrebbe votarla se lui avesse valutato positivamente. Se persona x non è friended y , vogliamo immaginare quanto è probabile che avrebbe voluto ad un amico di lui. Le raccomandazioni si basano sui valori ricostruiti.ijxyijxy

Quando prendi l'SVD del grafico sociale (ad esempio, collegalo svd()), fondamentalmente stai imputando zeri in tutti quei punti mancanti. Che ciò sia problematico è più evidente nell'impostazione della classificazione degli articoli dell'utente per il filtro collaborativo. Se avessi un modo per compilare in modo affidabile le voci mancanti, non avrei bisogno di usare SVD. Darei solo consigli basati sulle voci compilate. Se non ho un modo per farlo, non dovrei riempirli prima di fare SVD. *

SVD con valori mancanti

Naturalmente, la svd()funzione non sa come affrontare i valori mancanti. Quindi, cosa dovresti fare esattamente? Bene, c'è un modo per riformulare il problema come

"Trova la matrice di rango che è più vicina alla matrice originale"k

Questo è davvero il problema che stai cercando di risolvere, e non hai intenzione di usarlo svd()per risolverlo. Un modo che ha funzionato per me (sui dati del premio Netflix) è stato questo:

  • Prova a trovare le voci con un modello semplice, ad . Questo in realtà fa un buon lavoro.X^i,j=μ+αi+βj

  • Assegnare ad ogni utente un k -vettore u i e ciascun elemento j un k -vettore v j . (Nel tuo caso, ogni persona ottiene un k -vettore destro e sinistro ). Alla fine pronuncerai i residui come prodotti a punti: u i m v j mikuijkvjkuimvjm

  • Usa alcuni algoritmi per trovare i vettori che minimizzano la distanza dalla matrice originale. Ad esempio, usa questo documento

Buona fortuna!

*: Ciò che Tenali sta raccomandando sono sostanzialmente i vicini più vicini. Cerchi di trovare utenti simili e fornisci consigli in merito. Sfortunatamente, il problema della sparsità (~ 99% della matrice manca di valori) rende difficile trovare i vicini più vicini usando la distanza del coseno o la somiglianza del jaccard o altro. Quindi, sta raccomandando di fare un SVD della matrice (con zeri imputati ai valori mancanti) per comprimere prima gli utenti in uno spazio di funzionalità più piccolo e quindi fare confronti lì. Fare SVD-vicini più vicini va bene, ma consiglierei comunque di fare SVD nel modo giusto (intendo ... a modo mio). Non è necessario eseguire un'imputazione di valore senza senso!


Questa è stata la risposta che stavo cercando e che volevo sentire :) Grazie mille!
Vishal,

Stranamente la domanda si è posta "Ho cercato sul web e la maggior parte dei link si concentra sul calcolo dell'SVD, ma nessuno ti dice cosa farne. Quindi cosa dovrei fare?" o del resto il titolo dice "Come si usa SVD nel filtro collaborativo?"
TenaliRaman

Sì, e la mia risposta ha riassunto come la uso nel filtro collaborativo.
Stumpy Joe Pete,

1
+1, a quanto ho capito, non stai calcolando la matrice di basso rango usando SVD, ma un metodo iterativo per minimizzare l'errore al quadrato, giusto? Tuttavia, se voglio usare SVD, allora dovrei riempire le voci mancanti con alcuni valori prima di fare la fattorizzazione a matrice, giusto?
avocado,

1
svd()

14

Il motivo per cui nessuno ti dice cosa farne è perché se sai cosa fa SVD, allora è un po 'ovvio cosa farne :-).

Dal momento che le tue righe e colonne sono lo stesso set, lo spiegherò attraverso una matrice diversa A. Lascia che la matrice A sia tale che le righe siano gli utenti e le colonne siano gli elementi che piacciono all'utente. Nota che questa matrice non deve essere simmetrica, ma nel tuo caso, credo che sia simmetrica. Un modo di pensare a SVD è il seguente: SVD trova uno spazio di funzionalità nascosto in cui gli utenti e gli oggetti che preferiscono hanno vettori di funzionalità strettamente allineati.

A=U×s×VUV

Ora, se ti do due vettori dallo stesso spazio delle caratteristiche e ti chiedo di scoprire se sono simili, qual è la cosa più semplice a cui puoi pensare per realizzarlo? Prodotto Dot.

ijiUj


Due domande: 1) Riempi i valori mancanti con zero (elemento j non esaminato dall'utente i) prima di eseguire SVD? 2) Come si calcola se a un nuovo utente piacerà l'articolo j?
B_Miner,

1
@B_Miner Ciao, scusa per la risposta ritardata. Le risposte: 1) Bene, sì, di solito riempiamo i valori mancanti con zero prima di eseguire SVD. Tuttavia, di solito consiglio di riempirlo con un punteggio diverso da zero - ad esempio, puoi riempire i valori mancanti con il punteggio medio che l'utente ha dato finora. 2) L'approccio basato su SVD è solo per utenti noti e oggetti noti. Non può gestire nuovi utenti o nuovi elementi. E come può, se arriva un nuovo utente, non sappiamo nulla di lui in questo framework da prevedere.
TenaliRaman,

1
@B_Miner Se vuoi lavorare con nuovi utenti / articoli, dobbiamo presumere che abbiamo accesso ad alcune funzionalità utente e funzionalità articolo. Quindi, è possibile utilizzare un modello più sofisticato come PDLF (modello predittivo di fattore latente discreto). Ciò ti consentirà di gestire nuovi utenti / elementi perché funziona con uno spazio di funzionalità noto.
TenaliRaman

@TenaliRaman Non sono sicuro che vedrai questo, ma qui va. Quindi ho usato i modelli di argomenti (LDA) per creare funzionalità per gli utenti (letteralmente utenti) in base ai documenti che hanno letto. Ho appena fatto una media dei vettori di argomenti per ottenere un "vettore di argomenti utente". Voglio fare qualcosa di simile con SVD (o eventualmente ALS). Supponiamo che io calcoli SVD utilizzando dati di elementi utente noti e quindi ho nuovi utenti che "visitano" diversi elementi noti. In questo caso i vettori oggetto sono noti ma i vettori utente sono sconosciuti. Posso utilizzare i vettori oggetto per calcolare il vettore utente o devo calcolare nuovamente SVD usando tutti i dati?
thecity2

ottima risposta tenali. molto utile per comprendere il concetto
Nihal

3

Questo per cercare di rispondere alla parte "come" della domanda per coloro che vogliono implementare praticamente raccomandazioni sparse-SVD o ispezionare il codice sorgente per i dettagli. È possibile utilizzare un software FOSS standard per modellare SVD sparse. Ad esempio, vowpal wabbit, libFM, o redsvd.

vowpal wabbitha 3 implementazioni di algoritmi "simili a SVD" (ciascuno selezionabile da una delle 3 opzioni della riga di comando). A rigor di termini, questi dovrebbero essere chiamati "fattorizzazione approssimativa, iterativa, matriciale" piuttosto che pura "classica" SVD ", ma sono strettamente correlati alla SVD. Potresti considerarli come una fattorizzazione SVD approssimativa molto efficiente dal punto di vista computazionale di uno scarso (principalmente zero) matrice.

Ecco una ricetta completa e funzionante per fare consigli sui film in stile Netflix con vowpal wabbite la sua --lrqopzione "quadratica di basso livello" ( ) che sembra funzionare meglio per me:

File di formato del set di dati ratings.vw(ogni valutazione su una riga per utente e film):

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

Dove il 1 ° numero è la valutazione (da 1 a 5 stelle) seguita dall'ID dell'utente che ha valutato e dall'ID del film che è stato valutato.

I dati di test sono nello stesso formato ma possono (facoltativamente) omettere la colonna delle classifiche:

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

facoltativamente perché per valutare / testare le previsioni abbiamo bisogno di valutazioni per confrontare le previsioni. Se omettiamo le valutazioni, vowpal wabbitcontinueremo a prevedere le valutazioni ma non saremo in grado di stimare l'errore di previsione (valori previsti rispetto ai valori effettivi nei dati).

Per allenarci chiediamo vowpal wabbitdi trovare una serie di Nfattori di interazione latenti tra utenti e film che gli piacciono (o che non amano). Potresti pensare a questo come trovare temi comuni in cui utenti simili valutano un sottoinsieme di film in modo simile e utilizzare questi temi comuni per prevedere come un utente classificherebbe un film che non ha ancora valutato.

vw opzioni e argomenti che dobbiamo usare:

  • --lrq <x><y><N> trova fattori latenti "quadratici di basso rango".
  • <x><y>: "um" significa attraversare gli spazi dei nomi u [sers] e m [ovie] nel set di dati. Si noti che solo l' --lrqopzione 1a in ogni spazio dei nomi viene utilizzata con l' opzione.
  • <N>: N=14sotto è il numero di fattori latenti che vogliamo trovare
  • -f model_filename: scrivi il modello finale in model_filename

Quindi un semplice comando di allenamento completo sarebbe:

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

Una volta che abbiamo il ratings.modelfile modello, possiamo usarlo per prevedere valutazioni aggiuntive su un nuovo set di dati more_ratings.vw:

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

Le previsioni verranno scritte nel file more_ratings.predicted.

Usando demo/movielensnella struttura dei vowpalwabbitsorgenti, ottengo ~ 0,693 MAE (Mean Absolute Error) dopo l'allenamento su 1 milione di valutazioni utente / film ml-1m.ratings.train.vwcon 14 fattori latenti (il che significa che la matrice media SVD è una matrice 14x14 righe x colonne) e test sull'indipendente set di test ml-1m.ratings.test.vw. Quanto è buono 0.69 MAE? Per l'intera gamma di possibili previsioni, incluso il caso non classificato (0) [da 0 a 5], un errore dello 0,69 è ~ 13,8% (0,69 / 5,0) dell'intero intervallo, ovvero circa l'86,2% di precisione (1 - 0,138).

Puoi trovare esempi e una demo completa per un set di dati simile (movielens) con documentazione nella struttura dei vowpal wabbitsorgenti su github:

Gli appunti:

  • La movielensdemo utilizza diverse opzioni ho omesso (per semplicità) dal mio esempio: in particolare --loss_function quantile, --adaptivee--invariant
  • L' --lrqimplementazione vwè molto più rapida di --rank, in particolare durante l'archiviazione e il caricamento dei modelli.

Crediti:

  • --rank l'opzione vw è stata implementata da Jake Hofman
  • --lrq l'opzione vw (con dropout opzionale) è stata implementata da Paul Minero
  • vowpal wabbit (aka vw) è il figlio del cervello di John Langford

1

Direi che il nome SVDè fuorviante. In effetti, il SVDmetodo nel sistema di raccomandazione non utilizza direttamente la fattorizzazione SVD. Invece, usa la pendenza stocastica del gradiente per addestrare i pregiudizi e i vettori dei fattori.

I dettagli degli algoritmi SVDe del SVD++sistema di raccomandazione sono disponibili nelle sezioni 5.3.1e 5.3.2nel libro Francesco Ricci, Lior Rokach, Bracha Shapira, and Paul B. Kantor. Recommender Systems Handbook. 1st edition, 2010.

In Python, esiste un pacchetto consolidato che implementa questi algoritmi denominati surprise. Nella sua documentazione , menzionano anche i dettagli di questi algoritmi.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.