Reto Predicción De Estrellas De Un Nuevo Restaurante

La industria de los restaurantes esta más dura que nunca, con críticas en Internet desde el primer día de la apertura de un restaurante. Pero como amante de la comida, usted y un amigo deciden entrar en la industria y abrir su propio restaurante. Dado que el éxito de un restaurante está altamente correlacionado con su reputación, usted quiere asegurarse de que tenga las mejores críticas en el sitio de rating y reseñas de restaurantes más consultado: Yelp!

Aunque usted sabe que su comida será deliciosa, cree que hay otros factores que influyen en la calificación de Yelp y que, en última instancia, determinarán el éxito de su negocio. Con un conjunto de datos de diferentes características del restaurante y sus estrellas de Yelp, usted decide usar un modelo de Regresión Lineal Múltiple para investigar qué factores afectan más la reseña de un restaurante y predecir el número de estrellas en Yelp para su restaurante.

En este proyecto trabajaremos con un conjunto de datos reales proporcionados por Yelp. Hemos proporcionado seis archivos, que se enumeran a continuación con una breve descripción:

Nota: todos los archivos los puede encontrar aqui. Es una cantidad grande de datos (aprox. 200.000 datos). La idea de este reto es que puedas simular un ambiente de proyecto real.

  • yelp_business.json: datos del establecimiento relativos a la ubicación y los atributos de todas las empresas en el conjunto de datos
  • yelp_review.json: metadatos de las calificaciones por empresa
  • yelp_user.json: metadatos del perfil de usuario por empresa
  • yelp_checkin.json: metadatos de facturación online por empresa
  • yelp_tip.json: metadatos de consejos por empresa
  • yelp_photo.json: metadatos de fotos por empresa

Nota: como puede ver los datos estan en .json, un formato diferente a .csv, pero no te preocupes, es lo mismo al momento de importarlos y trabajarlos, aqui te vamos a ir enseñando como, sigue adelante!

Cargar los datos y echar un vistazo

Para obtener una mejor comprensión del conjunto de datos podemos usar Pandas para explorar los datos en forma de DataFrame. En el siguiente bloque de código debes importar Pandas. El método read_json() lee los datos de un archivo json en un DataFrame, como se muestra a continuación:

df = pd.read_json('file_name.json', lines=True)

Cargue los datos de cada uno de los archivos json con las siguientes convenciones para fijar nombres:

yelp_business.json en un DataFrame llamado business

yelp_review.json en un DataFrame llamado reviews

yelp_user.json en un DataFrame nombrando users

yelp_checkin.json en un DataFrame llamado checkins

yelp_tip.json en un DataFrame llamado tips

yelp_photo.json en un DataFrame llamado photos

La importación de esos datos puede tardar de 10 a 20 segundos en ejecutarse dependiendo de su computadora, pero no se preocupe, una vez cargados, ¡ya está listo para empezar!

Empieza instalando Pandas en la siguiente celda

In [ ]:
 

Importe Pandas como pd e importe todos los datasets como se indicó anteriormente

In [ ]:
 

Para poder ver más claramente la información en nuestro DataFrame, podemos ajustar el número de columnas mostradas (max_columns) y el número de caracteres mostrados en una columna (max_colwidth) con el siguiente código:

pd.options.display.max_columns = number_of_columns_to_display
pd.options.display.max_colwidth = number_of_characters_to_display

Ajuste max_columns a 60 y max_colwidth a 500. Estamos trabajando con algunos datos GRANDES aquí! (bienvenido al Big Data!)

In [ ]:
 

Inspeccione las primeras cinco filas de cada DataFrame usando el método .head() para obtener una visión general de los datos (asegúrese de revisar cada DataFrame en una celda separada para poder verlo correctamente).

In [ ]:
 
In [ ]:
 
In [ ]:
 
In [ ]:
 
In [ ]:
 
In [ ]:
 

¿Cuántos negocios diferentes hay en el conjunto de datos? ¿Cuáles son las diferentes características/features/columnas en el DataFrame reviews?

In [ ]:
 

¿Cuál es el rango de valores para las features del DataFrame users? Nota: puedes usar el metodo .describe() para hacer esto

In [ ]:
 

¿Cuál es la calificación en Yelp, o estrellas, del establecimiento con business_id=Apn5Q_b6Nz61Tq4XzPdf9A Utilice la indexación booleana de Pandas para encontrar la calificación de Yelp, usando la sintaxis de abajo:

df[df['column_we_know'] == 'value_we_know']['column_we_want']
In [ ]:
 

Fusionar los datos

