Como uso o SVD na filtragem colaborativa?

30

Estou um pouco confuso com o modo como o SVD é usado na filtragem colaborativa. Suponha que eu tenha um gráfico social e construa uma matriz de adjacência a partir das bordas e faça um SVD (vamos esquecer a regularização, as taxas de aprendizado, as otimizações de escassez etc.), como uso esse SVD para melhorar minhas recomendações?

Suponha que meu gráfico social corresponda ao instagram e fui encarregado de recomendar usuários no serviço, com base apenas no gráfico social. Primeiro, eu construí uma matriz de adjacência , pega o SVD, , escolhe os primeiros autovalores, e daí?UMA (m×m)UMA=vocêsVk

Presumivelmente, eu criaria um novo conjunto de matrizes: então o que se faz?

vocêneWm×ksneWk×kVneWk×m

Eu olhei na Web, e a maioria dos links se concentra no cálculo do SVD, mas ninguém lhe diz o que fazer com ele. Então, o que eu deveria fazer?

Vishal
fonte
1
Isso pode responder à sua pergunta: datascience.stackexchange.com/a/16523
avli

Respostas:

7

No entanto: com SVD puro de baunilha, você pode ter problemas para recriar a matriz original, e muito menos prever valores para itens ausentes. A regra prática nesta área é calcular a classificação média por filme e subtrair essa média para cada combinação de usuário / filme, ou seja, subtrair o viés do filme de cada usuário. Em seguida, é recomendável que você executar SVD, e, claro, você teria que gravar esses valores viés em algum lugar, a fim de classificações de recriar ou prever para valores desconhecidos. Eu li o post de Simon Funk no SVD para recomendações - ele inventou uma abordagem incremental de SVD durante a competição da Netflix.

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

Eu acho que a matriz degradante A antes do SVD faz sentido, já que o primo próximo do SVD, PCA, também funciona de maneira semelhante. Em termos de computação incremental, Funk me disse que, se você não rebaixar, a primeira direção do gradiente domina o restante da computação. Eu já vi isso em primeira mão, basicamente sem coisas humilhantes não funcionam.

BBDynSys
fonte
24

Eu gostaria de oferecer uma opinião divergente:

Bordas ausentes como valores ausentes

Em um problema de filtragem colaborativa, as conexões que não existem (o usuário não avaliou o item , a pessoa não fez amizade com a pessoa ) geralmente são tratadas como valores ausentes a serem previstos, e não como zeros. Ou seja, se o usuário não avaliado item de , queremos adivinhar o que ele pode avaliá-lo se ele tinha classificado como ele. Se pessoa não friended , queremos adivinhar como provável é que ele quer para um amigo dele. As recomendações são baseadas nos valores reconstruídos.j x y i j x yijxyEujxy

Quando você pega o SVD do gráfico social (por exemplo, conecte-o svd()), basicamente está imputando zeros em todos os pontos ausentes. Que isso é problemático é mais óbvio na configuração de classificação de itens do usuário para filtragem colaborativa. Se eu tivesse uma maneira de preencher com segurança as entradas ausentes, não precisaria usar o SVD. Eu apenas daria recomendações com base nas entradas preenchidas. Se eu não tiver uma maneira de fazer isso, não os preencherei antes de fazer o SVD. *

SVD com valores ausentes

Obviamente, a svd()função não sabe lidar com valores ausentes. Então, o que exatamente você deveria fazer? Bem, há uma maneira de reformular o problema como

"Encontre a matriz da posição mais próxima da matriz original"k

Esse é realmente o problema que você está tentando resolver e não vai usar svd()para resolvê-lo. Uma maneira que funcionou para mim (nos dados do prêmio Netflix) foi:

  • Tentar encaixar as entradas com um modelo simples, por . Isso realmente faz um bom trabalho.X^Eu,j=μ+αEu+βj

  • EukvocêEujkvjkvocêEumvjm

  • Use algum algoritmo para encontrar os vetores que minimizam a distância da matriz original. Por exemplo, use este documento

Boa sorte!

*: O que Tenali está recomendando são basicamente os vizinhos mais próximos. Você tenta encontrar usuários semelhantes e faz recomendações sobre isso. Infelizmente, o problema da escarsidade (~ 99% da matriz está faltando valores) dificulta a localização de vizinhos mais próximos usando distância de cosseno ou similaridade de jaccard ou qualquer outra coisa. Portanto, ele recomenda fazer um SVD da matriz (com zeros imputados nos valores ausentes) para compactar primeiro os usuários em um espaço menor de recursos e, em seguida, fazer comparações lá. Fazer SVD com os vizinhos mais próximos é bom, mas eu ainda recomendaria fazer o SVD da maneira certa (quero dizer ... do meu jeito). Não há necessidade de imputar valores sem sentido!

