<jupyter_start><jupyter_text>Trabajo Práctico 2: Análisis con Boosting - Organización de Datos **Alumnos y Padrón**+ <NAME>, <NAME> - 106255 + <NAME> - 103735https://github.com/joaqogomez/Organizacion-de-datos-fiuba  Configuraciones InicialesPrimero, importamos las bibliotecas que vamos a utilizar:<jupyter_code>import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
from sklearn.model_selection import KFold, StratifiedKFold
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.metrics import roc_auc_score
from sklearn.model_selection import GridSearchCV
from preprocessing import dividir_dataset
from preprocessing import preparar_dataset
from preprocessing import aplicar_one_hot_encoding
from funciones_auxiliares import graficar_auc_roc
from funciones_auxiliares import traer_df<jupyter_output><empty_output><jupyter_text>Carga del set de datosCargamos el dataset y aplicamos las funciones necesarias para adecuarlo al modelo:<jupyter_code>df = traer_df()
df = preparar_dataset(df)
df = aplicar_one_hot_encoding(df)<jupyter_output><empty_output><jupyter_text>También segmentamos el dataset en X e y (target), y luego lo dividimos en subsets de entrenamiento y validation development (test), y test holdout.<jupyter_code>X, y = dividir_dataset(df)
X_train_test, X_holdout, y_train_test, y_holdout = train_test_split(X, y, test_size=0.25, random_state=0, stratify=y)<jupyter_output><empty_output><jupyter_text>Búsqueda de hiperparámetrosDefinimos los mejores hiperparámetros mediante la siguiente función de búsqueda. Estos son la función de pérdida, la cantidad de estimadores a utilizar, el learning rate o tasa de aprendizaje, y el criterio. Nos quedamos con la combinación que maximice la métrica de comparación utilizada, que es AUC-ROC.Nota: No se utilizó el criterio 'mae' porque observamos el siguiente mensaje en la documentación, que dice que ese criterio está obsoleto."Deprecated since version 0.24: criterion='mae' is deprecated and will be removed in version 1.1 (renaming of 0.26). Use criterion='friedman_mse' or 'mse' instead, as trees should use a least-square criterion in Gradient Boosting."<jupyter_code>def definir_mejores_hiperparametros(X, y, modelo):    
    params = {'loss': ['deviance', 'exponential'], 'n_estimators':[1, 10, 20, 50, 100, 150, 200],'learning_rate': [0.001, 0.01, 0.1],'criterion':['friedman_mse', 'mse']}
    grid_search = GridSearchCV(modelo, params, scoring='roc_auc', n_jobs=-1, cv=5).fit(X, y)    
    return grid_search.best_params_<jupyter_output><empty_output><jupyter_text>Entrenamiento y predicción con el dataset originalBuscamos la mejor combinación de hiperparámetros para este dataset, con la función anteriormente mencionada.<jupyter_code>mejor_combinacion = definir_mejores_hiperparametros(X_train_test, y_train_test, GradientBoostingClassifier())<jupyter_output><empty_output><jupyter_text>Observamos que la mejor combinación de hiperparámetros es la siguiente:<jupyter_code>mejor_loss = mejor_combinacion['loss']