Como estamos trabajando con datos de varios archivos, necesitamos combinar los datos en un solo DataFrame que nos permita analizar las diferentes características con respecto a nuestra variable objetivo, la columna starts de Yelp.

Podemos hacer esto fusionando los múltiples DataFrames que tenemos juntos, uniéndolos en las columnas que tienen en común. En nuestro caso, esta columna de identificación única es el business_id.

Dados nuestros seis DataFrames, necesitaremos realizar 5 fusiones para combinar todos los datos en un solo DataFrame. Fusione primero business y reviews con un left join y asignelo a una variable llamada df

In [ ]:
 

Combine cada uno de los otros 4 DataFrames en nuestro nuevo DataFrame df para combinar todos los datos juntos. Asegúrese de que df es el DataFrame izquierdo en cada fusión y que hace left join en cada uno de ellos ya que no todos los DataFrame incluyen todos los negocios en el conjunto de datos (de esta manera no perderemos ningún dato durante las fusiones). Una vez combinada, imprima las columnas de df. ¿Qué características/features/columnas tiene este nuevo DataFrame?

In [ ]:
 
In [ ]:
 
In [ ]:
 
In [ ]:
 

Limpieza de los datos

Nos estamos acercando mucho a la parte del análisis divertido! Sólo tenemos que limpiar un poco nuestros datos para que podamos centrarnos en las características que podrían tener poder predictivo para determinar la calificación de Yelp de un establecimiento.

En un modelo de Regresión Lineal, nuestras características serán idealmente variables continuas que afectan a nuestra variable dependiente, o sea el rating de Yelp. Para este proyecto también se trabajará con algunas características que son binarias, en la escala [0,1]. Con esta información, podemos eliminar cualquier columna en el conjunto de datos que no sea continua o binaria, y sobre la que no queramos hacer predicciones. La siguiente celda contiene una lista de estas características innecesarias. Sáquelos de df con la sintaxis drop de Pandas, básicamente necesitamos remover las siguientes columnas:

'address',
'attributes',
'business_id',
'categories',
'city',
'hours',
'is_open',
'latitude',
'longitude',
'name',
'neighborhood',
'postal_code',
'state',
'time'

Vaya adelante y haga la operación mencionada en la siguiente celda

In [ ]:
 
In [ ]:
 
In [ ]:
 

Ahora sólo tenemos que comprobar nuestros datos para asegurarnos de que no nos faltan valores, o NaNs, lo que impedirá que el modelo de Regresión Lineal funcione correctamente. Para ello podemos utilizar la sentencia df.isna().any(). Esto comprobará todas nuestras columnas y devolverá True si hay valores faltantes o NaNs, o False si no hay valores faltantes. Compruebe si a df le falta algún valor.

In [ ]:
 

Como puede ver, hay algunas columnas con valores que faltan. Dado que nuestro conjunto de datos no tiene información registrada para algunos negocios en estas columnas, asumiremos que las páginas de Yelp no muestran estas características. Por ejemplo, si hay un valor NaN para number_pics, significa que el negocio asociado no tenía ninguna imagen publicada en su página de Yelp. De esta manera podemos reemplazar todos nuestros NaNs con 0s. Para ello podemos utilizar el método .fillna().

Rellena los valores que faltan en df con 0. Después, confirme que los valores que faltan han sido rellenados con df.isna().any().

In [ ]:
 
In [ ]:
 
In [ ]:
 

Análisis exploratorio

Ahora que nuestros datos están todos juntos, investiguemos algunas de las diferentes características para ver qué podría correlacionarse más con nuestra variable dependiente, la calificacion de Yelp (llamada stars en nuestro DataFrame). Las características con las mejores correlaciones podrían ser las más útiles para nuestro modelo de Regresión Lineal!

Los DataFrames de Pandas tienen un método realmente útil, .corr(), que nos permite ver los coeficientes de correlación para cada par de nuestras diferentes características. Recuerde, una correlación de 0 indica que dos características no tienen relación lineal, un coeficiente de correlación de 1 indica que dos características tienen una relación lineal positiva perfecta, y un coeficiente de correlación de -1 indica que dos características tienen una relación lineal negativa perfecta.

llame .corr() sobre df. Verás que number_funny_votes tiene un coeficiente de correlación de 0.001320 con respecto a stars o rating de Yelp. Esta es una correlación muy débil. ¿Qué características se correlacionan mejor, tanto positiva como negativamente, con la clasificación Yelp?

In [ ]:
 

