<jupyter_start><jupyter_text><NAME> THE CODE 2020 DESAFIO 6 - ANAHUAC  Introducción En este desafio, usted usará herramientas de IBM como Watson Studio (o Cloud Pak for Data) para construir un modelo baseado en Machine Learning capaz de preveer si un estudante irá continuar o abandonará su curso.   Installing Libs<jupyter_code>!pip install scikit-learn --upgrade
!pip install xgboost --upgrade<jupyter_output><empty_output><jupyter_text>Loading the .csv dataset from GitHub<jupyter_code>import pandas as pd
!wget --no-check-certificate --content-disposition https://raw.githubusercontent.com/vanderlei-test/dataset2/master/datasets/ForTraining.csv
df_base_for_training = pd.read_csv(r'ForTraining.csv')
df_base_for_training.head()<jupyter_output><empty_output><jupyter_text>Descripción: La primera tabla mostrada arriba tiene 4 columnas, 3 son features and el target: `Graduado` that has a binary values={Si, No}.Usted puede, y debe, usar mas data que esta disponible para construir su modelo. Los siguientes archivos .csv presentados:<jupyter_code>!wget --no-check-certificate --content-disposition https://raw.githubusercontent.com/vanderlei-test/dataset2/master/datasets/OrdenMaterias.csv
df_orden_materias = pd.read_csv(r'OrdenMaterias.csv')
df_orden_materias.head()
!wget --no-check-certificate --content-disposition https://raw.githubusercontent.com/vanderlei-test/dataset2/master/datasets/TablaConexiones.csv
df_tabla_conexiones = pd.read_csv(r'TablaConexiones.csv')
df_tabla_conexiones.head()
!wget --no-check-certificate --content-disposition https://raw.githubusercontent.com/vanderlei-test/dataset2/master/datasets/TablaTareas.csv
df_tabla_tareas = pd.read_csv(r'TablaTareas.csv')
df_tabla_tareas.head()<jupyter_output><empty_output><jupyter_text>Overview del Dataset:    Disponibles para el participante, ecisten 4 tables cargas en DataFrames anteriormente:        **df_base_for_training**        - ``studentId``        ``reducido``        ``ciclo``        ``Graduado`` --> ¡LA VARIABLE OBJETIVO PARA CLASIFICACIÓN BINARIA!            **df_orden_materias**        ``reducido``        ``2017 - 03``        ``2017 - 04``        ``2017 - 05``        ``2017 - 06``        ``2017 - 07``        ``2017 - 08``        ``2018 - 01``        ``2018 - 02``        ``2018 - 03``        ``2018 - 04``        ``2018 - 05``        ``2018 - 06``        ``2018 - 07``        ``2018 - 08``        ``2019 - 01``        ``2019 - 02``        ``2019 - 03``        ``2019 - 04``        ``2019 - 05``        ``2019 - 06``        ``2019 - 07``        ``2019 - 08``        ``2020 - 01``        ``2020 - 02``        ``2020 - 03``        ``2020 - 04``        ``2020 - 05``        ``2020 - 06``            **df_tabla_conexiones**        - ``studentId``        ``ciclo``        ``Dias_Conectado``        ``Minutos_Promedio``        ``Minutos_Total``            **df_tabla_tareas**        - ``studentId``        ``ciclo``        ``Calificacion_Promedio``        ``Tareas_Puntuales``        ``Tareas_No_Entregadas``        ``Tareas_Retrasadas``        ``Total_Tareas``        Observe que la variable ``studentId`` aparece en varias tablas.Usted puede combinar/merge estos datasets como usted desee.<jupyter_code>print("Columnas en *df_base_for_training*:")
print(df_base_for_training.columns)

print("\Columnas en *df_orden_materias*:")
print(df_orden_materias.columns)

print("\Columnas en *df_tabla_conexiones*:")
print(df_tabla_conexiones.columns)

print("\Columnas en *df_tabla_tareas*:")
print(df_tabla_tareas.columns)<jupyter_output><empty_output><jupyter_text>¡ATENCIÓN! La columna **target** es  ``Graduado``, presente en el DataFrame "df_base_for_training".   Uniendo DataFrames en PandasDocumentación oficial para Pandas 1.1.0: https://pandas.pydata.org/pandas-docs/stable/user_guide/merging.html Como un **ejemplo** de como usar Pandas, camos a unir/merge la información de las tablas "df_base_for_training" y "df_tabla_tareas" a traves de la llave ``studentId``.Usted puee editar el dataframes manualmente si lo prefiere, usando Microsoft Excel u otros lenguajes. Recuerde insertar la data procesada en IBM Cloud Pak for Data para que pueda entrenar su modelo.<jupyter_code>df_base_for_training.tail()
df_tabla_tareas.tail()
# El resultado de esta celda sera la union de los dos anteriores dataframes
# usando la columna ``studentId`` como llave.