mejor_n_estimators = mejor_combinacion['n_estimators']
mejor_learning_rate = mejor_combinacion['learning_rate']
mejor_criterio = mejor_combinacion['criterion']
print(f'Mejor función de pérdida: {mejor_loss}')
print(f'Mejor número de estimadores: {mejor_n_estimators}')
print(f'Mejor learning rate (tasa de aprendizaje): {mejor_learning_rate}')
print(f'Mejor criterio: {mejor_criterio}')<jupyter_output>Mejor función de pérdida: exponential
Mejor número de estimadores: 200
Mejor learning rate (tasa de aprendizaje): 0.1
Mejor criterio: friedman_mse<jupyter_text>Entrenamos el ensamble de modelos con esa combinación:<jupyter_code>boosting = GradientBoostingClassifier(loss = mejor_loss, n_estimators = mejor_n_estimators, learning_rate = mejor_learning_rate, criterion = mejor_criterio)
boosting.fit(X_train_test, y_train_test)<jupyter_output><empty_output><jupyter_text>Luego, hacemos que este prediga sobre el subset de validation. A continuación se muestra el gráfico de la curva ROC y su respectivo score en la métrica AUC-ROC.<jupyter_code>y_pred = boosting.predict(X_holdout)
y_pred_proba = boosting.predict_proba(X_holdout)[:, 1]
graficar_auc_roc(y_holdout, y_pred_proba)<jupyter_output><empty_output><jupyter_text>Podemos observar que el AUC score dio considerablemente alto, aproximadamente 0.93. Teniendo en cuenta que 1 es un clasificador ideal, podemos decir que Boosting está bastante cerca de serlo, dentro de los modelos que probamos.Luego, imprimimos el classification report:<jupyter_code>print(classification_report(y_holdout, y_pred, target_names=['No Tiene Alto Valor Adquisitivo', 'Tiene Alto Valor Adquisitivo'],digits=3))<jupyter_output>precision    recall  f1-score   support

No Tiene Alto Valor Adquisitivo      0.889     0.947     0.917      6181
   Tiene Alto Valor Adquisitivo      0.789     0.629     0.700      1960

                       accuracy                          0.870      8141
                      macro avg      0.839     0.788     0.808      8141
                   weighted avg      0.865     0.870     0.865      8141<jupyter_text>Se puede ver un f1-score (que tiene en cuenta precision y recall) muy alto para las instancias que no tienen alto valor adquisitivo. Por otra parte, en el caso de los que si tienen alto valor adquisitivo, a pesar de que no sea igual de alto, el f1-score es considerablemente bueno, teniendo en cuenta el resultado en el resto de los modelos. Por último, mostramos la matriz de confusión correspondiente, donde se puede confirmar visualmente lo informado por el classification report:<jupyter_code>from funciones_auxiliares import graficar_matriz_confusion
graficar_matriz_confusion(y_holdout, y_pred)<jupyter_output><empty_output><jupyter_text>Observando la matriz, podemos ver que el modelo predijo casi un 40% de las instancias de alto valor adquisitivo como instancias de bajo valor adquisitivo. Se podría decir que hay una tendencia a predecir ceros, pero tampoco es muy evidente, como sí ocurre en otros modelos.  Entrenamiento y predicción con el dataset ampliadoComo otra técnica de preprocesamiento, decidimos expandir el dataset utilizando clustering para obtener cuatro nuevas columnas. Las columnas corresponden a la utilización de K-means con 2, 4, 6 y 10 como cantidad de clusters usados.<jupyter_code>from preprocessing import expandir_dataset<jupyter_output><empty_output><jupyter_text>Expandimos el dataset y realizamos el split del mismo en los subsets de entrenamiento y validación.<jupyter_code>X_exp = expandir_dataset(X)
X_exp_train_test, X_exp_holdout, y_exp_train_test, y_exp_holdout = train_test_split(X_exp, y, test_size=0.25, random_state=0, stratify=y)<jupyter_output><empty_output><jupyter_text>Buscamos la mejor combinación de hiperparámetros para este dataset.<jupyter_code>mejor_combinacion = definir_mejores_hiperparametros(X_exp_train_test, y_exp_train_test, GradientBoostingClassifier())<jupyter_output><empty_output><jupyter_text>A continuación, vemos la mejor combinación de hiperparámetros obtenida.<jupyter_code>mejor_loss = mejor_combinacion['loss']
mejor_n_estimators = mejor_combinacion['n_estimators']
mejor_learning_rate = mejor_combinacion['learning_rate']
mejor_criterio = mejor_combinacion['criterion']
print(f'Mejor función de pérdida: {mejor_loss}')
print(f'Mejor número de estimadores: {mejor_n_estimators}')
print(f'Mejor learning rate (tasa de aprendizaje): {mejor_learning_rate}')
print(f'Mejor criterio: {mejor_criterio}')<jupyter_output>Mejor función de pérdida: deviance
Mejor número de estimadores: 200
Mejor learning rate (tasa de aprendizaje): 0.1
Mejor criterio: mse<jupyter_text>Entrenamos Boosting con la mejor combinación.<jupyter_code>boosting_expandido = GradientBoostingClassifier(loss = mejor_loss, n_estimators = mejor_n_estimators, learning_rate = mejor_learning_rate, criterion = mejor_criterio)
boosting_expandido.fit(X_exp_train_test, y_exp_train_test)<jupyter_output><empty_output><jupyter_text>Y ahora hacemos que prediga sobre el dataset expandido. Graficamos también la curva ROC con su respectivo resultado en la métrica AUC-ROC.<jupyter_code>y_pred = boosting_expandido.predict(X_exp_holdout)
y_pred_proba = boosting_expandido.predict_proba(X_exp_holdout)[:, 1]
graficar_auc_roc(y_exp_holdout, y_pred_proba)<jupyter_output><empty_output><jupyter_text>Podemos observar que Boosting con el dataset ampliado dio un resultado en AUC score muy similar al anterior, pero ligeramente superior. A continuación, se muestra el classification report, que muestra otras métricas como precision, recall, accuracy, etc.<jupyter_code>print(classification_report(y_exp_holdout, y_pred, target_names=['No Tiene Alto Valor Adquisitivo', 'Tiene Alto Valor Adquisitivo'],digits=3))<jupyter_output>precision    recall  f1-score   support

