Saltar al contenido principal

Tutorial de Kaggle: EDA e inteligencia artificial

En este tutorial de Kaggle, aprenderás a abordar y crear modelos de aprendizaje supervisado con ayuda del análisis exploratorio de datos (EDA) usando los datos del Titanic.
· 10 min leer

Explora con IA

A comienzos de este mes hice una sesión de Facebook Live Code Along en la que yo (y todas las personas que se unieron al código en directo) construimos varios algoritmos, cada vez más complejos, para predecir si un pasajero del Titanic sobrevivió o no, a partir de datos como la tarifa que pagó, el puerto de embarque o su edad.

En esta publicación repasaremos parte de lo que vimos en esa sesión. Si quieres volver a verla o seguir esta guía junto con el vídeo, puedes verlo aquí:

En concreto, quizá recuerdes que construimos modelos de aprendizaje supervisado.

El aprendizaje supervisado es la rama del Machine Learning (ML) que se centra en predecir etiquetas, como "Survived" o "Not". Estos modelos aprenden a partir de datos etiquetados —es decir, datos que incluyen si un pasajero sobrevivió (lo que llamamos "entrenamiento del modelo")— y luego predicen sobre datos sin etiquetar.

En Kaggle, una plataforma de competiciones de modelización predictiva y analítica, a estos conjuntos se les llama train y test porque

  • quieres construir un modelo que aprenda patrones en el conjunto de entrenamiento, y
  • después usar el modelo para predecir en el conjunto de test.

Kaggle te devuelve el porcentaje de aciertos: esto es la accuracy o precisión de tu modelo.

Cómo empezar con aprendizaje supervisado

Como ya sabrás, un buen enfoque para el aprendizaje supervisado es el siguiente:

  • Hacer un análisis exploratorio de datos (EDA) sobre tu conjunto de datos;
  • Construir un modelo rápido, un modelo base o de referencia, que te sirva para comparar con los modelos que crearás después;
  • Iterar el proceso: volverás a hacer EDA y construirás otro modelo;
  • Ingeniería de características: tomar las variables que ya tienes y combinarlas o extraer más información de ellas para llegar, por último, a
  • conseguir un modelo que rinda mejor.

En esta sesión de code along, hiciste (o harás) todos estos pasos.

Nota: también tenemos cursos para que te pongas en marcha con machine learning para el dataset del Titanic en Python y R.

Importa tus datos y échales un vistazo

El primer paso siempre es importar los datos para revisar rápidamente con qué vas a trabajar. En este caso, importarás el paquete pandas y usarás la función read_csv() para leer los datos:

Nota: en los bloques de código de abajo ya se han importado otros paquetes y módulos como matplotlib, sklearn y seaborn. Más adelante los usarás en mayor profundidad para visualización (estadística) de datos y para machine learning.

También usas el comando mágico de IPython %matplotlib inline para que las gráficas aparezcan embebidas en el notebook. Además, añades sns.set() para aplicar el estilo base de Seaborn a las visualizaciones:

# Import modules
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn import tree
from sklearn.metrics import accuracy_score

# Figures inline and set visualization style
%matplotlib inline
sns.set()

Sin más, vamos a importar los datos y dar el primer paso para examinarlos:

# Import test and train datasets
df_train = pd.read_csv('../data/train.csv')
df_test = pd.read_csv('../data/test.csv')

# View first lines of training data
df_train.head(n=4)
 PassengerIdSurvivedPclassNameSexAgeSibSpParchTicketFareCabinEmbarked
