Alberto Beiz

Mis pruebas y experimentos.

Contacta sin miedo:

Filtro colaborativo (sistema recomendador) con Fastai

¿Como hace Netflix para recomendarte películas? ¿O Amazon para recomendarte productos? Pues cosas mucho más complejas que las que vamos a ver en este post :D ¡Pero por algo hay que empezar!

Objetivos

Antes de empezar

Al turrón

%reload_ext autoreload
%autoreload 2
%matplotlib inline

from fastai.learner import *
from fastai.column_data import *
PATH = 'data/movielens/'
# cargamos el dataset
ratings = pd.read_csv(PATH+'ratings.csv')
ratings.head()
userId movieId rating timestamp
0 1 31 2.5 1260759144
1 1 1029 3.0 1260759179
2 1 1061 3.0 1260759182
3 1 1129 2.0 1260759185
4 1 1172 4.0 1260759205
# Vemos la lista de peliculas
movies = pd.read_csv(PATH+'movies.csv')
movies.head()
movieId title genres
0 1 Toy Story (1995) Adventure|Animation|Children|Comedy|Fantasy
1 2 Jumanji (1995) Adventure|Children|Fantasy
2 3 Grumpier Old Men (1995) Comedy|Romance
3 4 Waiting to Exhale (1995) Comedy|Drama|Romance
4 5 Father of the Bride Part II (1995) Comedy
# Creamos el set de validación
val_idxs = get_cv_idxs(len(ratings))
# Regularización
wd=2e-4
# Tamaño de los embeddings
n_factors = 50
# Creamos el modelo. Indicamos la tabla, las columnas de las entidades
# (usuarios y películas) y valor a predecir
cf = CollabFilterDataset.from_csv(PATH, 'ratings.csv', 'userId', 'movieId', 'rating')
learn = cf.get_learner(n_factors, val_idxs, 64, opt_fn=optim.Adam)
# Entrenamos
learn.fit(1e-2, 2, wds=wd, cycle_len=1, cycle_mult=2)
epoch      trn_loss   val_loss                                  
    0      0.814042   0.806063  
    1      0.765293   0.782853                                  
    2      0.59447    0.768173                                  
learn.save('lens')
learn.load('lens')
# Función para predecir la valoración de un usuario
# a una lista de películas
def pred(u, m):
    # id dentro del modelo
    idx = [cf.item2idx[i] for i in m]

    # aplicamos el modelo
    pred = learn.model(V(T([u]*len(m))), V(T(idx)))
    return pred.cpu().data.numpy()
pred(1, [32])
array([ 3.76582], dtype=float32)
# Vamos a ver las películas que más le gustan al usuario 1
user1 = ratings[ratings.userId == 1]
user1.merge(movies).sort_values('rating', ascending=False).head(10)
userId movieId rating timestamp title genres
4 1 1172 4.0 1260759205 Cinema Paradiso (Nuovo cinema Paradiso) (1989) Drama
13 1 2105 4.0 1260759139 Tron (1982) Action|Adventure|Sci-Fi
12 1 1953 4.0 1260759191 French Connection, The (1971) Action|Crime|Thriller
8 1 1339 3.5 1260759125 Dracula (Bram Stoker's Dracula) (1992) Fantasy|Horror|Romance|Thriller
19 1 3671 3.0 1260759117 Blazing Saddles (1974) Comedy|Western
1 1 1029 3.0 1260759179 Dumbo (1941) Animation|Children|Drama|Musical
2 1 1061 3.0 1260759182 Sleepers (1996) Thriller
14 1 2150 3.0 1260759194 Gods Must Be Crazy, The (1980) Adventure|Comedy
17 1 2455 2.5 1260759113 Fly, The (1986) Drama|Horror|Sci-Fi|Thriller
0 1 31 2.5 1260759144 Dangerous Minds (1995) Drama
# Predecimos unas cuantas peliculas al azar
r = movies.sample(frac=0.004)
r_i = r.movieId.tolist()
r_preds = pred(1, r_i)

# Las mostramos ordenadas
r['user 1 pred'] = r_preds
r.sort_values('user 1 pred', ascending=False)
movieId title genres user 1 pred
5 6 Heat (1995) Action|Crime|Thriller 3.804713
7619 80489 Town, The (2010) Crime|Drama|Thriller 3.547790
7792 86347 Louis C.K.: Chewed Up (2008) Comedy 3.405489
8774 120821 The War at Home (1979) Documentary|War 3.324330
4401 5959 Narc (2002) Crime|Drama|Thriller 3.323261
4767 6711 Lost in Translation (2003) Comedy|Drama|Romance 3.299270
8195 98243 Rise of the Guardians (2012) Adventure|Animation|Children|Fantasy|IMAX 3.283734
5406 8385 Lover Come Back (1961) Comedy|Romance 3.280140
5635 8973 Bad Education (La mala educación) (2004) Drama|Thriller 3.273949
1363 1728 Winter Guest, The (1997) Drama 3.273107
5709 25962 King Solomon's Mines (1950) Action|Adventure|Romance 3.258285
335 371 Paper, The (1994) Comedy|Drama 3.251215
6949 59392 Stargate: The Ark of Truth (2008) Action|Fantasy|Sci-Fi 3.242820
5258 7843 Lammbock (2001) Comedy 3.231621
1986 2482 Still Crazy (1998) Comedy|Romance 3.215308
5376 8263 Take Me Out to the Ball Game (1949) Comedy|Musical|Romance 3.206782
2753 3449 Good Mother, The (1988) Drama 3.201610
7867 89045 Rocky VI (1986) Comedy 3.195117
6113 32825 Sexmission (Seksmisja) (1984) Adventure|Comedy|Sci-Fi 3.195117
9005 142240 Romeos (2011) Drama 3.195117
7378 72294 Christmas Carol, A (2009) Animation|Children|Drama|Fantasy|IMAX 3.195117
8212 98829 Evil Cult, The (Lord of the Wu Tang) (Yi tian ... Action|Fantasy 3.195117
7720 83603 Fern flowers (Fleur de fougère) (1949) Animation 3.195117
3083 3855 Affair of Love, An (Liaison pornographique, Un... Drama|Romance 3.193918
3166 3960 Haunted (1995) Drama|Thriller 3.180170
1664 2104 Tex (1982) Drama 3.174023
4407 5966 Kiss Before Dying, A (1956) Film-Noir|Mystery 3.163048
5426 8482 Picture of Dorian Gray, The (1945) Drama|Fantasy|Horror 3.161517
5066 7222 Reefer Madness (a.k.a. Tell Your Children) (1938) Comedy|Drama 3.157145
6239 37736 Oliver Twist (2005) Drama 3.155708
5058 7209 M. Hulot’s Holiday (Mr. Hulot's Holiday) (Vaca... Comedy 3.144980
8 9 Sudden Death (1995) Action 3.110150
2159 2699 Arachnophobia (1990) Comedy|Horror 3.073169
6410 44828 Slither (2006) Comedy|Horror|Sci-Fi 3.046045
2963 3709 Sleepwalkers (1992) Horror 3.033271
3296 4130 Maid to Order (1987) Comedy|Fantasy 3.010936

Ahora podríamos sugerirle al usuario las películas que el modelo crea que va a votar mejor. O no mostrarle las que no le van a gustar.

Recapitulando

Fuentes