Post Top Ad

Your Ad Spot

martes, 9 de julio de 2019

Creando un sistema de recomendación simple en Python usando Pandas

Introducción

¿Alguna vez te has preguntado cómo Netflix te sugiere películas basadas en las películas que ya has visto? ¿O cómo muestran los sitios web de comercio electrónico opciones tales como "Comprados con frecuencia juntos"? Pueden parecer opciones relativamente simples, pero detrás de escena, se ejecuta un algoritmo estadístico complejo para predecir estas recomendaciones. Dichos sistemas se denominan sistemas de recomendación, sistemas de recomendación o motores de recomendación. Un sistema de recomendación es una de las aplicaciones más famosas de la ciencia de datos y el aprendizaje automático.
Un sistema de recomendación utiliza un algoritmo estadístico que busca predecir las calificaciones de los usuarios para una entidad en particular, en función de la similitud entre las entidades o la similitud entre los usuarios que previamente calificaron esas entidades. La intuición es que tipos de usuarios similares probablemente tengan calificaciones similares para un conjunto de entidades.
Actualmente, muchas de las grandes empresas de tecnología utilizan un sistema de recomendación de una u otra forma. Puede encontrarlos en cualquier lugar, desde Amazon (recomendaciones de productos) a YouTube (recomendaciones de video) a Facebook (recomendaciones de amigos). La capacidad de recomendar productos o servicios relevantes a los usuarios puede ser un gran impulso para una empresa, por lo que es tan común encontrar esta técnica empleada en tantos sitios.
En este artículo, veremos cómo podemos construir un sistema de recomendación simple en Python.

Tipos de sistemas de recomendación

Hay dos enfoques principales para construir sistemas de recomendación: filtrado basado en contenido y filtrado colaborativo:

Filtrado basado en contenido

En el filtrado basado en el contenido, la similitud entre los diferentes productos se calcula sobre la base de los atributos de los productos. Por ejemplo, en un sistema de recomendación de películas basadas en contenido, la similitud entre las películas se calcula en función de los géneros, los actores de la película, el director de la película, etc.

Filtración colaborativa

El filtrado colaborativo aprovecha el poder de la multitud. La intuición detrás del filtrado colaborativo es que si a un usuario A le gustan los productos X e Y, y si a otro usuario B le gusta el producto X, existe una gran posibilidad de que también le guste el producto Y.
Tomemos el ejemplo de un sistema de recomendación de películas. Supongamos que una gran cantidad de usuarios ha asignado las mismas clasificaciones a las películas X e Y. Llega un nuevo usuario que ha asignado la misma calificación a la película X, pero aún no ha visto la película Y. Sistema de filtrado colaborativo le recomendará la película Y.

Implementación del sistema de películas recomendadas en Python

En esta sección, desarrollaremos un sistema de recomendación de películas muy simple en Python que utiliza la correlación entre las clasificaciones asignadas a diferentes películas para encontrar la similitud entre las películas.
El conjunto de datos que vamos a utilizar para este problema es el conjunto de datos MovieLens. Para descargar el conjunto de datos, vaya a la página de inicio del conjunto de datos y descargue el archivo "ml-latest-small.zip", que contiene un subconjunto del conjunto de datos de la película real y contiene 100000 calificaciones para 9000 películas de 700 usuarios.
Una vez que haya descomprimido el archivo descargado, verá los archivos "links.csv", "movies.csv", "ratings.csv" y "tags.csv", junto con el documento "README". En este artículo, vamos a utilizar los archivos "movies.csv" y "ratings.csv".
Para los scripts en este artículo, la carpeta "ml-latest-small" descomprimida se ha colocado dentro de la carpeta "Datasets" en la unidad "E".

Visualización de datos y preprocesamiento.

El primer paso en cada problema de la ciencia de datos es visualizar y preprocesar los datos. Haremos lo mismo, así que primero importemos el archivo "ratings.csv" y veamos qué contiene. Ejecuta el siguiente script:
import numpy as np  
import pandas as pd

