Objectif : implémenter quelques algorithmes de filtrage collaboratif.

L’implémentation est en Python et les utilisations sont dans des notebook. Pour faire le TP, vous pouvez par exemple utiliser le serveur jupyter-hub de l’ENSAI. Vous pouvez aussi faire tourner les notebooks sur votre propre ordinateur.

Soumission du TP : Vous devez soumettre le TP par mail au plus tard à 23h59 le 22 Mars, 2024 (pour les etudiants MKT). Le mail doit avoir le sujet RECSYS-MKT-2024-TP1 et elle doit contenir un fichier ZIP contenant les fichiers .py et .ipynb. Le nom du ZIP doit etre le suivant:

  • Si vous travaillez en groupe : [nom1]-[nom2]-MKT-TP1.zip ou [nom1] et [nom2] sont les deux nom des deux membres du groupe de travail
  • Si vous travaillez individuellement : [prenom]-[nom]-MKT-TP1.zip ou [prenom] et [nom] sont votre prenom et nom.

1 Le problème

On travaille avec des données issues du système de recommandation de films MovieLens. Plusieurs jeux de données sont disponibles sur le site de GroupLens. Ces jeux de données diffèrent par leur taille et nous travaillons avec le plus petit. Vous êtes invités à refaire le TP avec les autres jeux de données par vous-même.

MovieLens est un site communautaire de recommandation de films. Les utilisateurs de ce site notent des films de 1 à 5. Ils peuvent également demander des suggestions de films étant donnés les notations qu’ils ont fournies.

Chaque utilisateur est décrit par quelques attributs :

  • un numéro d’identification,
  • son âge,
  • son sexe,
  • son métier,
  • son code postal (USA).

Chaque film est décrit par :

  • un numéro d’identification,
  • son titre,
  • sa date de sortie au cinéma,
  • son genre.

On dispose alors d’une liste de notes sous la forme :

  • identifiant d’utilisateur,
  • identifiant de film,
  • note attribué par cet utilisateur à ce film,
  • information de date : nombre de secondes écoulées depuis le 1/1/1970.

Il y a 100 000 notes, provenant de 943 utilisateurs pour 1 682 films. Les autres jeux de données disponibles sur ce site web en comptent respectivement 1 million et 10 millions.

L’objectif est de recommander des films à un utilisateur. Les recommandations peuvent concerner des films qui devraient lui plaire, mais aussi des films qui ne lui plairont probablement pas.

Pour cela, on applique différents algorithmes de filtrage collaboratif.

2 Les données et le code

Les données ont été nettoyées pour qu’elles puissent être chargées sans problème en python. Elles sont accessibles sur le site web du cours. Dans le cadre du TP, on n’utilise que le fichier des notes : u.data.

Dans le répertoire consacré au TP, créez un répertoire data et mettez les fichiers de données dans ce répertoire.

La page web du cours contient aussi un zip avec des fichiers Python et des notebook utiles pour le TP :

  • data.py : implémente les fonctions utiles au chargement et à la prépartion des données : load_data(tiny=FALSE) et movie_title(id).
  • eval.py : implémente les fonctions utiles à l’évaluation des modèles : quantitative_comparison(scoring_fn, M_star, recommenders, prop=0.8, nrep=10), RMSE(M_completed, M_star) et get_train_val(M, prop=0.8).
  • popularity.py : implémente un système de recommandation fondé sur la popularité des films. Il ne personnalise pas la recommandation.
  • knn.py : implémente un système de recommandation fondé sur les k plus proches voisins. La version implémentée est celle cherchant les utilisateurs voisins selon le critère du cosinus.
  • svd.py : signature des fonctions nécessaires à l’implémentation d’un système de recommandation fondé sur la décomposition en valeurs singulières.
  • test.ipynb : notebook permettant de tester les algorithmes implémentés. Ce notebook permet aussi de voir des exemples d’utilisation des implémentations fournies.
  • compare.ipynb : notebook permettant de comparer quantitativement la qualité des recommandations des divers algorithmes implémentés.
  • (bonus) qualitative_compare.ipynb : notebook permettant de comparer qualitativement la qualité des recommandations des divers algorithmes implémentés.

Téléchargez les zip et decompressez le dans le répertoire consacré au TP.

3 Recommandation de films

3.1 Popularity