df = pd.merge(
    df_base_for_training, df_tabla_tareas, how='inner',
    on=None, left_on=['studentId', 'ciclo'], right_on=['studentId', 'ciclo'],
    left_index=False, right_index=False, sort=True,
    suffixes=('_x', '_y'), copy=True, indicator=False,
    validate=None
)
df.tail()
# Información acerca de las columnas del dataset unido
df.info()<jupyter_output><empty_output><jupyter_text>De la información de arriba ud puede observar que hay valores Null/NaN en algunas de las columnas.Para que nuestro modelo quede bien entrenado necesitamos procesar estos valores nulos de una forma adecuada.Usted escogera la mejor estrategia como parte del desafío, pero en la siguiente celda encuentra un **ejemplo** the como puede hacer este procesamiento usanto la libreria *scikit-learn*.  Pre-procesando el dataset antes de entrenar  Borrando finlas con valores NaN Usando el metodo Pandas DataFrame.dropna() usted puede remover todas las filas que estan indefinidas para la columna ``Graduado``.Docs: https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.dropna.html<jupyter_code># Visualizando los datos faltantes del dataset antes de la primera transformación (df_data_2)
print("Valores nulos antes de la transformación DropNA: \n\n{}\n".format(df.isnull().sum(axis = 0)))
# Aplicando la función para borrar todas las filas con valor NaN en la columna ``Graduado``:
df2 = df.dropna(axis='index', how='any', subset=['Graduado'])
# Visualizando los datos faltantes del dataset antes de la primera transformación (SimpleImputer) (df_data_3)
print("Valores nulos antes de la transformación SimpleImputer: \n\n{}\n".format(df2.isnull().sum(axis = 0)))<jupyter_output><empty_output><jupyter_text>Procesando valores NaN con SimpleImputer de sklearnPara los otros valores NaN vamos a usar como **ejemplo** la sustitución por la constante 0. Usted puede escoger cualquier estrategia que crea que es la mejor para esto :)Docs: https://scikit-learn.org/stable/modules/generated/sklearn.impute.SimpleImputer.html?highlight=simpleimputersklearn.impute.SimpleImputer<jupyter_code>from sklearn.impute import SimpleImputer
import numpy as np


# Creando un objeto ``SimpleImputer``
impute_zeros = SimpleImputer(
    missing_values=np.nan,  # Los valores faltantes son de tipo ``np.nan`` (estandar Pandas)
    strategy='constant',  # La estrategia escogida es reemplazar por una constante
    fill_value=0,  # La constante que será usada para reemmplazar los valores faltantes es un int64=0.
    verbose=0,
    copy=True
)
# Visualizando los datos faltantes del dataset antes de la segunda transformación (df_data_2)
print("Valores nulos antes de transformación SimpleImputer: \n\n{}\n".format(df2.isnull().sum(axis = 0)))

# Aplicar la transformación ``SimpleImputer`` en el conjunto de datos base
impute_zeros.fit(X=df)

# Reconstrucción del nuevo DataFrame Pandas (df_data_3)
df = pd.DataFrame.from_records(
    data=impute_zeros.transform(
        X=df
    ),  # El resultado SimpleImputer.transform(<<pandas dataframe>>) es una lista de listas
    columns=df.columns  # Las columnas originals deben ser conservadas en esta transformación
)