ratings_data = pd.read_csv("E:\Datasets\ml-latest-small\\ratings.csv")  
ratings_data.head()  
En el script anterior, usamos el read_csv()método de la biblioteca de Pandas para leer el archivo "ratings.csv". A continuación, llamamos al head()método desde el objeto de marco de datos devuelto por la read_csv()función, que mostrará las primeras cinco filas del conjunto de datos.
La salida se ve así:
ID de usuarioID de películaclasificaciónmarca de tiempo
01312.51260759144
1110293.01260759179
2110613.01260759182
3111292.01260759185
4111724.01260759205
Puede ver en la salida que el archivo "ratings.csv" contiene los atributos userId, movieId, ratings y timestamp. Cada fila en el conjunto de datos corresponde a una calificación. La columna userId contiene el ID del usuario que dejó la calificación. La columna movieId contiene el Id. De la película, la columna de calificación contiene la calificación que dejó el usuario. Las calificaciones pueden tener valores entre 1 y 5. Y, finalmente, la marca de tiempo se refiere al momento en que el usuario dejó la calificación.
Hay un problema con este conjunto de datos. Contiene las identificaciones de las películas pero no sus títulos. Necesitaremos nombres de películas para las películas que estamos recomendando. Los nombres de las películas se almacenan en el archivo "movies.csv". Importemos el archivo y veamos los datos que contiene. Ejecuta el siguiente script:
movie_names = pd.read_csv("E:\Datasets\ml-latest-small\\movies.csv")  
movie_names.head()  
La salida se ve así:
ID de películatítulogéneros
01Toy Story (1995)Aventura | Animación | Niños | Comedia | Fantasía
12Jumanji (1995)Aventura | Niños | Fantasía
23Hombres viejos más gruñones (1995)Comedia | romance
34Esperando a exhalar (1995)Comedia | Drama | Romance
45Padre de la Novia Parte II (1995)Comedia
Como puede ver, este conjunto de datos contiene movieId, el título de la película y su género. Necesitamos un conjunto de datos que contenga el ID de usuario, el título de la película y sus calificaciones. Tenemos esta información en dos objetos de marco de datos diferentes: "ratings_data" y "nombres de película". Para obtener nuestra información deseada en un solo marco de datos, podemos combinar los dos objetos de marcos de datos en la columna movieId, ya que es común entre los dos marcos de datos.
Podemos hacer esto usando la merge()función de la biblioteca de Pandas, como se muestra a continuación:
movie_data = pd.merge(ratings_data, movie_names, on='movieId')  
Ahora veamos nuestro nuevo marco de datos:
movie_data.head()  
La salida se ve así:
ID de usuarioID de películaclasificaciónmarca de tiempotítulogéneros
01312.51260759144Mentes peligrosas (1995)Drama
17313.0851868750Mentes peligrosas (1995)Drama
231314.012703541953Mentes peligrosas (1995)Drama
332314.0834828440Mentes peligrosas (1995)Drama
436313.0847057202Mentes peligrosas (1995)Drama
Puede ver que nuestro marco de datos recién creado contiene ID de usuario, título y clasificación de la película según sea necesario.
Ahora echemos un vistazo a la calificación promedio de cada película. Para hacerlo, podemos agrupar el conjunto de datos por el título de la película y luego calcular la media de la calificación de cada película. Luego, mostraremos las primeras cinco películas junto con su calificación promedio utilizando el head()método. Mira el siguiente script:
movie_data.groupby('title')['rating'].mean().head()  
La salida se ve así:
title  
"Great Performances" Cats (1998)           1.750000
$9.99 (2008)                               3.833333
'Hellboy': The Seeds of Creation (2004)    2.000000  
'Neath the Arizona Skies (1934)            0.500000  
'Round Midnight (1986)                     2.250000  
Name: rating, dtype: float64  
Puedes ver que las calificaciones promedio no están ordenadas. Vamos a ordenar las calificaciones en orden descendente de sus calificaciones promedio:
movie_data.groupby('title')['rating'].mean().sort_values(ascending=False).head()  
Si ejecuta el script anterior, la salida se verá así:
title  
Burn Up! (1991)                                     5.0  
Absolute Giganten (1999)                            5.0  
Gentlemen of Fortune (Dzhentlmeny udachi) (1972)    5.0  
Erik the Viking (1989)                              5.0  
Reality (2014)                                      5.0  
Name: rating, dtype: float64  
Las películas ahora se han ordenado según el orden ascendente de sus calificaciones. Sin embargo, hay un problema. Una película puede llegar al principio de la lista anterior incluso si solo un usuario le ha dado cinco estrellas. Por lo tanto, las estadísticas anteriores pueden ser engañosas. Normalmente, una película que es realmente buena obtiene una calificación más alta por un gran número de usuarios.
Ahora vamos a trazar el número total de calificaciones para una película:
movie_data.groupby('title')['rating'].count().sort_values(ascending=False).head()  
La ejecución del script anterior devuelve el siguiente resultado:
title  
Forrest Gump (1994)                          341  
Pulp Fiction (1994)                          324  
Shawshank Redemption, The (1994)             311  
Silence of the Lambs, The (1991)             304  
Star Wars: Episode IV - A New Hope (1977)    291  
Name: rating, dtype: int64  
Ahora puedes ver algunas películas realmente buenas en la parte superior. La lista anterior apoya nuestro punto de que las buenas películas normalmente reciben calificaciones más altas. Ahora sabemos que tanto la calificación promedio por película como el número de calificaciones por película son atributos importantes. Vamos a crear un nuevo marco de datos que contenga ambos atributos.
Ejecute el siguiente script para crear el ratings_mean_countmarco de datos y primero agregue la calificación promedio de cada película a este marco de datos:
ratings_mean_count = pd.DataFrame(movie_data.groupby('title')['rating'].mean())  
A continuación, debemos agregar la cantidad de calificaciones para una película al ratings_mean_countmarco de datos. Ejecute el siguiente script para hacerlo:
ratings_mean_count['rating_counts'] = pd.DataFrame(movie_data.groupby('title')['rating'].count())  
Ahora echemos un vistazo a nuestro marco de datos recién creado.
ratings_mean_count.head()  
La salida se ve así:
títuloclasificaciónrating_counts
"Grandes actuaciones" Gatos (1998)1.7500002
$ 9.99 (2008)3.8333333
'Hellboy': Las semillas de la creación (2004)2.0000001
'Neath the Arizona Skies (1934)0.5000001
Ronda de medianoche (1986)2.2500002
Puede ver el título de la película, junto con la calificación promedio y el número de clasificaciones de la película.
Vamos a trazar un histograma para el número de calificaciones representadas por la columna "rating_counts" en el marco de datos anterior. Ejecuta el siguiente script:
import matplotlib.pyplot as plt  
import seaborn as sns  
sns.set_style('dark')  
%matplotlib inline