No Tiene Alto Valor Adquisitivo      0.889     0.948     0.918      6181
   Tiene Alto Valor Adquisitivo      0.793     0.626     0.700      1960

                       accuracy                          0.871      8141
                      macro avg      0.841     0.787     0.809      8141
                   weighted avg      0.866     0.871     0.865      8141<jupyter_text>Por último, mostramos la matriz de confusión correspondiente a la predicción con Boosting sobre el dataset ampliado:<jupyter_code>from funciones_auxiliares import graficar_matriz_confusion
graficar_matriz_confusion(y_exp_holdout, y_pred)<jupyter_output><empty_output><jupyter_text>Podemos ver que con el dataset expandido se obtuvo un resultado muy similar al del dataset original. La tendencia se mantiene casi igual al dataset original.  Predicción con el dataset nuevoA continuación, realizamos la predicción con Boosting con el dataset ampliado sobre el dataset de predicciones nuevo, ya que es el que mejor se desempeñó según la métrica AUC-ROC, y la escribimos al archivo 'Boosting.csv'<jupyter_code>from funciones_auxiliares import traer_df_predicciones
from preprocessing import preparar_df_predicciones
from funciones_auxiliares import escribir_predicciones
df_predicciones = traer_df_predicciones()
ids, df_predicciones = preparar_df_predicciones(df_predicciones)
df_predicciones = aplicar_one_hot_encoding(df_predicciones)
df_predicciones = expandir_dataset(df_predicciones)
predicciones = boosting_expandido.predict(df_predicciones)
escribir_predicciones(ids, predicciones, "Boosting")<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.06488914373088685, 'fraction_numerical': 0.021884556574923546, 'mean_word_length': 6.032930107526882, 'pattern_counts': {'":': 0, '<': 76, '<?xml version=': 0, '>': 76, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '19', 'dir': 'jupyter-structured-clean-dedup', 'id': '268587', 'license': 'MIT', 'n_tokens_mistral': 3667, 'n_tokens_neox': 3488, 'n_words': 966, 'path': 'TP2/Boosting.ipynb', 'repo_name': 'MateoCraviotto/Organizacion-de-datos-fiuba-1', 'size': '10492'}