Importamos las librería que vamos a utilizar
import numpy as np
import matplotlib.pyplot as plt
#import scipy.optimize #Use for fmincg
import scipy as sp
from recommenders import *
Utilizamos el lector de archivos de NumPy, esto porque así cargamos los datos en un formato utilizable para las operaciones matemáticas posteriores
datafile = 'utility_matrix.txt'
mat = np.loadtxt( datafile )
Tomamos los índices de los elementos rankeados en la metriz, esto para luego dividir los datos (Ojo que los datos se dividen por par rankeado, no por usuario o ítem). Checkeamos además que todo esté en orden, vemos además el porcentaje de la matriz que es no-cero, la forma de la matriz y la cantidad de elementos no-cero.
x,y = np.nonzero(mat)
mat[x[0],y[0]],x[0],y[0],mat
x.size/(mat.shape[0]*mat.shape[1])*100, np.min(mat[x,y]), mat.shape, x.size
Dividimos en test y entrenamiento de forma aleatorea.
# Entrenamiento + Test
indices = np.random.permutation(x.size)
entrenamiento = indices[:int(3*x.size/4)]
test = indices[int(3*x.size/4):]
Y construimos el test de entrenamiento.
Y_train = np.zeros_like(mat)
Y_train[x[entrenamiento],y[entrenamiento]] = mat[x[entrenamiento],y[entrenamiento]]
# Y_train2 = np.copy(mat)
# Y_train2[x[test],y[test]] = 0
Construimos el modelo y lo entrenamos (En el caso de los modelos que deba construir la función .fit(Y_train) sólo guardará los datos de Y_train pues son modelos lazy).
model_recommender = ModelBasedRecommender()#0.1*np.power(1.5,3),3+0)
model_recommender.fit(Y_train)
pred = model_recommender.predict_many(x[test],y[test])
from sklearn.metrics import mean_squared_error
np.sqrt(mean_squared_error(mat[x[test],y[test]], pred))
Algo importante de lo anterior es que la función .predict(a,b) remplaza los valores mayores a 5 por 5 y menores a 1 por 1, además los redondea a entreros (ver el código de la función predict_many en el "return")
La similaridad coseno ya está implementada en scikit-learn y devuelve una matriz simétrica con las similaridades
from sklearn.metrics.pairwise import cosine_similarity
cos_sim = cosine_similarity(mat)
Primero vemos que tenga la forma adecuada.
cos_sim.shape, mat.shape
Efectivamente vemos que es una matriz cuadrada con dimesión igual a la cantidad de películas.
El siguiente comando muestra las similitudes de la película 7 con los ítemes que ha etiquetado el usuario 543
cos_sim[7,np.nonzero(Y_train[:,543])[0].astype(int)]