Para visualizar mejor estas relaciones, podemos graficar ciertas características contra nuestra variable dependiente, el rating de Yelp. importe Matplotlib. Podemos usar el método .scatter() de Matplotlib para graficar cómo son estas correlaciones (añada como tercer parametro al scatter lo siguiente alpha=0.1)

Grafique las tres características que más se correlacionan con las estrellas de Yelp (average_review_sentiment, average_review_length, average_review_age) contra stars.. Luego grafique una característica de baja correlación, como por ejemplo, number_funny_votes, contra stars.

Nota: que es average_review_sentiment?, average_review_sentiment es la puntuación media de todos los comentarios en la página Yelp de un negocio. Dicha puntuación, Yelp la calcula interamente utilizando la herramienta de análisis de sentimiento VADER. VADER utiliza un conjunto de palabras positivas y negativas, junto con reglas gramaticales codificadas, para estimar qué tan positiva o negativa es un comentario. Las puntuaciones van de -1, a +1, y una puntuación de 0 que indica un comentario neutral. Aunque no es perfecto, VADER hace un buen trabajo adivinando el sentimiento de los datos de texto! Es por ello que verás una alta correlación con stars

In [ ]:
 
In [ ]:
 
In [ ]:
 
In [ ]:
 

Selección de datos

Para poner nuestros datos en un modelo de Regresión Lineal, necesitamos separar nuestras características/features/columnas para modelar las estrellas de Yelp.

De nuestro análisis de correlación vimos que las tres características con las correlaciones más fuertes para las estrellas de Yelp son el average_review_sentiment, average_review_length, y average_review_age.

Ya que queremos profundizar un poco más que usar solo el average_review_sentiment, que comprensiblemente tiene una correlación muy alta con las estrellas de Yelp, elijamos crear nuestro primer modelo con average_review_length y average_review_age como características.

Cree una nueva columna en el DataFrame que contenga las columnas sobre las que queremos modelar y llamelo features con las columnas: average_review_length y average_review_age. Luego cree otro DataFrame llamado ratings que almacene el valor que queremos predecir, las estrellas de Yelp stars en df.

In [ ]:
 

Dividir los datos en conjuntos de entrenamiento y pruebas

Estamos casi listos para modelar! Pero primero, necesitamos dividir nuestros datos en un conjunto de entrenamiento y un conjunto de pruebas para poder evaluar qué tan bien funciona nuestro modelo.

Usaremos la función train_test_split de scikit-learn para hacer esta división. Esta función toma dos parámetros requeridos: los datos, o nuestras características, seguidos por nuestra variable dependiente, en nuestro caso las estrellas de Yelp. Ajuste el parámetro opcional test_size a 0,2. Finalmente, establezca el parámetro opcional random_state en 1. Esto hará que sus datos se dividan de la misma manera que los datos en nuestro código de solución. Asigne los valores a las siguientes variables: X_train, X_test, y_train, y_test

In [ ]:
 
In [ ]:
 

Crear y entrenar al modelo

Ahora que nuestros datos están divididos en conjuntos de entrenamiento y pruebas, ¡por fin podemos modelar! Importe LinearRegression desde el módulo linear_model de scikit-learn.

Cree un nuevo objeto LinearRegression llamado model. El método .fit() ajustará nuestro modelo de Regresión Lineal a nuestros datos de entrenamiento y calculará los coeficientes para nuestras características. Llame al método .fit() en el modelo con X_train y y_train como parámetros. De esta manera, nuestro modelo será entrenado en nuestros datos de entrenamiento!

In [ ]:
 

Evaluar y comprender el modelo

Ahora podemos evaluar nuestro modelo de varias maneras. La primera forma será usando el método .score(), que proporciona el valor R^2 para nuestro modelo. Recuerde, R^2 es el coeficiente de determinación, o una medida de cuánto de la varianza en nuestra variable dependiente, las estrellas de Yelp predichas, se explica por nuestras variables independientes, nuestros datos de características.

Los valores de R^2 van de 0 a 1, con 0 indicando que el modelo creado no se ajusta a nuestros datos en absoluto, y con 1 indicando que el modelo se ajusta perfectamente a nuestros datos de características.

Llame .score()en nuestro modelo con X_train y y_traincomo parámetros para calcular nuestra puntuación R^2. Luego llame de nuevo al score()en el modelo con X_test y y_test como parámetros para calcular R^2 para nuestros datos de prueba.

¿Qué dicen estos valores de R^2 sobre nuestro modelo? ¿Cree usted que estas características por sí solas son capaces de predecir eficazmente las estrellas de Yelp?

In [ ]:
 
In [ ]:
 