# Visualizndo los datos faltantes del dataset 
print("Valores nulos del dataset despues de la transformación SimpleImputer: \n\n{}\n".format(df.isnull().sum(axis = 0)))<jupyter_output><empty_output><jupyter_text>Eliminando columnas no desadasVamos a **demostrar** acontinuación como usar el metodo DataFrame.drop().Docs: https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.drop.html<jupyter_code>df.tail()
df2 = df.drop(columns=['reducido'], inplace=False)
df2.tail()<jupyter_output><empty_output><jupyter_text>Manejando variables CategoricasComo se menciono antes, los computadores no son buenos con las variables categoricas.Mientras que nosotros entendemos bien las variables categoricas, es debido a un conocimiento previo quie el computador no tiene.La mayoria de tecnicas de Machine Learning y modelso trabajan con un set limitado de datos (Tipicamente binario). Las redes neurales consumenda data y producen resultados en el rango de 0..1 t raramente van mas alla del alcance.En resumen, la gran mayoria de algoritmos de machine learning aceptan data de entrada  ("training data") de donde los features son extraidos.Basado en estos features, un modelo matematico es creado, el cual es usado para hacer una predicción o decision sin ser programado explicitamente para esa tarea.Dado un dataset con con 2 features, vamos a dejar que encoder encuentre los valores unicos por features y transforme la data a binario usando la tecnica one-hot encoding.<jupyter_code># Columnas One-hot-encoding del dataset usando el metodo de Pandas ``get_dummies``  (demontración)
df3 = pd.get_dummies(df2, columns=['ciclo'])
df3.tail()<jupyter_output><empty_output><jupyter_text>Entrenando un clasificador basado  en un Árbol de Decisión  Seleccionando FEATURES y definiendo la variable TARGET<jupyter_code>df3.columns
features = df3[
    [
        'studentId', 'Calificacion_Promedio', 'Tareas_Puntuales',
        'Tareas_No_Entregadas', 'Tareas_Retrasadas', 'Total_Tareas',
        'ciclo_2017 - 03', 'ciclo_2017 - 04', 'ciclo_2017 - 05',
        'ciclo_2017 - 06', 'ciclo_2017 - 07', 'ciclo_2017 - 08',
        'ciclo_2018 - 01', 'ciclo_2018 - 02', 'ciclo_2018 - 03',
        'ciclo_2018 - 04', 'ciclo_2018 - 05', 'ciclo_2018 - 06',
        'ciclo_2018 - 07', 'ciclo_2018 - 08', 'ciclo_2019 - 01',
        'ciclo_2019 - 02', 'ciclo_2019 - 03', 'ciclo_2019 - 04',
        'ciclo_2019 - 05', 'ciclo_2019 - 06', 'ciclo_2019 - 07',
        'ciclo_2019 - 08'
    ]
]
target = df3['Graduado']  ## No cambie la variable target!<jupyter_output><empty_output><jupyter_text>Dividiendo nuestro dataset en set de Entrenamiento y Pruebas<jupyter_code>from sklearn.model_selection import train_test_split


X_train, X_test, y_train, y_test = train_test_split(features, target, test_size=0.2, random_state=133)<jupyter_output><empty_output><jupyter_text>Entrenando un modelo ``DecisionTreeClassifier()``<jupyter_code># Método para creacion de modelos basados en arbol de desición
from sklearn.tree import DecisionTreeClassifier


dtc = DecisionTreeClassifier(max_depth=15).fit(X_train, y_train)<jupyter_output><empty_output><jupyter_text>Haciendo predicciones del Sample Test<jupyter_code>y_pred = dtc.predict(X_test)
print(y_pred)<jupyter_output><empty_output><jupyter_text>Analice la calidad del modelo a través de la matriz de confusión<jupyter_code>!pip install seaborn --upgrade
from sklearn.metrics import confusion_matrix
import matplotlib.pyplot as plt
import seaborn as sns


cf_matrix = confusion_matrix(y_test, y_pred)
group_names = ['`Positivo` Correto', '`Negativo` Errado', 'Falso `Positivo`', '`Negativo` Correto']
group_counts = ['{0:0.0f}'.format(value) for value in cf_matrix.flatten()]
group_percentages = ['{0:.2%}'.format(value) for value in cf_matrix.flatten()/np.sum(cf_matrix)]
labels = [f'{v1}\n{v2}\n{v3}' for v1, v2, v3 in zip(group_names, group_counts, group_percentages)]
labels = np.asarray(labels).reshape(2,2)
accuracy  = np.trace(cf_matrix) / float(np.sum(cf_matrix))
precision = cf_matrix[1,1] / sum(cf_matrix[:,1])
recall    = cf_matrix[1,1] / sum(cf_matrix[1,:])
f1_score  = 2*precision*recall / (precision + recall)
sns.heatmap(cf_matrix, annot=labels, fmt="")
stats_text = "\n\nAccuracy={:0.3f}\nPrecision={:0.3f}\nRecall={:0.3f}\nF1 Score={}".format(accuracy, precision, recall, f1_score)
plt.ylabel('True label')
plt.xlabel('Predicted label' + stats_text)<jupyter_output><empty_output><jupyter_text>Scoring de la data requerida para hacer la entrega de la solución Para el envío, necesita clasificar el siguiente dataset. Para hacer eso, usted necesita reproducir los mismos pasos de pre-procesamiento para que el dataset este en la misma estructura del que usted uso para construir su modelo. Despues de clasificar este dataframe, esperamos que usted entregue un archivo csv con las 2499 filar y una columna 'Graduado' con su predicción. **No cambie el orden del archivo a predecir ni borre filas**<jupyter_code>!wget --no-check-certificate --content-disposition https://raw.githubusercontent.com/vanderlei-test/dataset2/master/for_submission/ToBePredicted.csv
df_to_be_predicted = pd.read_csv(r'ToBePredicted.csv')
df_to_be_predicted.tail()
# Uniendo los dataset
df = pd.merge(
    df_to_be_predicted, df_tabla_tareas, how='inner',
    on=None, left_on=['studentId', 'ciclo'], right_on=['studentId', 'ciclo'],
    left_index=False, right_index=False, sort=True,
    suffixes=('_x', '_y'), copy=True, indicator=False,
    validate=None
)