Stumpy Joe Pete
fonte
Esta foi realmente a resposta que eu estava procurando e queria ouvir :) Muito obrigado!
Vishal
Estranhamente, a pergunta "eu procurei na web e a maioria dos links se concentra no cálculo do SVD, mas ninguém lhe diz o que fazer com ele. Então, o que devo fazer?" ou, nesse caso, o título diz: "Como uso o SVD na filtragem colaborativa?"
TenaliRaman
Sim, e minha resposta resumiu como eu o uso na filtragem colaborativa.
Stumpy Joe Pete
1
+1, pelo que entendi, você não calcula a matriz de baixa classificação usando SVD, mas um método iterativo para minimizar o erro ao quadrado, certo? No entanto, se eu quiser usar SVD, devo preencher as entradas ausentes com alguns valores antes de fazer a fatoração da matriz, certo?
Avocado
1
svd()
14

A razão pela qual ninguém lhe diz o que fazer com isso é porque, se você sabe o que o SVD faz, é um pouco óbvio o que fazer com ele :-).

Como suas linhas e colunas são o mesmo conjunto, explicarei isso por meio de uma matriz diferente A. Permita que a matriz A seja tal que as linhas sejam os usuários e as colunas sejam os itens de que o usuário gosta. Observe que essa matriz não precisa ser simétrica, mas no seu caso, acho que acaba sendo simétrica. Uma maneira de pensar em SVD é a seguinte: O SVD encontra um espaço de recurso oculto onde os usuários e itens de que eles gostam têm vetores de recursos que estão alinhados.

UMA=você×s×VvocêV

Agora, se eu der dois vetores do mesmo espaço de recurso e pedir para você descobrir se eles são semelhantes, qual é a coisa mais simples que você pode pensar para fazer isso? Produto de ponto.

EujEuvocêj

TenaliRaman
fonte
Duas perguntas: 1) Você preenche os valores ausentes com zero (item j não revisado pelo usuário i) antes de executar o SVD? 2) Como você calcula se um novo usuário gosta do item j?
B_Miner
1
@B_Miner Olá, desculpe pela resposta atrasada. As respostas: 1) Bem, sim, normalmente preenchemos os valores ausentes com zero antes de executar o SVD. No entanto, eu geralmente recomendo preenchê-lo com uma classificação diferente de zero - por exemplo, você pode preencher os valores ausentes pela classificação média que o usuário forneceu até o momento. 2) A abordagem baseada em SVD é apenas para usuários conhecidos e itens conhecidos. Ele não pode lidar com novos usuários ou novos itens. E como pode, se um novo usuário entrar, não sabemos nada sobre ele nessa estrutura para prever.
precisa saber é o seguinte
1
@B_Miner Se você deseja trabalhar com novos usuários / itens, devemos assumir que temos acesso a alguns recursos do usuário e de itens. Em seguida, você pode usar um modelo mais sofisticado como PDLF (modelo de fator latente discreto preditivo). Isso permitirá que você lide com novos usuários / itens porque funciona com um espaço de recurso conhecido.
precisa saber é o seguinte
@TenaliRaman Não tenho certeza se você verá isso, mas aqui vai. Então, eu tenho usado modelos de tópicos (LDA) para criar recursos para usuários (literalmente usuários) com base nos documentos que eles leram. Eu apenas calculo a média dos vetores de tópicos para obter um "vetor de tópico do usuário". Eu quero fazer algo semelhante com SVD (ou ALS possivelmente). Digamos que eu calcule o SVD usando dados conhecidos de itens do usuário e, em seguida, tenho novos usuários que "visitam" vários itens conhecidos. Nesse caso, os vetores de itens são conhecidos, mas os vetores de usuário são desconhecidos. Posso usar os vetores de itens para calcular o vetor de usuário ou preciso calcular o SVD novamente usando todos os dados?
thecity2
ótima resposta tenali. muito útil para a compreensão do conceito
Nihal
3

Isso é para tentar responder à parte "como fazer" da pergunta para quem deseja implementar praticamente recomendações de SVD esparsas ou inspecionar o código-fonte para obter detalhes. Você pode usar um software FOSS pronto para uso para modelar SVD esparso. Por exemplo, vowpal wabbit, libFM, ou redsvd.