Después de tanto trabajo, por fin podemos echar un vistazo a los coeficientes de nuestras diferentes características!

El modelo tiene un atributo .coef_ que es una matriz de los coeficientes de característica determinados al ajustar nuestro modelo a los datos de entrenamiento. Para que sea más fácil ver qué característica corresponde a qué coeficiente, hemos proporcionado un código en la celda que une una lista de nuestras características con los coeficientes y las ordena en orden descendente desde la más predictiva a la menos predictiva.

sorted(list(zip(['average_review_length','average_review_age'],model.coef_)),key = lambda x: abs(x[1]),reverse=True)

Copiela y peguela en la siguiente celda

In [ ]:
 

Por último, podemos calcular las estrellas de Yelp previstas para nuestros datos de pruebas y compararlas con las estrellas de Yelp reales.

Nuestro modelo tiene un método .predict() que utiliza los coeficientes del modelo para calcular el valor de Yelp predicho. Llama a .predict() en X_test y asignar los valores a y_predicted.

Usa Matplotlib para graficar y_test vs y_predicted. Para un modelo de regresión lineal perfecto, esperaríamos ver los datos trazados a lo largo de la línea y = x, ¿Es éste el caso? Si no, ¿por qué no?

In [ ]:
 
In [ ]:
 
In [ ]:
 
In [ ]:
 

Definir diferentes subconjuntos de datos

Después de evaluar el primer modelo, puede ver que average_review_length y average_review_age por sí solas no son los mejores predictores para las estrellas de Yelp.

Vamos a hacer un poco más de modelado con diferentes subconjuntos de características y ver si podemos lograr un modelo más preciso!

En las celdas de abajo hemos proporcionado diferentes listas de subconjuntos de características con las que modelaremos y evaluaremos. ¿Qué otros subconjuntos de características le gustaría probar? ¿Por qué crees que esos conjuntos de características son más predictivos de las estrellas de Yelp que otros? Cree al menos un subconjunto adicional de características a partir de las cuales desea predecir las estrellas de Yelp. Copie y pegue los subconjuntos en la siguiente celda

# subset of only average review sentiment
sentiment = ['average_review_sentiment']

# subset of all features that have a response range [0,1]
binary_features = ['alcohol?','has_bike_parking','takes_credit_cards','good_for_kids','take_reservations','has_wifi']

# subset of all features that vary on a greater range than [0,1]
numeric_features = ['review_count','price_range','average_caption_length','number_pics','average_review_age','average_review_length','average_review_sentiment','number_funny_votes','number_cool_votes','number_useful_votes','average_tip_length','number_tips','average_number_friends','average_days_on_yelp','average_number_fans','average_review_count','average_number_years_elite','weekday_checkins','weekend_checkins']

# all features
all_features = binary_features + numeric_features
In [ ]:
 
In [ ]:
 

Otros modelos

Ahora que tenemos listas de diferentes subconjuntos de características, podemos crear nuevos modelos a partir de ellos. Para poder comparar más fácilmente el rendimiento de estos nuevos modelos, hemos creado una función para usted llamada model_these_features().

Esta función replica el proceso de construcción del modelo que acaba de completar con nuestro primer modelo! Tómese un tiempo para revisar cómo funciona, analizándola línea por línea. Rellene los comentarios vacíos con una explicación de la tarea que el código debajo está realizando.

Importe Numpy y copie y pegue la función en la siguiente celda

import numpy as np

# take a list of features to model as a parameter
def model_these_features(feature_list):

    # define ratings and features, with the features limited to our chosen subset of data
    ratings = df.loc[:,'stars']
    features = df.loc[:,feature_list]

    # perform train, test, split on the data
    X_train, X_test, y_train, y_test = train_test_split(features, ratings, test_size = 0.2, random_state = 1)

    # don't worry too much about these lines, just know that they allow the model to work when
    # we model on just one feature instead of multiple features. Trust us on this one :)
    if len(X_train.shape) < 2:
        X_train = np.array(X_train).reshape(-1,1)
        X_test = np.array(X_test).reshape(-1,1)

    # create and fit the model to the training data
    model = LinearRegression()
    model.fit(X_train,y_train)

    # print the train and test scores
    print('Train Score:', model.score(X_train,y_train))
    print('Test Score:', model.score(X_test,y_test))

    # print the model features and their corresponding coefficients, from most predictive to least predictive
    print(sorted(list(zip(feature_list,model.coef_)),key = lambda x: abs(x[1]),reverse=True))

    # calculate the predicted Yelp ratings from the test data
    y_predicted = model.predict(X_test)

    # plot the actual Yelp Ratings vs the predicted Yelp ratings for the test data
    plt.scatter(y_test,y_predicted)
    plt.xlabel('Yelp Rating')
    plt.ylabel('Predicted Yelp Rating')
    plt.ylim(1,5)
    plt.show()