plt.figure(figsize=(8,6))  
plt.rcParams['patch.force_edgecolor'] = True  
ratings_mean_count['rating_counts'].hist(bins=50)  
Aquí está la salida del script anterior:
Histograma de calificaciones
Desde la salida, puedes ver que la mayoría de las películas han recibido menos de 50 calificaciones. Mientras que el número de películas que tienen más de 100 clasificaciones es muy bajo.
Ahora vamos a trazar un histograma para las calificaciones promedio. Aquí está el código para hacerlo:
plt.figure(figsize=(8,6))  
plt.rcParams['patch.force_edgecolor'] = True  
ratings_mean_count['rating'].hist(bins=50)  
La salida se ve así:
Promedio de calificaciones de histograma
Puede ver que los valores enteros tienen barras más altas que los valores flotantes, ya que la mayoría de los usuarios asignan una calificación como valor entero, es decir, 1, 2, 3, 4 o 5. Además, es evidente que los datos tienen una distribución normal débil con media de alrededor de 3.5. Hay algunos valores atípicos en los datos.
Anteriormente, dijimos que las películas con un mayor número de clasificaciones también suelen tener una alta calificación promedio, ya que normalmente una buena película es bien conocida y una gran cantidad de personas la ven una conocida y, por lo tanto, generalmente tiene una imagen más alta. clasificación. Veamos si este también es el caso con las películas en nuestro conjunto de datos. Vamos a trazar calificaciones promedio contra el número de calificaciones:
plt.figure(figsize=(8,6))  
plt.rcParams['patch.force_edgecolor'] = True  
sns.jointplot(x='rating', y='rating_counts', data=ratings_mean_count, alpha=0.4)  
La salida se ve así:
Calificaciones promedio vs número de calificaciones
La gráfica muestra que, en general, las películas con calificaciones promedio más altas en realidad tienen una mayor cantidad de calificaciones, en comparación con las películas que tienen calificaciones promedio más bajas.

