Titanic
Análisis de los supervivientes del Titanic, creación de modelo de Machine Learning que predice si un pasajero sobrevivió o murió durante el naufragio.
El hundimiento del RMS Titanic es uno de los mayores naufragios de la historia. En abril de 1912 durante su viaje inaugural, el Titanic se hundió después de colisionar con un iceberg, matando 1502 de 2224 pasajeros y tripulación. Después de esta tragedia sensacional la comunidad internacional impulsó la creación de mejores regularizaciones para una optima seguridad de los barcos.
Una de las razones de que el naufragio tuviese muchas pérdidas de vidas fue que tenían suficientes salvavidas para los pasajeros y tripulación. A pesar de que hubo mucha suerte involucrada en la supervivencia del hundimiento, algunos grupos tuvieron mayor probabilidad de sobrevivir que otros, tales como mujeres, niños y la clase alta.
Primeras 5 filas de los datos a analizar valores de los datos
PassengerId | Survived | Pclass | Name | Sex | Age | SibSp | Parch | Ticket | Fare | Cabin | Embarked | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 0 | 3 | Braund, Mr. Owen Harris | male | 22.0 | 1 | 0 | A/5 21171 | 7.2500 | NaN | S |
1 | 2 | 1 | 1 | Cumings, Mrs. John Bradley (Florence Briggs Th... | female | 38.0 | 1 | 0 | PC 17599 | 71.2833 | C85 | C |
2 | 3 | 1 | 3 | Heikkinen, Miss. Laina | female | 26.0 | 0 | 0 | STON/O2. 3101282 | 7.9250 | NaN | S |
3 | 4 | 1 | 1 | Futrelle, Mrs. Jacques Heath (Lily May Peel) | female | 35.0 | 1 | 0 | 113803 | 53.1000 | C123 | S |
4 | 5 | 0 | 3 | Allen, Mr. William Henry | male | 35.0 | 0 | 0 | 373450 | 8.0500 | NaN | S |
Completar los datos
Buscaremos cuantos valores nulos se encuentran en el conjunto de datos
PassengerId | 0 |
Survived | 0 |
Pclass | 0 |
Name | 0 |
Sex | 0 |
Age | 263 |
SibSp | 0 |
Parch | 0 |
Ticket | 0 |
Fare | 1 |
Cabin | 1014 |
Embarked | 2 |
dtype: | int64 |
Se encuentran 263 datos nulos en la columna de edad, 1014 en la columna de la cabina, 2 en la ciudad donde embarcaron y uno en la tarifa del boleto.
Sustituiremos los valores nulos de edad y de la tarifa usando la media de edad de los datos que sí conocemos de sus respectivas columnas, mientras que en la columna de embarcamiento los remplazaremos con 0’s.
Borraremos la columna de identificación del pasajero y del ticket ya que no nos provee de información util, también eliminaremos la cabina, pero esta vez lo haremos ya que más de la mitad de los datos de esa columna están perdidos.
for dataset in data_cleaner:
dataset['Age'].fillna(dataset['Age'].median(), inplace = True)
dataset['Embarked'].fillna(dataset['Embarked'].mode()[0], inplace = True)
dataset['Fare'].fillna(dataset['Fare'].median(), inplace = True)
drop_column = ['PassengerId','Cabin', 'Ticket']
data1.drop(drop_column, axis=1, inplace = True)
Verifiquemos que no hay más datos nulos.
Survived | 0 |
Pclass | 0 |
Name | 0 |
Sex | 0 |
Age | 0 |
SibSp | 0 |
Parch | 0 |
Fare | 0 |
Embarked | 0 |
dtype: | int64 |
Crearemos una columna que nos cuente el tamaño de su familia a bordo, usando las columnas hermanos/cónyuge y padres/hijos, también se hará una columna que diga si el pasajero viaja solo o no, adicionalmente crearemos una columna con el titulo de la persona, obtendremos este campo con la columna de nombre; Además crearemos grupos de edades y de tarifas para que sea más fácil para el modelo interpretar los datos.
for dataset in data_cleaner:
dataset['FamilySize'] = dataset ['SibSp'] + dataset['Parch'] + 1
dataset['IsAlone'] = 1
dataset['IsAlone'].loc[dataset['FamilySize'] > 1] = 0
dataset['Title'] = dataset['Name'].str.split(", ", expand=True)[1]\
.str.split(".", expand=True)[0]
dataset['FareBin'] = pd.qcut(dataset['Fare'], 4)
dataset['AgeBin'] = pd.cut(dataset['Age'].astype(int), 5)
Miraremos las primeras 5 filas del conjunto de datos modificado.
Survived | Pclass | Name | Sex | Age | SibSp | Parch | Fare | Embarked | FamilySize | IsAlone | Title | FareBin | AgeBin | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 3 | Braund, Mr. Owen Harris | male | 22.0 | 1 | 0 | 7.2500 | S | 2 | 0 | Mr | (-0.001, 7.91] | (16.0, 32.0] |
1 | 1 | 1 | Cumings, Mrs. John Bradley (Florence Briggs Th... | female | 38.0 | 1 | 0 | 71.2833 | C | 2 | 0 | Mrs | (31.0, 512.329] | (32.0, 48.0] |
2 | 1 | 3 | Heikkinen, Miss. Laina | female | 26.0 | 0 | 0 | 7.9250 | S | 1 | 1 | Miss | (7.91, 14.454] | (16.0, 32.0] |
3 | 1 | 1 | Futrelle, Mrs. Jacques Heath (Lily May Peel) | female | 35.0 | 1 | 0 | 53.1000 | S | 2 | 0 | Mrs | (31.0, 512.329] | (32.0, 48.0] |
4 | 0 | 3 | Allen, Mr. William Henry | male | 35.0 | 0 | 0 | 8.0500 | S | 1 | 1 | Mr | (7.91, 14.454] | (32.0, 48.0] |
Convertir formatos
Usaremos un codificador de etiquetas para las columnas con variables categóricas.
label = LabelEncoder()
for dataset in data_cleaner:
dataset['Sex_Code'] = label.fit_transform(dataset['Sex'])
dataset['Embarked_Code'] = label.fit_transform(dataset['Embarked'])
dataset['Title_Code'] = label.fit_transform(dataset['Title'])
dataset['AgeBin_Code'] = label.fit_transform(dataset['AgeBin'])
dataset['FareBin_Code'] = label.fit_transform(dataset['FareBin'])
Columnas originales
Original X Y | ‘Survived’ | ‘Sex’ | ‘Pclass’ | ‘Embarked’ | ‘Title’ | ‘SibSp’ |
‘Parch’ | ‘Age’ | ‘Fare’ | ‘FamilySize’ | ‘IsAlone’ |
Columnas en cajas
Bin X Y | ‘Survived’ | ‘Sex_Code’ | ‘Pclass’ | ‘Embarked_Code’ |
‘Title_Code’ | ‘FamilySize’ | ‘AgeBin_Code’ | ‘FareBin_Code’ |
Columnas con variables ficticias
Dummy X Y | ‘Survived’ | ‘Pclass’ | ‘SibSp’ | ‘Parch’ | ‘Age’ |
‘Fare’ | ‘FamilySize’ | ‘IsAlone’ | ‘Sex_female’ | ‘Sex_male’ | |
‘Embarked_C’ | ‘Embarked_Q’ | ‘Embarked_S’ | ‘Title_Master’ | ‘Title_Misc’ | |
‘Title_Miss’ | ‘Title_Mr’ | ‘Title_Mrs’ |
Primeras 5 filas del conjunto de datos con las variables ficticias.
Pclass | SibSp | Parch | Age | Fare | FamilySize | IsAlone | Sex_female | Sex_male | Embarked_C | Embarked_Q | Embarked_S | Title_Master | Title_Misc | Title_Miss | Title_Mr | Title_Mrs | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 3 | 1 | 0 | 22.0 | 7.2500 | 2 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 1 | 0 |
1 | 1 | 1 | 0 | 38.0 | 71.2833 | 2 | 0 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
2 | 3 | 0 | 0 | 26.0 | 7.9250 | 1 | 1 | 1 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 |
3 | 1 | 1 | 0 | 35.0 | 53.1000 | 2 | 0 | 1 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 1 |
4 | 3 | 0 | 0 | 35.0 | 8.0500 | 1 | 1 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 1 | 0 |
Dividir los datos
Dividiremos el conjunto original en entrenamiento y pruebas
Datos originales: (891, 19)
Datos de entrenamiento: (668, 19)
Datos de prueba: (223, 19)
Realizar análisis exploratorio
Porcentaje de hombres y mujeres que sobrevivieron.
Porcentaje de personas de cierta clase social que sobrevivieron.
Porcentaje de personas que sobrevivieron según su zona de embarque.
Porcentaje de personas que sobrevivieron según su titulo.
Porcentaje de personas que sobrevivieron dependiendo del número de hermanos/cónyuges a bordo
Porcentaje de personas que sobrevivieron dependiendo del número de padres e hijos a bordo
Porcentaje de personas que sobreviveron dependiendo del número de integrantes de su familia a bordo.
Porcentaje de personas que sobrevivieron dependiendo si viajaban solas o no.
Algunos gráficos extra.
Mapa de correlación de las columnas del conjunto de datos.
Modelar los datos
Tabla que nos indica el rendimiento de los diversos modelos utilizados para resolver el problema.
MLA Name | MLA Parameters | MLA Train Accuracy Mean | MLA Test Accuracy Mean | MLA Test Accuracy 3*STD | MLA Time | |
---|---|---|---|---|---|---|
7 | SVC | {'C': 1.0, 'break_ties': False, 'cache_size': ... | 0.835206 | 0.827612 | 0.0409157 | 0.136107 |
4 | RandomForestClassifier | {'bootstrap': True, 'ccp_alpha': 0.0, 'class_w... | 0.895131 | 0.826493 | 0.0633724 | 0.658607 |
12 | XGBClassifier | {'objective': 'binary:logistic', 'base_score':... | 0.890449 | 0.826493 | 0.0617704 | 0.356233 |
8 | NuSVC | {'break_ties': False, 'cache_size': 200, 'clas... | 0.834082 | 0.826119 | 0.0456629 | 0.15811 |
2 | ExtraTreesClassifier | {'bootstrap': False, 'ccp_alpha': 0.0, 'class_... | 0.895131 | 0.824254 | 0.0593284 | 0.466217 |
3 | GradientBoostingClassifier | {'ccp_alpha': 0.0, 'criterion': 'friedman_mse'... | 0.866667 | 0.822015 | 0.0529916 | 0.341489 |
9 | DecisionTreeClassifier | {'ccp_alpha': 0.0, 'class_weight': None, 'crit... | 0.895131 | 0.820896 | 0.0579501 | 0.00795968 |
1 | BaggingClassifier | {'base_estimator': None, 'bootstrap': True, 'b... | 0.890075 | 0.81903 | 0.0631744 | 0.0723112 |
6 | KNeighborsClassifier | {'algorithm': 'auto', 'leaf_size': 30, 'metric... | 0.850375 | 0.813806 | 0.0690863 | 0.00837021 |
0 | AdaBoostClassifier | {'algorithm': 'SAMME.R', 'base_estimator': Non... | 0.820412 | 0.81194 | 0.0498606 | 0.307621 |
5 | GaussianProcessClassifier | {'copy_X_train': True, 'kernel': None, 'max_it... | 0.871723 | 0.810448 | 0.0492537 | 0.668614 |
11 | QuadraticDiscriminantAnalysis | {'priors': None, 'reg_param': 0.0, 'store_cova... | 0.821536 | 0.80709 | 0.0810389 | 0.00862453 |
10 | ExtraTreeClassifier | {'ccp_alpha': 0.0, 'class_weight': None, 'crit... | 0.895131 | 0.806716 | 0.0557008 | 0.0073771 |
Gráfico de barras con la exactitud de cada uno de los modelos utilizados.
Evaluar el rendimiento del modelo
Porcentaje de sobrevivientes femeninos dependiendo de su clase social, la ciudad de embarcamiento y la tarifa de su boleto.
Sex | Pclass | Embarked | FareBin | Surviving percentage |
female | 1 | C | (14.454, 31.0] | 0.666667 |
(31.0, 512.329] | 1.000000 | |||
Q | (31.0, 512.329] | 1.000000 | ||
S | (14.454, 31.0] | 1.000000 | ||
(31.0, 512.329] | 0.955556 | |||
2 | C | (7.91, 14.454] | 1.000000 | |
(14.454, 31.0] | 1.000000 | |||
(31.0, 512.329] | 1.000000 | |||
Q | (7.91, 14.454] | 1.000000 | ||
S | (7.91, 14.454] | 0.875000 | ||
(14.454, 31.0] | 0.916667 | |||
(31.0, 512.329] | 1.000000 | |||
3 | C | (-0.001, 7.91] | 1.000000 | |
(7.91, 14.454] | 0.428571 | |||
(14.454, 31.0] | 0.666667 | |||
Q | (-0.001, 7.91] | 0.750000 | ||
(7.91, 14.454] | 0.500000 | |||
(14.454, 31.0] | 0.714286 | |||
S | (-0.001, 7.91] | 0.533333 | ||
(7.91, 14.454] | 0.448276 | |||
(14.454, 31.0] | 0.357143 | |||
(31.0, 512.329] | 0.125000 |
Porcentaje de sobrevivientes masculinos dependiendo de su titulo.
Sex | Title | Surviving percentage |
male | Master | 0.575000 |
Misc | 0.250000 | |
Mr | 0.156673 |
Rendimiento del modelo con Cross-Validation
Evaluación del árbol de decision antes de Cross-Validation
BEFORE DT Parameters: {'ccp_alpha': 0.0, 'class_weight': None,
'criterion': 'gini', 'max_depth': None,
'max_features': None, 'max_leaf_nodes': None,
'min_impurity_decrease': 0.0, 'min_impurity_split': None,
'min_samples_leaf': 1, 'min_samples_split': 2,
'min_weight_fraction_leaf': 0.0, 'presort': 'deprecated',
'random_state': 0, 'splitter': 'best'}
BEFORE DT Training w/bin score mean: 89.51
BEFORE DT Test w/bin score mean: 82.09
BEFORE DT Test w/bin score 3*std: +/- 5.57
Evaluación del árbol de decision después de Cross-Validation
AFTER DT Parameters: {'criterion': 'gini', 'max_depth': 4,
'max_features': None, 'min_samples_leaf': 5,
'min_samples_split': 2, 'random_state': 0,
'splitter': 'best'}
AFTER DT Training w/bin score mean: 89.25
AFTER DT Test w/bin score mean: 87.68
AFTER DT Test w/bin score 3*std: +/- 6.00
Evaluación del árbol de decision antes de recursive feature elimination Cross-Validation
BEFORE DT RFE Training Shape Old: (891, 7)
BEFORE DT RFE Training Columns Old: ['Sex_Code' 'Pclass' 'Embarked_Code' 'Title_Code' 'FamilySize'
'AgeBin_Code' 'FareBin_Code']
BEFORE DT RFE Training w/bin score mean: 89.51
BEFORE DT RFE Test w/bin score mean: 82.09
BEFORE DT RFE Test w/bin score 3*std: +/- 5.57
Evaluación del árbol de decision después de recursive feature elimination Cross-Validation
AFTER DT RFE Training Shape New: (891, 6)
AFTER DT RFE Training Columns New: ['Sex_Code' 'Pclass' 'Title_Code'
'FamilySize' 'AgeBin_Code' 'FareBin_Code']
AFTER DT RFE Training w/bin score mean: 88.16
AFTER DT RFE Test w/bin score mean: 83.06
AFTER DT RFE Test w/bin score 3*std: +/- 6.22
Evaluación del árbol de decision después de Cross-Validation usando las nuevas columnas
AFTER DT RFE Tuned Parameters: {'criterion': 'gini', 'max_depth': 8,
'max_features': None, 'min_samples_leaf': 5,
'min_samples_split': 2, 'random_state': 0,
'splitter': 'best'}
AFTER DT RFE Tuned Training w/bin score mean: 89.23
AFTER DT RFE Tuned Test w/bin score mean: 87.82
AFTER DT RFE Tuned Test w/bin score 3*std: +/- 6.81
----------
Visualización del árbol de decisión creado por el modelo.
Validar e implementar el modelado de datos
Votación sin hyper-parametrización
Hard Voting Training w/bin score mean: 87.90
Hard Voting Test w/bin score mean: 82.01
Hard Voting Test w/bin score 3*std: +/- 3.50
----------
Soft Voting Training w/bin score mean: 88.65
Soft Voting Test w/bin score mean: 82.95
Soft Voting Test w/bin score 3*std: +/- 5.82
----------
Classifier | Parameter_name | Parameter_value |
AdaBoostClassifier | ‘algorithm’ | ‘SAMME.R’ |
‘learning_rate’ | 0.1 | |
‘n_estimators’ | 300 | |
‘random_state’ | 0 | |
with a runtime of 302.35 seconds. | ||
ExtraTreesClassifier | ‘criterion’ | ‘entropy’ |
‘max_depth’ | 6 | |
‘n_estimators’ | 100 | |
‘random_state’ | 0 | |
with a runtime of 281.81 seconds. | ||
GradientBoostingClassifier | ||
‘criterion’ | ‘friedman_mse’ | |
‘learning_rate’ | 0.05 | |
‘loss’ | ‘deviance’ | |
‘max_depth’ | 2 | |
‘n_estimators’ | 300 | |
‘random_state’ | 0 | |
with a runtime of 3145.16 seconds. | ||
RandomForestClassifier | ‘criterion’ | ‘entropy’ |
‘max_depth’ | 6 | |
‘n_estimators’ | 100 | |
‘oob_score’ | True | |
‘random_state’ | 0 | |
with a runtime of 466.24 seconds. | ||
GaussianProcessClassifier | ‘max_iter_predict’ | 10 |
‘random_state’ | 0 | |
with a runtime of 43.35 seconds. | ||
KNeighborsClassifier | ‘algorithm’ | ‘brute’ |
‘n_neighbors’ | 7 | |
‘weights’ | ‘uniform’ | |
with a runtime of 14.40 seconds. | ||
SVC | ‘C’ | 2 |
‘decision_function_shape’ | ‘ovo’ | |
‘gamma’ | 0.1 | |
‘probability’ | True | |
‘random_state’ | 0 | |
with a runtime of 86.27 seconds. | ||
XGBClassifier | ‘learning_rate’ | 0.01 |
‘max_depth’ | 4 | |
‘n_estimators’ | 300 | |
‘seed’ | 0 | |
with a runtime of 271.92 seconds. | ||
Total optimization time was 76.86 minutes. |
Resultados finales con hyperparametros
Hard Voting w/Tuned Hyperparameters Training w/bin score mean: 85.52
Hard Voting w/Tuned Hyperparameters Test w/bin score mean: 82.46
Hard Voting w/Tuned Hyperparameters Test w/bin score 3*std: +/- 4.90
----------
Soft Voting w/Tuned Hyperparameters Training w/bin score mean: 85.22
Soft Voting w/Tuned Hyperparameters Test w/bin score mean: 82.46
Soft Voting w/Tuned Hyperparameters Test w/bin score 3*std: +/- 5.88
----------
Para ver el repositorio completo ¡Click aquí!