In [ ]:
 
In [ ]:
 

Una vez que se sienta cómodo con los pasos de la función, ejecute modelos en los siguientes subconjuntos de datos utilizando model_these_features():

sentiment: sólo average_review_sentiment

binary_features: todas las características que tienen un rango de respuesta [0,1]

numeric_features: todas las características que varían en un rango mayor que [0,1]

all_features: todas las características

feature_subset: su propio subconjunto de características

¿Cómo afecta el cambio de los conjuntos de características al valor R^2 del modelo? ¿Qué características son más importantes para predecir las estrellas de Yelp en los diferentes modelos?

In [ ]:
 
In [ ]:
 
In [ ]:
 
In [ ]:
 

Debut de su nuevo restaurante - Pizzas y Pizzas

Ha cargado los datos, los ha limpiado, modelado y evaluado. Estás cansado, pero resplandeciente de orgullo después de todo el trabajo duro. Cierra los ojos y puedes ver claramente el día de apertura de Pizzas y Pizzas con una fila de personas en la puerta. Pero, ¿cuántas serán sus estrellas de Yelp? Usemos nuestro modelo para hacer una predicción.

Nuestro mejor modelo era el que utilizaba todas las carecteristicas o features!!, así que volveremos a trabajar con este modelo. En la celda de abajo imprima all_features para obtener un recordatorio de las características con las que estamos trabajando.

In [ ]:
 

Ejecute la celda de abajo para agarrar todas las características y volver a entrenar a nuestro modelo en ellas.

features = df.loc[:,all_features]
ratings = df.loc[:,'stars']
X_train, X_test, y_train, y_test = train_test_split(features, ratings, test_size = 0.2, random_state = 1)
model = LinearRegression()
model.fit(X_train,y_train)
In [ ]:
 

Para darle una perspectiva de los restaurantes que ya existen, hemos proporcionado los valores medios, mínimos y máximos para cada característica/feature/columna a continuación. ¿Será Pizzas y Pizzas otro restaurante promedio, o será un gigante de 5 estrellas entre las masas?

pd.DataFrame(list(zip(features.columns,features.describe().loc['mean'],features.describe().loc['min'],features.describe().loc['max'])),columns=['Feature','Mean','Min','Max'])
In [ ]:
 

Basado en sus planes para el restaurante, cómo espera que sus clientes califiquen en su página de Yelp para cada uno de los features? llene los espacios en blanco en la matriz NumPy a continuación con sus valores deseados.

El primer espacio en blanco corresponde a la característica en index=0 en el DataFrame de arriba, alcohol? y el último espacio en blanco corresponde a la característica en index=24, weekend_checkins. Asegúrese de introducir 0 o 1 para todas las características binarias, y si no está seguro de qué valor poner para una característica, seleccione la media en el DataFrame de arriba.

Guarde el array de numpy en una variable llamada pizzas_pizzas y recuerde hacerle un reshape(1, -1)

Después de ingresar los valores, ejecute la celda de predicción a continuación para recibir su calificación de Yelp! ¿Cómo va a ser el debut de Pizzas y Pizzas?

In [ ]:
 
In [ ]:
 
In [ ]:
 

Próximos pasos

Usted ha construido con éxito un modelo de regresión lineal que predice las estrellas de Yelp de un restaurante! Como has visto, puede ser bastante difícil predecir las estrellas como ésta incluso cuando tenemos una plétora de datos.

¿Qué otras preguntas le vienen a la mente cuando ve los datos que tenemos? ¿Qué ideas cree usted que podrían pronosticar de un tipo diferente de análisis? Aquí hay algunas ideas para reflexionar:

  • ¿Podemos predecir el tipo de cocina de un restaurante en función de los usuarios que la revisan?

  • ¿Qué restaurantes son similares entre sí en otros aspectos además del tipo de cocina?

  • ¿Existe un ambiente diferente en los restaurantes, y qué tipo de restaurantes se ajustan a estos conceptos?

  • ¿Cómo afecta el estatus de las redes sociales a la credibilidad y visibilidad de un restaurante?

A medida que avance en el campo de la ciencia de datos, podrá crear modelos que aborden estas preguntas y muchas más. Pero mientras tanto, felicitece, ha alcanzado un gran logro!!

In [ ]: