Creación de un sistema de recomendación sencillo en Python con Pandas

C

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 como “Comprados juntos con frecuencia”? Pueden parecer opciones relativamente simples, pero detrás de escena, se ejecuta un algoritmo estadístico complejo para predecir estas recomendaciones. Estos 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 emplea un algoritmo estadístico que busca predecir las calificaciones de los usuarios para una entidad en particular, basándose en la similitud entre las entidades o entre los usuarios que calificaron previamente esas entidades. La intuición es que es probable que tipos similares de usuarios 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 forma u otra. Puede encontrarlos en cualquier lugar, desde Amazon (recomendaciones de productos) hasta YouTube (recomendaciones de videos) hasta 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 crear sistemas de recomendación: filtrado basado en contenido y filtrado colaborativo:

Filtrado basado en contenido

En el filtrado basado en contenido, la similitud entre diferentes productos se calcula sobre la base de los atributos de los productos. Por ejemplo, en un sistema de recomendación de películas basado 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, hay muchas posibilidades de que también le guste el producto Y.

Tomemos el ejemplo de un sistema de recomendación de películas. Suponga que un gran número de usuarios ha asignado las mismas calificaciones a las películas X e Y. Llega un nuevo usuario que ha asignado la misma calificación a la película X pero que aún no ha visto la película Y. El sistema de filtrado colaborativo le recomendará la película Y.

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

En esta sección, desarrollaremos un sistema de recomendación de películas muy simple en Python que usa la correlación entre las calificaciones 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 MovieLens Dataset. 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 películas real y contiene 100000 clasificaciones para 9000 películas de 700 usuarios.

Una vez que descomprima el archivo descargado, verá los archivos “links.csv”, “movies.csv”, “ratings.csv” y “tags.csv”, junto con el documento “README”. En este artículo, usaremos los archivos “movies.csv” y “ratings.csv”.

Para los scripts de este artículo, la carpeta “ml-latest-small” descomprimida se ha colocado dentro de la carpeta “Conjuntos de datos” en la unidad “E”.

Visualización y preprocesamiento de datos

El primer paso en cada problema de ciencia de datos es visualizar y preprocesar los datos. Haremos lo mismo, así que primero importemos el archivo “ratings.csv” y veamos qué contiene. Ejecute el siguiente script:

import numpy as np
import pandas as pd

ratings_data = pd.read_csv("E:Datasetsml-latest-small\ratings.csv")
ratings_data.head()

En el script anterior usamos el read_csv()método de la biblioteca 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í:

userId
movieId
calificación
marca de tiempo

01312.51260759144
1110293.01260759179
2110613.01260759182
3111292.01260759185
4111724.01260759205

Puede ver en el resultado que el archivo “ratings.csv” contiene los atributos userId, movieId, ratings y timestamp. Cada fila del 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 dejada por 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 los ID de las películas pero no sus títulos. Necesitaremos nombres de películas para las películas que recomendamos. Los nombres de las películas se almacenan en el archivo “movies.csv”. Importemos el archivo y veamos los datos que contiene. Ejecute el siguiente script:

movie_names = pd.read_csv("E:Datasetsml-latest-small\movies.csv")
movie_names.head()

La salida se ve así:

géneros de
títulos de movieId

01Toy Story (1995)Aventura | Animación | Infantil | Comedia | Fantasía
12Jumanji (1995)Aventura | Niños | Fantasía
23Viejos gruñones (1995)Comedia | Romance
34Esperando para 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 “movie_names”. Para obtener nuestra información deseada en un solo marco de datos, podemos fusionar 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 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í:

userId
movieId
clasificación
marca de tiempo géneros de
título

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 userId, título y calificació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 usando el head()método. Mira el siguiente guión:

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

Puede ver que las calificaciones promedio no están ordenadas. Ordenemos 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, existe un problema. Una película puede llegar a la parte superior 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 parte de un gran número de usuarios.

Tracemos ahora la cantidad total de calificaciones de 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 respalda 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. Creemos un nuevo marco de datos que contenga ambos atributos.

Ejecute el siguiente script para crear un 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 de 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í:

titleratingrating_counts