Testez un système de recommandation fondé sur l’approche Popularity-based.

Etudiez le code dans le fichier popularity.py et commentez chaque ligne en disant ce que elle fait. Vous aurez besoin de regarder aussi le code du notebook compare.ipynb et des fichiers python data.py et eval.py

3.2 KNN : approche memory-based k-plus proches voisins

Testez un système de recommandation fondé sur l’approche KNN.

Etudiez le code dans le fichier knn.py et commentez chaque ligne en disant ce que elle fait. En particulier il faudra aussi determiner s'il s'agit d'un user-based ou un item-based collaborative filtering. Vous aurez besoin de regarder aussi le code du notebook compare.ipynb et des fichiers python data.py et eval.py

Modifiez le notebook compare.ipynb pour chercher les valeurs du parametre k les plus adaptées aux données MovieLens et sauvegardez votre resultat.

Creez une copie de knn.py et implementez l'autre approche memory based (user-based ou item-based). Ajoutez votre approche dans compare.ipynb. Et cherchez les valeurs du parametre k lee plus adaptées aux données MovieLens et sauvegardez votre resultat.

3.3 SVD : factorisation de matrice par décomposition en valeurs singulières

Implémentez et testez un système de recommandation fondé sur l’approche par décomposition en valeurs singulières qui pré-remplit les valeurs manquantes avec la valeur zéro.

Dans le fichier svd.py vous avez trois fonctions vides.

  • replaceNA_with_zeros qui remplace les valeurs NA par des zero pour pouvoir utiliser la methode de factorization.
  • complete qui factorize la matrice initiale en utilisant la metode linalg.svd de numpy (vous pouvez regarder un exemple ici) et retourne une matrice de poids obtenue en faisant le produit des trois facteurs trunque' au k-eme valeur propre.
  • recommend qui appelle la fonction complete et utilise son resultat pour predire le rating d'un utilisateur pour une item.
Implementez ces trois fonctions.

Regardez quelques recommendations faites par cette fonction et expliquez comment cette fonction marche, et rajoutez des commentaires dans ce sense dans le code

Cherchez les valeurs de paramètres les plus adaptées aux données MovieLens en utilisant compare.ipynb. N'effacez pas vos resultats precedents.

Cliquez pour aller plus loin

Implémentez et testez d’autres pré-imputations. Cherchez la meilleur pré-imputation.

Modifiez le partitionnement entre training et testing set dans eval.py. Essayez aussi de mettre a false le parametre tiny dans l'invocation de data.load_data. Est-ce que les resultats changent?

4 Metriques d'evaluation

Le fichier eval implemente une fonction RMSE que vous avez deja utilise' dans les etapes precedentes.

Le but de cet exercise est d'implementer les autres metriques vue dans le cours, notamment

  • MAE
  • Recall
  • Precision

Pour chacune des metriques decrivez votre protocole d'evaluation.

RappelLes valeurs de recall de precision dependent du nombre n d'items qui sont recommandees. Basez vous sur les elements vu en cours pour determiner comment faire la compairaison.

RappelLe calcul des metriques depende aussi du choix du candidate set. Evaluez les differents methodes vu dans le cours et comparez les resultats. Pour cela vous pouvez lire le papier "Precision-Oriented Evaluation of Recommender Systems: An Algorithmic Comparison" disponible dans la page web du cours et les pages 20 et 21 du fichier florestanDeMoor.pdf.

Cliquez pour aller plus loin

Evaluez les algorithmes selon les autres metriques discutees dans le cours notamment.

  • User-space Coverage
  • Item-space Coverage
  • Ranking based on predicted ratings vs ranking based on actual ratings
Pour chacune des metriques decrivez votre protocole d'evaluation.

Modifiez le partitionnement entre training et testing set dans eval.py. Essayez aussi de mettre a false le parametre tiny dans l'invocation de data.load_data. Est-ce que les resultats changent?

5 (Pour aller plus loin) Recommandation de films (bis)

5.1 ALS-WR

Implémentez et testez un système de recommandation fondé sur l’approche par regression aux moindres carrés alternée qui définit la prediction ainsi

