Systèmes de recommandation : Filtrage collaboratif basé sur l’utilisateur utilisant les N plus proches voisins

Ashay Pathak
Ashay Pathak

Follow

Feb 25, 2019 – 9 min lu

Ashay Pathak, Chatana Mandava, Ritesh Patel

Le filtrage collaboratif est une technique largement utilisée dans les systèmes de recommandation et un domaine de recherche qui progresse rapidement. Les deux méthodes les plus couramment utilisées sont celles basées sur la mémoire et celles basées sur le modèle.

Dans ce post, nous nous concentrerons uniquement sur (User-Based Collaborative Filtering) UB-CF qui est une méthode basée sur la mémoire. L’idée principale derrière UB-CF est que les personnes ayant des caractéristiques similaires partagent des goûts similaires. Par exemple, si l’on souhaite recommander un film à notre ami Bob, supposons que Bob et moi avons vu de nombreux films ensemble et que nous les avons notés de manière presque identique. Il est logique de penser qu’à l’avenir aussi nous continuerions à aimer des films similaires et à utiliser cette métrique de similarité pour recommander des films.

Essayons de mettre en œuvre UB-CF et de générer une liste de films que notre ami Bob a.k.a utilisateur actif pourrait être intéressé à regarder. La motivation derrière l’écriture de ce post est de plonger en profondeur dans l’algorithme et de comprendre comment UB-CF fonctionne réellement. La plupart du contenu de ce post est inspiré d’un cours sur Coursera.

User-User Collaborative Filtering

La méthode identifie les utilisateurs qui sont similaires à l’utilisateur interrogé et estime que la note souhaitée est la moyenne pondérée des notes de ces utilisateurs similaires.

Filtrage collaboratif : source ici

Nous ferions les recommandations sur MovieLens Dataset. Le langage de programmation utilisé est python et le travail d’analyse de données est principalement effectué en utilisant la bibliothèque pandas. L’IDE utilisé est jupyter notebook.

Alors avant de commencer je voudrais donner la liste des bibliothèques utilisées :

  1. Pandas
  2. Numpy
  3. sklearn

Alors allons de l’avant et comprenons les concepts derrière les recommandations. J’ai joint quelques extraits de code et des sorties dans le blog pour une meilleure compréhension. L’ensemble du fichier ipynb est joint à la fin du blog.

Fonction score

Il est facile de trouver une fonction pour le filtrage collaboratif non personnalisé (c’est-à-dire que nous ne considérons pas les goûts, les aversions et l’évaluation de l’utilisateur actif dans le passé) qui renvoie un score en prenant l’utilisateur u et l’élément i comme paramètres d’entrée. La fonction produit un score qui quantifie à quel point un utilisateur u aime/préfère l’élément i.

C’est donc généralement fait en utilisant les évaluations d’autres personnes similaires à l’utilisateur. Tout ceci sera discuté en détail plus tard. Pour l’instant la formule que j’ai utilisée est,

fonction score

Où ‘s’ est le score prédit, ‘u’ est l’utilisateur, ‘i’ est l’élément, ‘r’ est la note donnée par l’utilisateur et ‘w’ est le poids.

Dans ce cas, notre score est égal à la somme des notes que chaque utilisateur a donné à cet élément en soustrayant la note moyenne de cet utilisateur multipliée par un certain poids qui est de combien cet utilisateur est similaire ou supposé contribuer aux prédictions des autres utilisateurs. C’est le poids entre l’utilisateur u et v. Le score varie entre 0 et 1, 0 étant faible et 1 étant élevé. Tout semble parfait, alors pourquoi avons-nous soustrait les notes moyennes de chaque utilisateur et pourquoi avons-nous utilisé la moyenne pondérée au lieu de la moyenne simple ?

Le problème vient des types d’utilisateurs que nous manipulons. Cela commence par le fait que les gens évaluent souvent sur des échelles très différentes. Je peux être un utilisateur positif et optimiste où je vais évaluer le film que j’ai aimé comme 4 sur 5, mais un autre utilisateur qui est moins optimiste ou a quelques normes élevées peut évaluer son film préféré comme 2 sur 5. Ici, son 2 est mon 4. Pour améliorer cet algorithme, nous pouvons en augmenter l’efficacité en normalisant la note de l’utilisateur. Une façon de le faire est de dire que nous allons calculer s(u,i) c’est-à-dire le score comme la note moyenne que l’utilisateur donne à chaque élément plus un certain écart et l’écart va être combien cet élément est meilleur ou pire que la moyenne.

