9/12/2018 01RegresionLogisticaConPython
Regresión logística con Python
En esta parte trabajaremos con el Conjunto de Datos Titanic de Kaggle
(https://www.kaggle.com/c/titanic). ¡Este es un conjunto de datos muy famoso y muy a menudo es
el primer paso de un estudiante en el aprendizaje automático!
Trataremos de predecir una clasificación: supervivencia o muerte. Comencemos nuestra
comprensión de la implementación de Regresión logística en Python para clasificación.
Usaremos una versión "semi-limpia" del conjunto de datos Titanic, si usa el conjunto de datos
alojado directamente en Kaggle, es posible que necesite realizar una limpieza adicional que no se
muestra en este notebook.
Importación de Librerias
Vamos a importar algunas de las librerias para comenzar!
In [2]: import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
Los datos
Comencemos leyendo el archivo titanic_train.csv en un dataframe de pandas.
In [3]: train = pd.read_csv('titanic_train.csv')
http://localhost:8888/notebooks/03RegresionLogistica/01RegresionLogisticaConPython.ipynb 1/17
9/12/2018 01RegresionLogisticaConPython
In [3]: train.head()
Out[3]: PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabi
Braund,
0 1 0 3 Mr. Owen male 22.0 1 0 A/5 21171 7.2500 Na
Harris
Cumings,
Mrs. John
Bradley
1 2 1 1 female 38.0 1 0 PC 17599 71.2833 C8
(Florence
Briggs
Th...
Heikkinen,
STON/O2.
2 3 1 3 Miss. female 26.0 0 0 7.9250 Na
3101282
Laina
Futrelle,
Mrs.
Jacques
3 4 1 1 female 35.0 1 0 113803 53.1000 C12
Heath
(Lily May
Peel)
Allen, Mr.
4 5 0 3 William male 35.0 0 0 373450 8.0500 Na
Henry
Análisis exploratorio de datos
Hagamos análisis de datos exploratorio, ¡Comenzaremos por verificar los datos que faltan!
Datos perdidos
¡Podemos usar Seaborn para crear un mapa de calor simple para ver dónde nos faltan datos!
http://localhost:8888/notebooks/03RegresionLogistica/01RegresionLogisticaConPython.ipynb 2/17
9/12/2018 01RegresionLogisticaConPython
In [6]: sns.heatmap(train.isnull(),yticklabels=False,cbar=False,cmap='viridis')
Out[6]: <matplotlib.axes._subplots.AxesSubplot at 0x205c3def940>
Aproximadamente el 20 por ciento de los datos Age falta. La proporción de datos Age faltantes es
probablemente lo suficientemente pequeña para un reemplazo razonable con alguna forma de
imputación. Al mirar la columna Cabin, parece que se está perdiendo demasiados datos para hacer
algo útil a un nivel básico. Probablemente lo eliminaremos más tarde o lo cambiemos a otra
característica como "Cabina Conocida: 1 or 0".
In [7]: sns.set_style('whitegrid')
sns.countplot(x='Survived',data=train,palette='RdBu_r')
Out[7]: <matplotlib.axes._subplots.AxesSubplot at 0x205c3f34550>
http://localhost:8888/notebooks/03RegresionLogistica/01RegresionLogisticaConPython.ipynb 3/17
9/12/2018 01RegresionLogisticaConPython
In [8]: sns.set_style('whitegrid')
sns.countplot(x='Survived',hue='Sex',data=train,palette='RdBu_r')
Out[8]: <matplotlib.axes._subplots.AxesSubplot at 0x205c3fa56d8>
In [9]: sns.set_style('whitegrid')
sns.countplot(x='Survived',hue='Pclass',data=train,palette='rainbow')
Out[9]: <matplotlib.axes._subplots.AxesSubplot at 0x205c4005b38>
http://localhost:8888/notebooks/03RegresionLogistica/01RegresionLogisticaConPython.ipynb 4/17
9/12/2018 01RegresionLogisticaConPython
In [10]: sns.distplot(train['Age'].dropna(),kde=False,color='darkred',bins=30)
C:\Users\Juan\Anaconda3\lib\site-packages\matplotlib\axes\_axes.py:6462: UserW
arning: The 'normed' kwarg is deprecated, and has been replaced by the 'densit
y' kwarg.
warnings.warn("The 'normed' kwarg is deprecated, and has been "
Out[10]: <matplotlib.axes._subplots.AxesSubplot at 0x205c4069ba8>
In [12]: train['Age'].hist(bins=30,color='darkred',alpha=0.7)
Out[12]: <matplotlib.axes._subplots.AxesSubplot at 0x205c41e9ac8>
http://localhost:8888/notebooks/03RegresionLogistica/01RegresionLogisticaConPython.ipynb 5/17
9/12/2018 01RegresionLogisticaConPython
In [13]: sns.countplot(x='SibSp',data=train)
Out[13]: <matplotlib.axes._subplots.AxesSubplot at 0x205c42f2d30>
In [15]: train['Fare'].hist(color='green',bins=40,figsize=(8,4))
Out[15]: <matplotlib.axes._subplots.AxesSubplot at 0x205c43ceb00>
Limpieza de datos
Queremos completar los datos de edad faltantes en lugar de simplemente eliminar las filas con
datos de edad faltantes. Una forma de hacerlo es rellenándolos con la edad promedio de todos los
pasajeros (imputación). Sin embargo, podemos ser más cuidadosos al respecto y verificar la edad
promedio por clase de pasajeros. Por ejemplo:
http://localhost:8888/notebooks/03RegresionLogistica/01RegresionLogisticaConPython.ipynb 6/17
9/12/2018 01RegresionLogisticaConPython
In [16]: plt.figure(figsize=(12, 7))
sns.boxplot(x='Pclass',y='Age',data=train,palette='winter')
Out[16]: <matplotlib.axes._subplots.AxesSubplot at 0x205c4350b70>
Podemos ver que los pasajeros más ricos en las clases superiores tienden a ser mayores, lo que
tiene sentido. Utilizaremos estos valores de edad promedio para imputar Age según Pclass.
In [17]: def imputar_edad(cols):
Age = cols[0]
Pclass = cols[1]
if pd.isnull(Age):
if Pclass == 1:
return 37
elif Pclass == 2:
return 29
else:
return 24
else:
return Age
¡Ahora apliquemos está función!
In [19]: train['Age'] = train[['Age','Pclass']].apply(imputar_edad,axis=1)
¡Ahora vamos a revisar el mapa de calor de nuevo!
http://localhost:8888/notebooks/03RegresionLogistica/01RegresionLogisticaConPython.ipynb 7/17
9/12/2018 01RegresionLogisticaConPython
In [20]: sns.heatmap(train.isnull(),yticklabels=False,cbar=False,cmap='viridis')
Out[20]: <matplotlib.axes._subplots.AxesSubplot at 0x205c4571400>
¡Estupendo! Avancemos y eliminemos la columna Cabin y la fila de Embarked que es NaN.
In [21]: train.drop('Cabin',axis=1,inplace=True)
In [22]: train.head()
Out[22]: PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Emb
Braund,
0 1 0 3 Mr. Owen male 22.0 1 0 A/5 21171 7.2500
Harris
Cumings,
Mrs. John
Bradley
1 2 1 1 female 38.0 1 0 PC 17599 71.2833
(Florence
Briggs
Th...
Heikkinen,
STON/O2.
2 3 1 3 Miss. female 26.0 0 0 7.9250
3101282
Laina
Futrelle,
Mrs.
Jacques
3 4 1 1 female 35.0 1 0 113803 53.1000
Heath
(Lily May
Peel)
Allen, Mr.
4 5 0 3 William male 35.0 0 0 373450 8.0500
Henry
In [23]: train.dropna(inplace=True)
http://localhost:8888/notebooks/03RegresionLogistica/01RegresionLogisticaConPython.ipynb 8/17
9/12/2018 01RegresionLogisticaConPython
Conversión de características categóricas
¡Necesitamos convertir características categóricas a variables dummy usando pandas! De lo
contrario, nuestro algoritmo de aprendizaje automático no podrá tomar directamente esas
características como entradas.
In [24]: train.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 889 entries, 0 to 890
Data columns (total 11 columns):
PassengerId 889 non-null int64
Survived 889 non-null int64
Pclass 889 non-null int64
Name 889 non-null object
Sex 889 non-null object
Age 889 non-null float64
SibSp 889 non-null int64
Parch 889 non-null int64
Ticket 889 non-null object
Fare 889 non-null float64
Embarked 889 non-null object
dtypes: float64(2), int64(5), object(4)
memory usage: 83.3+ KB
In [25]: train.head()
Out[25]: PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Emb
Braund,
0 1 0 3 Mr. Owen male 22.0 1 0 A/5 21171 7.2500
Harris
Cumings,
Mrs. John
Bradley
1 2 1 1 female 38.0 1 0 PC 17599 71.2833
(Florence
Briggs
Th...
Heikkinen,
STON/O2.
2 3 1 3 Miss. female 26.0 0 0 7.9250
3101282
Laina
Futrelle,
Mrs.
Jacques
3 4 1 1 female 35.0 1 0 113803 53.1000
Heath
(Lily May
Peel)
Allen, Mr.
4 5 0 3 William male 35.0 0 0 373450 8.0500
Henry
In [27]: sex = pd.get_dummies(train['Sex'],drop_first=True)
embark = pd.get_dummies(train['Embarked'],drop_first=True)
http://localhost:8888/notebooks/03RegresionLogistica/01RegresionLogisticaConPython.ipynb 9/17
9/12/2018 01RegresionLogisticaConPython
In [28]: train.drop(['Sex','Embarked','Name','Ticket'],axis=1,inplace=True)
In [29]: train = pd.concat([train,sex,embark],axis=1)
In [30]: train.head(15)
Out[30]: PassengerId Survived Pclass Age SibSp Parch Fare male Q S
0 1 0 3 22.0 1 0 7.2500 1 0 1
1 2 1 1 38.0 1 0 71.2833 0 0 0
2 3 1 3 26.0 0 0 7.9250 0 0 1
3 4 1 1 35.0 1 0 53.1000 0 0 1
4 5 0 3 35.0 0 0 8.0500 1 0 1
5 6 0 3 24.0 0 0 8.4583 1 1 0
6 7 0 1 54.0 0 0 51.8625 1 0 1
7 8 0 3 2.0 3 1 21.0750 1 0 1
8 9 1 3 27.0 0 2 11.1333 0 0 1
9 10 1 2 14.0 1 0 30.0708 0 0 0
10 11 1 3 4.0 1 1 16.7000 0 0 1
11 12 1 1 58.0 0 0 26.5500 0 0 1
12 13 0 3 20.0 0 0 8.0500 1 0 1
13 14 0 3 39.0 1 5 31.2750 1 0 1
14 15 0 3 14.0 0 0 7.8542 0 0 1
¡Estupendo! ¡Nuestros datos están listos para nuestro modelo!
Construcción del modelo de Regresión
Logística
Comencemos dividiendo nuestros datos en un conjunto de entrenamiento y un conjunto de pruebas
(hay otro archivo test.csv que puede usar en caso de que desee utilizar todos estos datos para el
entrenamiento).
División de datos de entrenamiento y prueba
In [31]: from sklearn.model_selection import train_test_split
In [32]: X_train, X_test, y_train, y_test = train_test_split(train.drop('Survived',axis=1),
train['Survived'], test_size=0
random_state=101)
Entrenamiento y predicción
http://localhost:8888/notebooks/03RegresionLogistica/01RegresionLogisticaConPython.ipynb 10/17
9/12/2018 01RegresionLogisticaConPython
In [33]: from sklearn.linear_model import LogisticRegression
In [34]: logmodel = LogisticRegression()
logmodel.fit(X_train,y_train)
Out[34]: LogisticRegression(C=1.0, class_weight=None, dual=False, fit_intercept=True,
intercept_scaling=1, max_iter=100, multi_class='ovr', n_jobs=1,
penalty='l2', random_state=None, solver='liblinear', tol=0.0001,
verbose=0, warm_start=False)
In [35]: predictions = logmodel.predict(X_test)
http://localhost:8888/notebooks/03RegresionLogistica/01RegresionLogisticaConPython.ipynb 11/17
9/12/2018 01RegresionLogisticaConPython
In [38]: y_test
Out[38]: 511 0
613 0
615 1
337 1
718 0
152 0
826 0
418 0
614 0
241 1
747 1
291 1
656 0
128 1
868 0
640 0
269 1
496 1
142 1
321 0
158 0
490 0
185 0
110 0
480 0
724 1
139 0
657 0
7 0
238 0
..
476 0
327 1
734 0
760 0
808 0
226 1
762 1
866 1
598 0
636 0
85 1
24 0
546 1
603 0
754 1
270 0
728 0
722 0
873 0
90 0
414 1
197 0
84 1
259 1
http://localhost:8888/notebooks/03RegresionLogistica/01RegresionLogisticaConPython.ipynb 12/17
9/12/2018 01RegresionLogisticaConPython
819 0
792 0
828 1
732 0
669 1
634 0
Name: Survived, Length: 267, dtype: int64
http://localhost:8888/notebooks/03RegresionLogistica/01RegresionLogisticaConPython.ipynb 13/17
9/12/2018 01RegresionLogisticaConPython
In [37]: X_test
Out[37]: PassengerId Pclass Age SibSp Parch Fare male Q S
511 512 3 24.0 0 0 8.0500 1 0 1
613 614 3 24.0 0 0 7.7500 1 1 0
615 616 2 24.0 1 2 65.0000 0 0 1
337 338 1 41.0 0 0 134.5000 0 0 0
718 719 3 24.0 0 0 15.5000 1 1 0
152 153 3 55.5 0 0 8.0500 1 0 1
826 827 3 24.0 0 0 56.4958 1 0 1
418 419 2 30.0 0 0 13.0000 1 0 1
614 615 3 35.0 0 0 8.0500 1 0 1
241 242 3 24.0 1 0 15.5000 0 1 0
747 748 2 30.0 0 0 13.0000 0 0 1
291 292 1 19.0 1 0 91.0792 0 0 0
656 657 3 24.0 0 0 7.8958 1 0 1
128 129 3 24.0 1 1 22.3583 0 0 0
868 869 3 24.0 0 0 9.5000 1 0 1
640 641 3 20.0 0 0 7.8542 1 0 1
269 270 1 35.0 0 0 135.6333 0 0 1
496 497 1 54.0 1 0 78.2667 0 0 0
142 143 3 24.0 1 0 15.8500 0 0 1
321 322 3 27.0 0 0 7.8958 1 0 1
158 159 3 24.0 0 0 8.6625 1 0 1
490 491 3 24.0 1 0 19.9667 1 0 1
185 186 1 37.0 0 0 50.0000 1 0 1
110 111 1 47.0 0 0 52.0000 1 0 1
480 481 3 9.0 5 2 46.9000 1 0 1
724 725 1 27.0 1 0 53.1000 1 0 1
139 140 1 24.0 0 0 79.2000 1 0 0
657 658 3 32.0 1 1 15.5000 0 1 0
7 8 3 2.0 3 1 21.0750 1 0 1
238 239 2 19.0 0 0 10.5000 1 0 1
... ... ... ... ... ... ... ... ... ...
476 477 2 34.0 1 0 21.0000 1 0 1
327 328 2 36.0 0 0 13.0000 0 0 1
734 735 2 23.0 0 0 13.0000 1 0 1
760 761 3 24.0 0 0 14.5000 1 0 1
http://localhost:8888/notebooks/03RegresionLogistica/01RegresionLogisticaConPython.ipynb 14/17
9/12/2018 01RegresionLogisticaConPython
PassengerId Pclass Age SibSp Parch Fare male Q S
808 809 2 39.0 0 0 13.0000 1 0 1
226 227 2 19.0 0 0 10.5000 1 0 1
762 763 3 20.0 0 0 7.2292 1 0 0
866 867 2 27.0 1 0 13.8583 0 0 0
598 599 3 24.0 0 0 7.2250 1 0 0
636 637 3 32.0 0 0 7.9250 1 0 1
85 86 3 33.0 3 0 15.8500 0 0 1
24 25 3 8.0 3 1 21.0750 0 0 1
546 547 2 19.0 1 0 26.0000 0 0 1
603 604 3 44.0 0 0 8.0500 1 0 1
754 755 2 48.0 1 2 65.0000 0 0 1
270 271 1 37.0 0 0 31.0000 1 0 1
728 729 2 25.0 1 0 26.0000 1 0 1
722 723 2 34.0 0 0 13.0000 1 0 1
873 874 3 47.0 0 0 9.0000 1 0 1
90 91 3 29.0 0 0 8.0500 1 0 1
414 415 3 44.0 0 0 7.9250 1 0 1
197 198 3 42.0 0 1 8.4042 1 0 1
84 85 2 17.0 0 0 10.5000 0 0 1
259 260 2 50.0 0 1 26.0000 0 0 1
819 820 3 10.0 3 2 27.9000 1 0 1
792 793 3 24.0 8 2 69.5500 0 0 1
828 829 3 24.0 0 0 7.7500 1 1 0
732 733 2 29.0 0 0 0.0000 1 0 1
669 670 1 37.0 1 0 52.0000 0 0 1
634 635 3 9.0 3 2 27.9000 0 0 1
267 rows × 9 columns
http://localhost:8888/notebooks/03RegresionLogistica/01RegresionLogisticaConPython.ipynb 15/17
9/12/2018 01RegresionLogisticaConPython
In [36]: predictions
Out[36]: array([0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0,
0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1,
1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1,
0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0,
0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0,
1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1,
0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0,
0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0,
0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0,
1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0,
0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0,
0, 1, 1], dtype=int64)
¡Pasemos a evaluar nuestro modelo!
Evaluación
¡Podemos verificar la precisión, recuperación, puntaje f1 usando el informe de clasificación!
In [39]: from sklearn.metrics import confusion_matrix
In [40]: confusion_matrix(y_test,predictions)
Out[40]: array([[151, 12],
[ 36, 68]], dtype=int64)
In [41]: from sklearn.metrics import classification_report
In [42]: print(classification_report(y_test,predictions))
precision recall f1-score support
0 0.81 0.93 0.86 163
1 0.85 0.65 0.74 104
avg / total 0.82 0.82 0.81 267
¡No esta mal! Es posible que desee explorar otra ingeniería de características y el otro archivo
titanic_text.csv, algunas sugerencias para la ingeniería de características:
Intente usar el título (Dr., Mr., Mrs, etc.) del nombre como una característica
Tal vez la letra Cabin podría ser una característica
¿Hay alguna información desde la que se pueda obtener del boleto?
¡Gran trabajo!
http://localhost:8888/notebooks/03RegresionLogistica/01RegresionLogisticaConPython.ipynb 16/17
9/12/2018 01RegresionLogisticaConPython
http://localhost:8888/notebooks/03RegresionLogistica/01RegresionLogisticaConPython.ipynb 17/17