Gatos “Grandes actuaciones” (1998)1.7500002
$9.99 (2008)3.8333333
‘Hellboy’: Las semillas de la creación (2004)2.0000001
Bajo los cielos de Arizona (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 calificaciones de la película.

Tracemos un histograma para el número de calificaciones representadas por la columna “rating_counts” en el marco de datos anterior. Ejecute 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á el resultado del script anterior:

En la salida, puede ver que la mayoría de las películas han recibido menos de 50 calificaciones. Mientras que la cantidad de películas que tienen más de 100 calificaciones es muy baja.

Ahora trazaremos un histograma para 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í:

Puede ver que los valores enteros tienen barras más altas que los valores flotantes ya que la mayoría de los usuarios asignan 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 el 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 calificaciones generalmente también tienen una calificación promedio alta, ya que una buena película normalmente es conocida y una película conocida es vista por una gran cantidad de personas y, por lo tanto, generalmente tiene una calificación más alta. clasificación. Veamos si este también es el caso de las películas en nuestro conjunto de datos. Trazaremos las 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í:

El gráfico muestra que, en general, las películas con calificaciones promedio más altas en realidad tienen un mayor número de calificaciones, en comparación con las películas que tienen calificaciones promedio más bajas.

Encontrar similitudes entre películas

Dedicamos bastante tiempo a visualizar y preprocesar nuestros datos. Ahora es el momento de encontrar la similitud entre películas.

Usaremos la correlación entre las calificaciones de una película como 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 calificación asignada por un usuario específico a esa película. Tenga en cuenta que esta matriz tendrá muchos valores nulos ya que cada película no es calificada por todos los usuarios.

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 “Great Performances” Cats (1998) $ 9.99 (1998) ‘Hellboy’: The Seeds of Creation (2008) ‘Neath the Arizona Skies (1934)’ Round Midnight (1986) ‘Salem’s Lot (2004)’ Til There Was You ( 1997) ‘burbs, The (1989)’ night Mother (1986) (500) Days of Summer (2009) … Zulu (1964) Zulu (2013) userId

1YayaYayaYayaYayaYayaYayaYayaYayaYayaYayaYayaYaya
2YayaYayaYayaYayaYayaYayaYayaYayaYayaYayaYayaYaya
3YayaYayaYayaYayaYayaYayaYayaYayaYayaYayaYayaYaya
4YayaYayaYayaYayaYayaYayaYayaYayaYayaYayaYayaYaya
5YayaYayaYayaYayaYayaYayaYayaYayaYayaYayaYayaYaya

Sabemos que cada columna contiene todas las calificaciones de los usuarios para una película en particular. Busquemos todas las calificaciones de los usuarios de la película “Forrest Gump (1994)” y busquemos películas similares. Elegimos esta película porque tiene el mayor número de calificaciones y queremos encontrar la correlación entre las películas que tienen un mayor número de calificaciones.

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. Veamos 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 de “Forest Gump (1994)” y todas las demás películas que utilizan la corrwith()función que 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í:

titleCorrelation

$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 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. Ejecute el siguiente script:

corr_forrest_gump.sort_values('Correlation', ascending=False).head(10)

Aquí está el resultado del script anterior:

titleCorrelation

$9.99 (2008)1.0
Di que no es así (2001)1.0
Metrópolis (2001)1.0
No ver el mal, no escuchar el mal (1989)1.0
Hombres intermedios (2009)1.0
Agua para elefantes (2011)1.0
Watch, The (2012)1.0
La próxima película de Cheech & Chong (1980)1.0
Forrest Gump (1994)1.0
Guerrero (2011)1.0

De la salida se puede ver que las películas que tienen 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 una película más y calificó ambas como 5.

Una solución a este problema es recuperar solo aquellas películas correlacionadas que tengan al menos más de 50 calificaciones. Para hacerlo, agregará 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í:

titleCorrelationrating_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 justicia para todos (1979)0.17342213

Puede ver que la película “$ 9.99”, que tiene la correlación más alta, tiene solo tres calificaciones. Esto significa que sólo tres usuarios dieron las mismas calificaciones a “Forest Gump (1994)”, “$ 9,99”. Sin embargo, podemos deducir que una película no se puede declarar similar a otra película basándonos en solo 3 calificaciones. Es por eso que agregamos la columna “rating_counts”. Filtremos ahora películas correlacionadas con “Forest Gump (1994)”, que tienen más de 50 ratings. El siguiente código hará eso:

corr_forrest_gump[corr_forrest_gump ['rating_counts']>50].sort_values('Correlation', ascending=False).head()

La salida del script se ve así:

titleCorrelationrating_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.54563865

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 alta probabilidad 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 usando 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 discutirá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 . Ellos profundizan mucho más en este tema y cubren métodos más complejos y precisos que los que hicimos en este artículo.

 

About the author

Ramiro de la Vega

Bienvenido a Pharos.sh

Soy Ramiro de la Vega, Estadounidense con raíces Españolas. Empecé a programar hace casi 20 años cuando era muy jovencito.

Espero que en mi web encuentres la inspiración y ayuda que necesitas para adentrarte en el fantástico mundo de la programación y conseguir tus objetivos por difíciles que sean.

Add comment

Sobre mi

Últimos Post

Etiquetas

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con tus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, aceptas el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Más información
Privacidad