J’ai utilisé la similarité cosinus pour calculer le poids donné dans la formule ci-dessus. J’ai également utilisé la notion de voisinage qui serait discutée dans ce blog au fur et à mesure que nous avançons.

Pour normaliser les données de la manière ci-dessus, une certaine analyse des données est nécessaire dans pandas. Vous pouvez obtenir le code entier à la fin. Pour le blog, je vais me concentrer sur les concepts importants.

import pandas as pdmovies = pd.read_csv("movies.csv",encoding="Latin1")
Ratings = pd.read_csv("ratings.csv")
Tags = pd.read_csv("tags.csv",encoding="Latin1")Mean = Ratings.groupby(by="userId",as_index=False).mean()
Rating_avg = pd.merge(Ratings,Mean,on='userId')
Rating_avg=Rating_avg-Rating_avg
Rating_avg.head()

Cotes normalisées

Alors maintenant nous avons fini de calculer la cote normalisée pour un utilisateur. Les données ci-dessus seraient utilisées pour calculer le score final de l’utilisateur plus tard.

À partir de là, nous allons maintenant nous concentrer sur certains concepts importants liés aux systèmes de recommandation.

Cosine Similarity

Pour la formule ci-dessus, nous devons trouver les utilisateurs qui ont des pensées similaires. Cela semble si intéressant de trouver un utilisateur qui a des goûts et des aversions similaires. Mais la question est de savoir comment trouver la similarité ?

Pour répondre à cette question, nous allons utiliser la similarité Cosinus et voir à quel point les utilisateurs sont similaires. Il est généralement calculé sur les évaluations que les deux utilisateurs ont évalué dans le passé.

Dans notre exemple, j’ai utilisé la fonction cosine_similarité de sklearn pour calculer la similarité. Mais avant cela, nous devons effectuer un certain prétraitement et nettoyer les données.

from sklearn.metrics.pairwise import cosine_similarityfinal=pd.pivot_table(Rating_avg,values='adg_rating',index='userId',columns='movieId')

tableau pivot

Ce tableau contient quelques lots de valeur NaN puisque chaque utilisateur n’a pas vu tous les films et c’est la raison pour laquelle ce type de matrice est appelé matrice éparse. Des méthodes comme la factorisation matricielle sont utilisées pour traiter cette rareté mais nous ne nous y intéresserons pas dans ce blog. L’étape suivante et une des étapes importantes est de remplacer ces valeurs NaN.

Il y a deux méthodes couramment utilisées pour cela :

  1. Utiliser la moyenne de l’utilisateur sur la ligne.
  2. Utiliser la moyenne du film sur la colonne.

J’ai utilisé les deux méthodes et vous pouvez l’obtenir dans le code ci-dessous. Mais pour expliquer, j’utiliserais la méthode de la moyenne du film.

# Replacing NaN by Movie Average
final_movie = final.fillna(final.mean(axis=0))

Remplacer les valeurs NaN par la moyenne du film

Maintenant, l’étape suivante consiste à calculer la similarité entre les utilisateurs.

# user similarity on replacing NAN by item(movie) avg
cosine = cosine_similarity(final_movie)
np.fill_diagonal(cosine, 0 )
similarity_with_movie =pd.DataFrame(cosine,index=final_movie.index)
similarity_with_movie.columns=final_user.index
similarity_with_movie.head()

Similitude cosinus utilisateur

Vérifions nous-mêmes si ce que nous avons calculé a vraiment un sens !!

a = get_user_similar_movies(370,86309)
a = a.loc]
a.head()

films similaires

D’après l’image ci-dessus, nous pouvons voir que la similarité que nous avons générée est vraie puisque les deux utilisateurs donnés (370,86309) ont presque les mêmes évaluations et les mêmes goûts.

Donc nous avons fini de calculer les similarités entre les utilisateurs mais je ne suis pas encore satisfait. Je discuterais de la raison dans la prochaine étape.

Voisinage pour l’utilisateur (K)

Donc, à partir de ce qui précède, nous pouvons voir que nous avons calculé les similarités pour tous les utilisateurs. Mais depuis que je suis un étudiant en Big Data, la complexité du problème me pousse toujours. Par cela, je veux dire que le système de recommandation fonctionne avec les données énormes et donc il devient très important de maintenir et de capturer seulement les faits saillants importants et nécessaires des données.