# Eliminando la columna 'reducido'
df2 = df.drop(columns=['reducido'], inplace=False)

# Columnas One-hot-encoding del dataset usando el metodo de Pandas ``get_dummies``  (demontración)
df3 = pd.get_dummies(df2, columns=['ciclo'])
df3.tail()<jupyter_output><empty_output><jupyter_text>Observando los features declarados acontinuación, sabemos que el dataset ha ser evaluado esta en el mismo formato usado para entrenar nuestro árbol de decisión anteriormente.```features = df3[    [        'studentId', 'Calificacion_Promedio', 'Tareas_Puntuales',        'Tareas_No_Entregadas', 'Tareas_Retrasadas', 'Total_Tareas',        'ciclo_2017 - 03', 'ciclo_2017 - 04', 'ciclo_2017 - 05',        'ciclo_2017 - 06', 'ciclo_2017 - 07', 'ciclo_2017 - 08',        'ciclo_2018 - 01', 'ciclo_2018 - 02', 'ciclo_2018 - 03',        'ciclo_2018 - 04', 'ciclo_2018 - 05', 'ciclo_2018 - 06',        'ciclo_2018 - 07', 'ciclo_2018 - 08', 'ciclo_2019 - 01',        'ciclo_2019 - 02', 'ciclo_2019 - 03', 'ciclo_2019 - 04',        'ciclo_2019 - 05', 'ciclo_2019 - 06', 'ciclo_2019 - 07',        'ciclo_2019 - 08'    ]]target = df3['Graduado']   No cambie la variable target!```<jupyter_code>y_pred = dtc.predict(df3[
    [
        'studentId', 'Calificacion_Promedio', 'Tareas_Puntuales',
        'Tareas_No_Entregadas', 'Tareas_Retrasadas', 'Total_Tareas',
        'ciclo_2017 - 03', 'ciclo_2017 - 04', 'ciclo_2017 - 05',
        'ciclo_2017 - 06', 'ciclo_2017 - 07', 'ciclo_2017 - 08',
        'ciclo_2018 - 01', 'ciclo_2018 - 02', 'ciclo_2018 - 03',
        'ciclo_2018 - 04', 'ciclo_2018 - 05', 'ciclo_2018 - 06',
        'ciclo_2018 - 07', 'ciclo_2018 - 08', 'ciclo_2019 - 01',
        'ciclo_2019 - 02', 'ciclo_2019 - 03', 'ciclo_2019 - 04',
        'ciclo_2019 - 05', 'ciclo_2019 - 06', 'ciclo_2019 - 07',
        'ciclo_2019 - 08'
    ]
])
print(y_pred)<jupyter_output><empty_output><jupyter_text>Guardando los resultados de la predicción en un archivo csv<jupyter_code>np.savetxt("results.csv", y_pred, delimiter=",", fmt='%s')
project.save_data(file_name="results.csv", data=pd.read_csv("results.csv", header=None).to_csv(header=["TARGET"], index=False))<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.11662154130621409, 'fraction_numerical': 0.04325430892161395, 'mean_word_length': 4.669786596780233, 'pattern_counts': {'":': 0, '<': 72, '<?xml version=': 0, '>': 73, 'https://': 9, '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': '17', 'dir': 'jupyter-structured-clean-dedup', 'id': '30967', 'license': 'Apache-2.0', 'n_tokens_mistral': 5886, 'n_tokens_neox': 5333, 'n_words': 1348, 'path': 'anahuac.ipynb', 'repo_name': 'MiliRomero/btc-desafio6', 'size': '15152'}