Encontrar similitudes entre películas

Pasamos bastante tiempo visualizando y preprocesando nuestros datos. Ahora es el momento de encontrar la similitud entre las películas.
Usaremos la correlación entre las calificaciones de una película como la métrica de similitud. Para encontrar la correlación entre las calificaciones de la película, necesitamos crear una matriz donde cada columna es un nombre de película y cada fila contiene la clasificación asignada por un usuario específico a esa película. Tenga en cuenta que esta matriz tendrá muchos valores nulos, ya que cada usuario no califica cada película.
Para crear la matriz de títulos de películas y las calificaciones de usuarios correspondientes, ejecute el siguiente script:
user_movie_rating = movie_data.pivot_table(index='userId', columns='title', values='rating')  
user_movie_rating.head()  
título"Grandes actuaciones" Gatos (1998)$ 9.99 (1998)'Hellboy': Las semillas de la creación (2008)'Neath the Arizona Skies (1934)Ronda de medianoche (1986)'Salem's Lot (2004)'Hasta que estabas tú (1997)'burbs, el (1989)'noche Madre (1986)(500) Días de verano (2009)...Zulú (1964)Zulu (2013)
ID de usuario
1YayaYayaYayaYayaYayaYayaYayaYayaYayaYaya...YayaYaya
2YayaYayaYayaYayaYayaYayaYayaYayaYayaYaya...YayaYaya
3YayaYayaYayaYayaYayaYayaYayaYayaYayaYaya...YayaYaya
4YayaYayaYayaYayaYayaYayaYayaYayaYayaYaya...YayaYaya
5YayaYayaYayaYayaYayaYayaYayaYayaYayaYaya...YayaYaya
Sabemos que cada columna contiene todas las calificaciones de los usuarios para una película en particular. Encontremos todas las calificaciones de los usuarios para la película "Forrest Gump (1994)" y encontremos las películas similares. Elegimos esta película porque tiene la mayor cantidad de clasificaciones y queremos encontrar la correlación entre las películas que tienen una mayor cantidad de clasificaciones.
Para encontrar las calificaciones de los usuarios de "Forrest Gump (1994)", ejecute el siguiente script:
forrest_gump_ratings = user_movie_rating['Forrest Gump (1994)']  
El script anterior devolverá una serie de Pandas. Vamos a ver cómo se ve.
forrest_gump_ratings.head()  
userId  
1    NaN  
2    3.0  
3    5.0  
4    5.0  
5    4.0  
Name: Forrest Gump (1994), dtype: float64  
Ahora recuperemos todas las películas que son similares a "Forrest Gump (1994)". Podemos encontrar la correlación entre las calificaciones de los usuarios para "Forest Gump (1994)" y todas las demás películas que usan la corrwith()función como se muestra a continuación:
movies_like_forest_gump = user_movie_rating.corrwith(forrest_gump_ratings)