Pour expliquer cela en utilisant notre exemple de système de recommandation de films, la matrice que nous avons obtenue ci-dessus est (862*862), car il y a 862 utilisateurs uniques dans les données. Ce nombre est encore faible par rapport aux données sur lesquelles le système original devrait travailler. Prenons l’exemple d’Amazon. Il y aurait plus de millions d’utilisateurs dans sa base de données et donc, lors du calcul du score pour un article, ce ne serait pas une bonne solution ou méthode de regarder tous les autres utilisateurs tout le temps. Pour surmonter ce problème, nous créons une notion de voisinage. Cela comprend seulement l’ensemble des (K) utilisateurs similaires pour un utilisateur particulier.

Maintenant prenons d’autres mesures pour mettre en œuvre l’idée. Dans notre exemple, j’ai pris la valeur de k comme 30. Donc nous aurions 30 voisins les plus proches pour tous les utilisateurs.

J’ai utilisé ma fonction personnalisée find_n_neighbours qui prend la matrice de similarité et la valeur de n comme entrée et renvoie les n voisins les plus proches pour tous les utilisateurs. Vous pouvez trouver le code dans le notebook donné à la fin du blog.

# top 30 neighbours for each user
sim_user_30_m = find_n_neighbours(similarity_with_movie,30)
sim_user_30_m.head()

les 30 premiers voisins pour les utilisateurs

Alors maintenant si vous pensez que nous avons sérieusement réduit le nombre de calculs inutiles. Maintenant, nous sommes prêts à calculer le score d’un élément maintenant.

Générer le score final S(u,i)

Wow ! nous avons terminé le processus. Je sais que nous sommes passés par des trucs vraiment techniques, mais le temps passé en vaut la peine car nous avons atteint la dernière étape.

Ici nous allons essayer de prédire le score du film que l’utilisateur donné n’a pas vu.

score = User_item_score(320,7371)
print(score)

score prédit

Donc notre système a prédit que le score serait de 4,25 ce qui est vraiment bien. Je pense que l’utilisateur (370) pourrait aimer le film avec l’id (7371).

Maintenant donnons une touche finale à notre système. Je pense que la plupart d’entre nous auraient utilisé Netflix ou Hotstar. Donc, lorsque nous ouvrons l’application, il montre l’élément que vous faites comme.

Je suis toujours fasciné par la recommandation car ils s’avèrent être les films que j’aime. Tout cela se passe par le système de recommandation lui-même. Nous allons maintenant faire de même et essayer de prédire les 5 meilleurs films que l’utilisateur donné pourrait aimer.

La logique n’est pas si difficile. Nous avons déjà généré le score pour un élément. De même, nous pouvons générer le score pour les autres éléments avec le même utilisateur.

Mais, maintenant encore en gardant le Big Data en considération, cela a-t-il du sens de générer le score pour tous les autres éléments ??

Je pense NOOOOOO !!!

Prenons l’utilisateur (U) et l’utilisateur (K). Maintenant supposons que K n’est pas dans le voisinage de U ,est-il possible pour l’utilisateur U d’aimer un film que K a vu et noté. Principalement non.

Je pense que vous avez compris le truc. Oui, nous sommes juste intéressés par le calcul des notes pour les éléments que leurs utilisateurs voisins ont vu.

Nous avons vraiment réussi. Nous avons réduit le calcul de 2500 à N ( où N est l’ensemble des films que mon voisinage a aimé ) et qui est très inférieur à 2500.

Alors finalement, recommandons les films.

User_item_score1 est ma fonction personnalisée qui utilise notre discussion ci-dessus pour calculer les prédictions

user = int(input("Enter the user id to whom you want to recommend : "))
predicted_movies = User_item_score1(user)
print(" ")
print("The Recommendations for User Id : ",user)
print(" ")
for i in predicted_movies:
print(i)

At last !!!! Nous l’avons fait. Nous avons notre propre système de recommandation.

La représentation du code ci-dessous pourrait ne pas être très facile à lire, alors s’il vous plaît allez à mon dépôt GitHub pour accéder au code.

Les ensembles de données nécessaires peuvent être obtenus à partir d’ici.

J’espère que vous avez aimé le blog. Pour toute question, vous pouvez m’envoyer un mail. Restez à l’écoute pour d’autres blogs puisque c’est l’un de mes domaines d’intérêt et je posterais certainement de nouvelles choses.

Merci…!!

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée.