Spark ALS: recommander aux nouveaux utilisateurs

10

La question

Comment prédire la note d'un nouvel utilisateur dans un modèle ALS formé à Spark? (Nouveau = pas vu pendant le temps de formation)

Le problème

Je suis le tutoriel officiel de Spark ALS ici:

http://ampcamp.berkeley.edu/big-data-mini-course/movie-recommendation-with-mllib.html

Je suis en mesure de construire un bon recommandeur avec un MSE décent, mais je me bats avec la façon d'entrer de nouvelles données dans le modèle. Le tutoriel modifie les notes du premier utilisateur avant la formation, mais c'est vraiment un hack. Ils donnent l'indice suivant:

9.2. Augmenter les facteurs matriciels:

Dans ce didacticiel, nous ajoutons vos notes à l'ensemble de formation. Une meilleure façon d'obtenir les recommandations pour vous consiste d'abord à former un modèle de factorisation matricielle, puis à augmenter le modèle à l'aide de vos notes. Si cela vous semble intéressant, vous pouvez jeter un œil à la mise en œuvre de MatrixFactorizationModel et voir comment mettre à jour le modèle pour les nouveaux utilisateurs et les nouveaux films.

L'implémentation ne m'aide pas du tout. Idéalement, je recherche quelque chose comme:

predictions = model.predictAllNew(newinput)

Mais une telle méthode n'existe pas. Je pourrais aller modifier le RDD d'origine, mais je pense que cela me demanderait de recycler le modèle, ce ne serait donc pas une solution idéale non plus. Il doit sûrement y avoir une manière plus élégante?

Où je suis en ce moment:

Je pense que je dois trouver la représentation latente du nouveau vecteur. Selon l' article original, nous pouvons calculer cela comme suit:

Xu=(YTCuY+λI)1YTCup(u)

Cu

Ma tentative actuelle:

V = model.productFeatures().map(lambda x: (x[1])).collect() #product latent matrix Y

Cui =  alpha * np.abs(newinput)
Cui =  (1. + Cui) / (Cui)
Cui[np.where(newinput == 0)] = 0
Cui = np.diag(Cui)

lambdaI = len(np.where(newinput!=0)) * regularization_parameter * np.eye(np.shape(V)[1]) #
term   = np.dot(np.dot(Vt,Cui),V)+lambdaI
term   = np.dot(np.linalg.inv(term),Vt)
term   = np.dot(term,Cui)
term   = np.dot(term,newinput)
latentinput = term

Mais cela ne correspond pas.

ciri
la source

Réponses:

9

Beaucoup de questions ici. Tout d'abord, pour un utilisateur vraiment nouveau sans données, il n'y a aucun moyen d'utiliser un modèle de recommandation. Si vous n'avez littéralement aucune information sur l'utilisateur, la seule chose que vous pouvez faire est de fournir des recommandations par défaut.

Bien sûr, une fois que vous avez des données et que vous pouvez reconstruire le modèle pour incorporer l'utilisateur, vous pouvez faire des recommandations. Vous pouvez le faire dans Spark mais vous le savez déjà. Cela prendra trop de temps si vous devez ajouter des informations sur les nouveaux utilisateurs lors de l'exécution. La technique que vous souhaitez est appelée "repli", utilisée pour comprendre ce qu'est le nouveau vecteur utilisateur (approximativement) compte tenu des éléments avec lesquels l'utilisateur interagit. Ce n'est qu'une algèbre linéaire et découle de l'équation que vous donnez.

J'ai creusé une vieille diapositive qui pourrait aider:

Repliable ALS

Le "Cu" n'est pas vraiment différent. J'ai ajouté une «extension» pour gérer le cas d'une entrée négative, mais c'est la même chose pour une entrée positive.

Voici une implémentation du repli, bien que je pense que ça va être trop dense pour avoir beaucoup de valeur:

https://github.com/OryxProject/oryx/blob/2c01d496f93f2825a076eb7fe492aa39a5290aa6/app/oryx-app-common/src/main/java/com/cloudera/oryx/app/als/ALSUtils.java#L74

Le calcul du nouveau vecteur utilisateur impliqué par une interaction utilisateur-élément est une algèbre linéaire assez facile. La partie la plus délicate que j'ai trouvée est de décider du poids à lui accorder.

J'espère que c'est un pas dans la bonne direction.

Sean Owen
la source