0103Braund, Mr. Owen Harrismale22.010A/5 211717.2500NaNS
1211Cumings, Mrs. John Bradley (Florence Briggs Th...female38.010PC 1759971.2833C85C
2313Heikkinen, Miss. Lainafemale26.000STON/O2. 31012827.9250NaNS
3411Futrelle, Mrs. Jacques Heath (Lily May Peel)female35.01011380353.1000C123S

Si quieres ver qué significa cada una de estas variables, consulta la documentación de datos de Kaggle aquí.

Antes de seguir, conviene tener claras estas definiciones:

  • La variable objetivo es la que intentas predecir;
  • El resto de variables se conocen como "features" (o "variables predictoras": las que usas para predecir la variable objetivo).

Con esto en mente, puedes seguir explorando tus datos con, por ejemplo, la función head(), que te muestra las primeras cinco filas del conjunto:

# View first lines of test data
df_test.head()
 PassengerIdPclassNameSexAgeSibSpParchTicketFareCabinEmbarked
08923Kelly, Mr. Jamesmale34.5003309117.8292NaNQ
18933Wilkes, Mrs. James (Ellen Needs)female47.0103632727.0000NaNS
28942Myles, Mr. Thomas Francismale62.0002402769.6875NaNQ
38953Wirz, Mr. Albertmale27.0003151548.6625NaNS
48963Hirvonen, Mrs. Alexander (Helga E Lindqvist)female22.011310129812.2875NaNS

Fíjate en que el DataFrame df_test no tiene la columna 'Survived' porque justo eso es lo que vas a predecir.

  • También puedes usar el método .info() del DataFrame para ver tipos de datos, valores ausentes y más (de df_train).
df_train.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 891 entries, 0 to 890
Data columns (total 12 columns):
PassengerId    891 non-null int64
Survived       891 non-null int64
Pclass         891 non-null int64
Name           891 non-null object
Sex            891 non-null object
Age            714 non-null float64
SibSp          891 non-null int64
Parch          891 non-null int64
Ticket         891 non-null object
Fare           891 non-null float64
Cabin          204 non-null object
Embarked       889 non-null object
dtypes: float64(2), int64(5), object(5)
memory usage: 83.6+ KB

En este caso, ves que solo hay 714 valores no nulos para la columna "Age" en un DataFrame con 891 filas. Esto significa que hay 177 valores nulos o ausentes.

  • Usa también el método .describe() del DataFrame para ver estadísticas descriptivas de las columnas numéricas (de df_train).
df_train.describe()
 PassengerIdSurvivedPclassAgeSibSpParchFare
count891.000000891.000000891.000000714.000000891.000000891.000000891.000000
mean446.0000000.3838382.30864229.6991180.5230080.38159432.204208
std257.3538420.4865920.83607114.5264971.1027430.80605749.693429
min1.0000000.0000001.0000000.4200000.0000000.0000000.000000
25%223.5000000.0000002.00000020.1250000.0000000.0000007.910400
50%446.0000000.0000003.00000028.0000000.0000000.00000014.454200
75%668.5000001.0000003.00000038.0000001.0000000.00000031.000000
max891.0000001.0000003.00000080.0000008.0000006.000000512.329200

EDA visual y tu primer modelo

Ahora que ya te haces una idea del aspecto de los datos y has visto algunas estadísticas, es momento de visualizarlos con ayuda del paquete seaborn:

  • Por ejemplo, usa seaborn para crear un gráfico de barras de la variable de supervivencia del Titanic, que es tu variable objetivo.
sns.countplot(x='Survived', data=df_train);

bar chart

Conclusión: en el conjunto de entrenamiento, sobrevivió menos gente de la que no sobrevivió. Construyamos entonces un primer modelo que prediga que nadie sobrevivió.

Sabemos que es un mal modelo, porque hubo supervivientes. Pero nos da una referencia: cualquier modelo que construyamos después debe hacerlo mejor.

Puedes hacerlo siguiendo estos pasos:

  • Crear una columna 'Survived' en df_test que codifique "no sobrevivió" para todas las filas;
  • Guardar las columnas 'PassengerId' y 'Survived' de df_test en un .csv y enviarlo a Kaggle.
df_test['Survived'] = 0
df_test[['PassengerId', 'Survived']].to_csv('data/predictions/no_survivors.csv', index=False)

¿Qué precisión te dio esto? La accuracy en Kaggle es 62.7.

kaggle

¡No está nada mal!

¡Nota importante! También querrás usar métricas distintas a la accuracy.

EDA sobre variables predictoras

Ahora que tienes un modelo rápido, toca iterar: hagamos más análisis exploratorio y pronto construiremos otro modelo.

  • Puedes usar seaborn para crear un gráfico de barras de la variable 'Sex' del conjunto del Titanic (de df_train).
sns.countplot(x='Sex', data=df_train);

bar plot

  • Además, usa seaborn para crear gráficos de barras de 'Survived' segmentados (facetados) por 'Sex'.
sns.factorplot(x='Survived', col='Sex', kind='count', data=df_train);

bar plot

Conclusión: las mujeres tenían más probabilidades de sobrevivir que los hombres.

  • Con esta idea, puedes usar pandas para ver cuántas mujeres y cuántos hombres sobrevivieron:
df_train.groupby(['Sex']).Survived.sum()
Sex
female    233
male      109
Name: Survived, dtype: int64
  • Usa pandas para calcular la proporción de mujeres que sobrevivieron y la de hombres:
print(df_train[df_train.Sex == 'female'].Survived.sum()/df_train[df_train.Sex == 'female'].Survived.count())
print(df_train[df_train.Sex == 'male'].Survived.sum()/df_train[df_train.Sex == 'male'].Survived.count())
0.742038216561
0.188908145581

El 74% de las mujeres sobrevivieron, frente al 19% de los hombres.

Ahora construyamos un segundo modelo y predigamos que todas las mujeres sobrevivieron y todos los hombres no. De nuevo, es un modelo irreal, pero nos da una referencia con la que comparar futuros modelos.

  • Crea una columna 'Survived' en df_test que codifique la predicción anterior.
  • Guarda las columnas 'PassengerId' y 'Survived' de df_test en un .csv y envíalo a Kaggle.
df_test['Survived'] = df_test.Sex == 'female'
df_test['Survived'] = df_test.Survived.apply(lambda x: int(x))
df_test.head()
 PassengerIdPclassNameSexAgeSibSpParchTicketFareCabinEmbarkedSurvived
08923Kelly, Mr. Jamesmale34.5003309117.8292NaNQ0
18933Wilkes, Mrs. James (Ellen Needs)female47.0103632727.0000NaNS1
28942Myles, Mr. Thomas Francismale62.0002402769.6875NaNQ0
38953Wirz, Mr. Albertmale27.0003151548.6625NaNS0
48963Hirvonen, Mrs. Alexander (Helga E Lindqvist)female22.011310129812.2875NaNS1
df_test[['PassengerId', 'Survived']].to_csv('../data/predictions/women_survive.csv', index=False)

Y ahora, ¿qué precisión te dio este modelo al enviarlo a Kaggle?

La accuracy en Kaggle es del 76.6%:

kaggle

¡Con este envío subiste unas 2.000 posiciones en el ranking! Además, has mejorado tu puntuación, así que buen trabajo.

¡Sigue explorando tus datos!

  • Usa seaborn para crear gráficos de barras de 'Survived' segmentados por 'Pclass'.
sns.factorplot(x='Survived', col='Pclass', kind='count', data=df_train);

bar plot

Conclusión: los pasajeros de primera clase tenían más probabilidades de sobrevivir. En cambio, quienes viajaban en tercera clase tenían menos probabilidades.

  • Usa seaborn para crear gráficos de barras de 'Survived' segmentados por 'Embarked'.
sns.factorplot(x='Survived', col='Embarked', kind='count', data=df_train);

bar plot

Conclusión: los pasajeros que embarcaron en Southampton tenían menos probabilidades de sobrevivir.

EDA con variables numéricas

  • Usa seaborn para dibujar un histograma de la columna 'Fare' de df_train.
sns.distplot(df_train.Fare, kde=False);

histogram

Conclusión: la mayoría de los pasajeros pagaron menos de 100 por viajar en el Titanic.

  • Usa un método de pandas para representar la columna 'Fare' para cada valor de 'Survived' en la misma gráfica.
df_train.groupby('Survived').Fare.hist(alpha=0.6);

bar plot

Conclusión: parece que quienes pagaron más tuvieron mayor probabilidad de sobrevivir.

  • Usa seaborn para dibujar un histograma de la columna 'Age' de df_train. Antes tendrás que eliminar los valores nulos.
df_train_drop = df_train.dropna()
sns.distplot(df_train_drop.Age, kde=False);

histogram

  • Dibuja un strip plot y un swarm plot de 'Fare' con 'Survived' en el eje X.
sns.stripplot(x='Survived', y='Fare', data=df_train, alpha=0.3, jitter=True);

strip plot

sns.swarmplot(x='Survived', y='Fare', data=df_train);

swarm plot

Conclusión: la tarifa parece estar claramente correlacionada con la supervivencia a bordo del Titanic.

  • Usa el método .describe() del DataFrame para consultar estadísticas descriptivas de 'Fare' en función de 'Survived'.
df_train.groupby('Survived').Fare.describe()
 countmeanstdmin25%50%75%max
Survived        
0549.022.11788731.3882070.07.854210.526.0263.0000
1342.048.39540866.5969980.012.475026.057.0512.3292
  • Usa seaborn para crear un diagrama de dispersión de 'Age' frente a 'Fare', coloreado por 'Survived'.
sns.lmplot(x='Age', y='Fare', hue='Survived', data=df_train, fit_reg=False, scatter_kws={'alpha':0.5});

scatter plot

Conclusión: parece que quienes sobrevivieron o bien pagaron bastante por su billete o bien eran jóvenes.

  • Usa seaborn para crear un pairplot de df_train coloreado por 'Survived'. Un pairplot es una forma estupenda de mostrar en una sola cuadrícula gran parte de lo que ya has descubierto.
sns.pairplot(df_train_drop, hue='Survived');

plots

De EDA a modelo de machine learning

En este tutorial, has conseguido:

  • cargar los datos y echarles un primer vistazo,
  • explorar visualmente la variable objetivo y hacer tus primeras predicciones,
  • explorar visualmente algunas variables predictoras y hacer más predicciones que mejoran gracias al EDA,
  • y hacer un EDA en profundidad de variables categóricas y numéricas.

En la próxima publicación, te dedicarás a construir modelos de Machine Learning basados en lo que has aprendido aquí con el EDA. Lo haremos en el siguiente post de este proyecto (previsto para el 27 de diciembre).

Temas

Relacionado