corr_forrest_gump = pd.DataFrame(movies_like_forest_gump, columns=['Correlation'])  
corr_forrest_gump.dropna(inplace=True)  
corr_forrest_gump.head()  
En el guión anterior, primero recuperamos la lista de todas las películas relacionadas con "Forrest Gump (1994)" junto con su valor de correlación, usando la corrwith()función. A continuación, creamos un marco de datos que contiene el título de la película y las columnas de correlación. Luego eliminamos todos los valores de NA del marco de datos y mostramos sus primeras 5 filas usando la headfunción.
La salida se ve así:
títuloCorrelación
$ 9.99 (2008)1.000000
'burbs, el (1989)0.044946
(500) Días de verano (2009)0.624458
* pilas no incluidas (1987)0.603023
... Y la justicia para todos (1979)0.173422
Ordenemos las películas en orden descendente de correlación para ver películas altamente correlacionadas en la parte superior. Ejecuta el siguiente script:
corr_forrest_gump.sort_values('Correlation', ascending=False).head(10)  
Aquí está la salida del script anterior:
títuloCorrelación
$ 9.99 (2008)1.0
Di que no es así (2001)1.0
Metrópolis (2001)1.0
See No Evil, Hear No Evil (1989)1.0
Hombres medios (2009)1.0
Agua para elefantes (2011)1.0
Mira, El (2012)1.0
La siguiente película de Cheech & Chong (1980)1.0
Forrest Gump (1994)1.0
Guerrero (2011)1.0
Desde la salida se puede ver que las películas que tienen una alta correlación con "Forrest Gump (1994)" no son muy conocidas. Esto muestra que la correlación por sí sola no es una buena métrica para la similitud porque puede haber un usuario que vio "Forest Gump (1994)" y solo otra película y calificó a ambas como 5.
Una solución a este problema es recuperar solo aquellas películas correlacionadas que tengan al menos más de 50 clasificaciones. Para hacerlo, agregaremos la rating_countscolumna del rating_mean_countmarco de datos a nuestro corr_forrest_gumpmarco de datos. Ejecute el siguiente script para hacerlo:
corr_forrest_gump = corr_forrest_gump.join(ratings_mean_count['rating_counts'])  
corr_forrest_gump.head()  
La salida se ve así:
títuloCorrelaciónrating_counts
$ 9.99 (2008)1.0000003
'burbs, el (1989)0.04494619
(500) Días de verano (2009)0.62445845
* pilas no incluidas (1987)0.6030237
... Y la justicia para todos (1979)0.17342213
Puedes ver que la película "$ 9.99", que tiene la correlación más alta, tiene solo tres calificaciones. Esto significa que solo tres usuarios dieron las mismas calificaciones a "Forest Gump (1994)", "$ 9.99". Sin embargo, podemos deducir que una película no puede ser declarada similar a otra basada en solo 3 calificaciones. Es por esto que agregamos la columna "rating_counts". Filtremos ahora las películas relacionadas con "Forest Gump (1994)", que tienen más de 50 clasificaciones. El siguiente código lo hará:
corr_forrest_gump[corr_forrest_gump ['rating_counts']>50].sort_values('Correlation', ascending=False).head()  
La salida del script, se ve así:
títuloCorrelaciónrating_counts
Forrest Gump (1994)1.000000341
Mi gran boda griega (2002)0.62624051
Mente Hermosa, A (2001)0.575922114
Pocos hombres buenos, A (1992)0.55520676
Million Dollar Baby (2004)0.545638sesenta y cinco
Ahora puede ver en la salida las películas que están altamente correlacionadas con "Forrest Gump (1994)". Las películas de la lista son algunas de las películas más famosas de Hollywood, y dado que "Forest Gump (1994)" también es una película muy famosa, existe una gran posibilidad de que estas películas estén correlacionadas.

Conclusión

En este artículo, estudiamos qué es un sistema de recomendación y cómo podemos crearlo en Python utilizando solo la biblioteca Pandas. Es importante mencionar que el sistema de recomendación que creamos es muy simple. Los sistemas de recomendación de la vida real utilizan algoritmos muy complejos y se analizarán en un artículo posterior.
Si desea obtener más información sobre los sistemas de recomendación, le sugiero que consulte los libros Sistemas prácticos de recomendación y Sistemas de recomendación: El libro de texto . Abordan mucho más este tema y cubren métodos más complejos y precisos de lo que hicimos en este artículo.

No hay comentarios.:

Publicar un comentario

Dejanos tu comentario para seguir mejorando!

outbrain

Páginas