vowpal wabbitpossui 3 implementações de algoritmos "do tipo SVD" (cada uma selecionável por uma das 3 opções de linha de comando). Estritamente falando, eles devem ser chamados de "fatoração matricial aproximada, iterativa", em vez de puro "SVD" clássico, mas estão intimamente relacionados ao SVD.Você pode pensar neles como uma fatoração SVD aproximada muito computacionalmente eficiente de uma dispersão (principalmente zeros) matriz.

Aqui está uma receita completa e prática para fazer recomendações de filmes no estilo Netflix com vowpal wabbite sua --lrqopção "quadrática de classificação baixa" ( ) que parece funcionar melhor para mim:

Arquivo de formato do conjunto de dados ratings.vw(cada classificação em uma linha por usuário e filme):

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

Onde o 1º número é a classificação (de 1 a 5 estrelas), seguida pelo ID do usuário que avaliou e o ID do filme que foi classificado.

Os dados de teste estão no mesmo formato, mas podem (opcionalmente) omitir a coluna de classificações:

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

opcionalmente porque para avaliar / testar previsões precisamos de classificações para comparar as previsões. Se omitirmos as classificações, vowpal wabbitainda assim as preveremos, mas não será possível estimar o erro de previsão (valores previstos x valores reais nos dados).

Para treinar, solicitamos vowpal wabbitencontrar um conjunto de Nfatores de interação latente entre usuários e filmes de que eles gostam (ou não). Você pode pensar nisso como encontrar temas comuns em que usuários semelhantes classificam um subconjunto de filmes de maneira semelhante e usar esses temas comuns para prever como um usuário classificaria um filme que ainda não classificou.

vw opções e argumentos que precisamos usar:

  • --lrq <x><y><N> encontra fatores latentes "quadráticos de classificação baixa".
  • <x><y>: "um" significa cruzar os espaços de nomes dos [es] e dos [ovi] no conjunto de dados. Observe que apenas a 1ª letra em cada espaço de nome é usada com a --lrqopção
  • <N>: N=14abaixo está o número de fatores latentes que queremos encontrar
  • -f model_filename: escreva o modelo final em model_filename

Portanto, um simples comando de treinamento completo seria:

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

Depois de termos o ratings.modelarquivo de modelo, podemos usá-lo para prever classificações adicionais em um novo conjunto de dados more_ratings.vw:

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

As previsões serão gravadas no arquivo more_ratings.predicted.

Usando demo/movielensa vowpalwabbitárvore de origem, recebo ~ 0,693 MAE (erro absoluto médio) após o treinamento em 1 milhão de classificações de usuário / filme ml-1m.ratings.train.vwcom 14 fatores latentes (o que significa que a matriz do meio SVD é uma matriz de 14 x 14 linhas x colunas) e teste no independente conjunto de teste ml-1m.ratings.test.vw. Quão bom é 0,69 MAE? Para o intervalo completo de previsões possíveis, incluindo o caso não classificado (0) [0 a 5], um erro de 0,69 é de ~ 13,8% (0,69 / 5,0) do intervalo completo, ou seja, cerca de 86,2% de precisão (1 - 0,138).

Você pode encontrar exemplos e uma demonstração completa de um conjunto de dados semelhante (movielens) com documentação na vowpal wabbitárvore de fontes no github:

Notas:

  • A movielensdemonstração usa várias opções I omitido (para simplificar) do meu exemplo: em particular --loss_function quantile, --adaptivee--invariant
  • A --lrqimplementação vwé muito mais rápida do que --rank, em particular, ao armazenar e carregar os modelos.

Créditos:

  • --rank opção vw foi implementada por Jake Hofman
  • --lrq A opção vw (com abandono opcional) foi implementada por Paul Minero
  • vowpal wabbit (aka vw) é o filho cerebral de John Langford
arielf
fonte
1

Eu diria que o nome SVDé enganador. De fato, o SVDmétodo no sistema de recomendação não usa diretamente a fatoração SVD. Em vez disso, ele usa descida de gradiente estocástico para treinar os vieses e vetores de fatores.

Os detalhes SVDe os SVD++algoritmos do sistema de recomendação podem ser encontrados nas Seções 5.3.1e 5.3.2no livro Francesco Ricci, Lior Rokach, Bracha Shapira, and Paul B. Kantor. Recommender Systems Handbook. 1st edition, 2010.

No Python, há um pacote bem estabelecido implementado por esses algoritmos nomeados surprise. Na documentação , eles também mencionam os detalhes desses algoritmos.

lenhhoxung
fonte