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 datosyelp_review.json
: metadatos de las calificaciones por empresayelp_user.json
: metadatos del perfil de usuario por empresayelp_checkin.json
: metadatos de facturación online por empresayelp_tip.json
: metadatos de consejos por empresayelp_photo.json
: metadatos de fotos por empresaNota: 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!
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
Importe Pandas como pd
e importe todos los datasets como se indicó anteriormente
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!)
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).
¿Cuántos negocios diferentes hay en el conjunto de datos? ¿Cuáles son las diferentes características/features/columnas en el DataFrame reviews
?
¿Cuál es el rango de valores para las features del DataFrame users
? Nota: puedes usar el metodo .describe()
para hacer esto
¿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']
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
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?
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
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.
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 0
s. 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()
.
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?
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
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
.
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
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!
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_train
como 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?
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
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?
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
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()
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?
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.
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)
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'])
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?
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!!