import numpy as np
import scipy.sparse as sp
import matplotlib.pyplot as plt
Récupérez l'archive http://files.grouplens.org/datasets/movielens/ml-100k.zip, sauvegardez-la dans votre répertoire de travail, et décompressez-la.
Le jeu de données contient 100,000 notes (entre 1 et 5) données par 943 utilisateurs sur 1682 films.
Nous utiliserons pour ce TP:
u.data
qui contient la liste des diférentes notes données par les différents utilisateurs aux différents filmsu.item
qui fournit des informations sur les films concernés (titre, année de sortie, genre,...)import pandas
f = open("ml-100k/u.data",'r', encoding = 'latin_1')
rating_data = pandas.read_csv(f, delimiter='\t', header = None)
rating_data.columns=['user_id', 'item_id', 'rating', 'timestamp']
rating_data
Les notes sont définies sous forme de triplets (3 premières colonnes):
Pour qu'elles soient exploitables, vous devez transformer ces données au format matrice creuse (coo matrix ou csr matrix).
Voir:
http://docs.scipy.org/doc/scipy-0.14.0/reference/generated/scipy.sparse.coo_matrix.html
http://docs.scipy.org/doc/scipy-0.14.0/reference/generated/scipy.sparse.csr_matrix.html
row = rating_data.user_id #- 1 # !! numerotation à partir de 0 en python
col = rating_data.item_id #- 1
rating = rating_data.rating
X = sp.coo_matrix((rating, (row , col))).toarray()
plt.figure(figsize=(35,12))
plt.imshow(X, aspect='auto')
Pour lire les données contenues dans u.item
, vous devez utiliser un pandas.read_csv
:
f = open("ml-100k/u.item",'r', encoding = 'latin_1')
film_data = pandas.read_csv(f, delimiter='|', header = None)
film_data.columns=['item_id', 'title', 'date', 'nan', 'url', 'unknown', 'Action', 'Adventure', 'Animation', "Children's", 'Comedy', 'Crime', 'Documentary', 'Drama', 'Fantasy', 'Film-Noir', 'Horror', 'Musical', 'Mystery', 'Romance', 'Sci-Fi', 'Thriller', 'War', 'Western']
film_data.set_index('item_id')
del film_data['nan']
film_data
Exo : affichez le titre et le genre des dix premiers films de la liste.
L'indice idx
de film_data
est le correspond à un numero de colonne dans la matrice X
Calculez (sous la forme d'un tableau bidimensionnel) la similarité cosinus entre les 5 premiers films de film_data et affichez-le.
Rappel : simcos(x,y)=⟨x,y⟩√⟨x,x⟩.⟨y,y⟩
NB: le produit scalaire entre 2 vecteurs est obtenu par la fonction np.dot(x,y)
Calculez de même le tableau de similarité de corrélation entre les mêmes films et comparez le au tableau précédent
Rappel : simcorr(x,y)=⟨x−ˉx,y−ˉy⟩√⟨x−ˉx,x−ˉx⟩.⟨y−ˉy,y−ˉy⟩
Pour ces deux mesures de similarité, affichez maintenant la liste des dix films les plus similaires au film 'Citizen Kane (1941)', par ordre de similarité décroissante. Conclusion?
(m,n) = X.shape
X_norm = np.zeros((m,n))
for i in range(1, m):
indices = np.where(X[i,:]>0)
X_norm[i,indices] = X[i,indices] - np.mean(X[i,indices])
plt.figure(figsize=(35,12))
plt.imshow(X_norm, aspect='auto')
Memes questions que l'exercice 1 en utilisant X_norm au lieu de X. Conclusion?
On cherche à prédire la note donnée par un utilisateur i à un film j. Pour celà, on utilise la méthode des K plus proches voisins.
Affichez tout d'abord la liste des films notés par l'utilisateur 678, avec les notes associées.
La méthode des K plus proche voisins permet de prédire les notes produites par l'utilisateur à partir des notes des utilisateurs dont le profil est le plus proche.
La similarité entre utilisateurs sera basée sur les vecteurs lignes de la matrice X.
Ecrivez une fonction calcule_voisins(i,K)
qui retourne la liste des K utilisateurs ayant le profil le plus similaire de celui de l'utilisateur i.
Puis testez-la:
voisins = calcule_voisins(i,50)
print(voisins)
Ecrivez une fonction moy_pond(i, voisins, j) qui, à partir de la liste des voisins, retourne l'estimation de la note attribuée au film j par moyenne pondérée selon la formule :
predi,j=mi+∑v∈Voisins(i)sim(i,v)(rv,j−mv)∑v∈Voisins(i)sim(i,v)avec :
Ecrivez une fonction vote(voisins, j) qui, à partir de la liste des voisins, retourne la note la plus probable par vote majoritaire (chaque voisin vote pour sa note).
Testez ces 2 fonctions sur la liste des films de l'utilsateur 678. Affichez pour chaque film la note réelle et sa prédiction selon ces 2 méthodes.
Calculez également l'erreur moyenne, en fonction du nombre de voisins
Déterminez laquelle de ces méthodes est en moyenne la plus précise.
Attention :