\[\widehat{M} = \mathop{\text{argmin}}_{X=UV^T}\sum_{M_{i,j} \text{ connu}} (U_i.V_j^T-M_{i,j})^2 + \lambda.\|U\|^2 + \lambda.\|V\|^2,\]

  • \(M\) est la matrice contenant les notes connues,
  • \(U\) et \(V\) sont des matrices avec \(k\) colonnes,
  • \(k\) et \(\lambda\) sont des hyper-paramètres à fixer.

Ajoutez un fichier als.py et implémentez et testez la fonction complete(M_train, k, n_iter=5, lambd=0.1) qui retourne la matrice prédite. M_train est la matrice initiale (contenant des NA), k est le rang de la matrice inférée, n_iter est le nombre de passes faites sur l’ensemble des lignes et colonnes de la matrice, et lambd est le poids associé à la régularisation.

Cherchez les valeurs de paramètres les plus adaptées aux données MovieLens.

Cliquez pour aller plus loin

Implémentez et testez la fonction recommend(M_train, id_user, new=TRUE, k=10, n_iter=5, lambd=0.1) qui recommande un film (son numéro) au id_user-ième utilisateur. new indique si l’algorithme a le droit de recommander un film déjà noté par l’utilisateur (new=FALSE) ou non (new=TRUE), k est le rang de la matrice inférée, n_iter est le nombre de passes faites sur l’ensemble des lignes et colonnes de la matrice, et lambd est le poids associé à la régularisation.

Regardez quelques recommendations faites par cette fonction.

5.2 SGD

Implémentez et testez un système de recommandation fondé sur l’approche par descente de gradient stochastique qui définit la prediction ainsi

\[\widehat{M} = \mathop{\text{argmin}}_{X=UV^T}\sum_{M_{i,j} \text{ connu}} \frac{1}{2}\left[(U_iV_j^T-M_{i,j})^2 + \lambda\|U_i\|^2 + \lambda\|V_j\|^2\right],\]

  • \(M\) est la matrice contenant les notes connues,
  • \(U\) et \(V\) sont des matrices avec \(k\) colonnes,
  • \(k\) et \(\lambda\) sont des hyper-paramètres à fixer.

On note \(L_{i,j} = \frac{1}{2}(U_iV_j^T-M_{i,j})^2 + \frac{1}{2}\lambda\|U_i\|^2 + \frac{1}{2}\lambda\|V_j\|^2\) la perte pour l’entrée \(M_{i,j}\). Alors les gradients de \(L_{i,j}\) sont donnés par les formules :

  • \(\frac{\partial L_{i,j}}{\partial U_i} = -(M_{i,j} - U_i.V_j^T)V_j + \lambda U_i\),
  • \(\frac{\partial L_{i,j}}{\partial V_j} = -(M_{i,j} - U_i.V_j^T)U_i + \lambda V_j\).

Implémentez et testez les fonctions suivantes :

  • complete(M_train, k, n_iter=5, lambd=0.1) qui retourne la matrice prédite. M_train est la matrice initiale (contenant des NA), k est le rang de la matrice inférée, n_iter est le nombre de passes faites sur l’ensemble des lignes et colonnes de la matrice, et lambd est le poids associé à la régularisation ;
  • recommend(M_train, id_user, new=TRUE, k=10, n_iter=5, lambd=0.1) qui recommande un film (son numéro) au id.user-ième utilisateur. new indique si l’algorithme a le droit de recommander un film déjà noté par l’utilisateur (new=FALSE) ou non (new=TRUE), k est le rang de la matrice inférée, n_iter est le nombre de passes faites sur l’ensemble des lignes et colonnes de la matrice, et lambd est le poids associé à la régularisation.

Cherchez les valeurs de paramètre les plus adaptées aux données MovieLens.

6 (Pour aller plus loin) Exploration “préliminaire” des données

Comme toujours, on aurait dû commencer par explorer les données pour les comprendre. Voici quelques questions que vous pourriez-vous poser sur les données :

  • Quelle est la distribution des notes ?
  • Quelle est la distribution du nombre de notes par film / par utilisateur ?
  • Quelle est la distribution de la note moyenne par utilisateur ?
  • Cette distribution est-elle corrélée au nombre de notes données par l’utilisateur ?
  • Est-ce qu’il y a une corrélation entre les informations sur l’utilisateur et ses notes ?
  • Est-ce qu’il y a une corrélation entre les informations concernant un film et les notes qu’il a reçues ?