IN-P1/docs/Summary.org

7.1 KiB

Práctica 1

Práctica 1

Introducción

En esta práctica, usaremos distintos algoritmos de aprendizaje automático para resolver un problema de clasificación.

Procesado de datos

Antes de proceder con el entrenamiento de los distintos modelos, debemos realizar un preprocesado de los datos, para asegurarnos que nuestros modelos aprenden de un dataset congruente.

La integridad de la lógica del preprocesado se encuentra en el archivo preprocessing.py, cuyo contenido mostramos aquí:

from pandas import read_csv
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import KFold


def replace_values(df):
    columns = ["BI-RADS", "Margin", "Density", "Age"]
    for column in columns:
        df[column].fillna(value=df[column].mean(), inplace=True)
    return df


def process_na(df, action):
    if action == "drop":
        return df.dropna()
    elif action == "fill":
        return replace_values(df)
    else:
        print("Unknown action selected. The choices are: ")
        print("fill: fills the na values with the mean")
        print("drop: drops the na values")
        exit()


def encode_columns(df):
    label_encoder = LabelEncoder()
    encoded_df = df.copy()
    encoded_df["Shape"] = label_encoder.fit_transform(df["Shape"])
    encoded_df["Severity"] = label_encoder.fit_transform(df["Severity"])
    return encoded_df


def split_train_target(df):
    train_data = df.drop(columns=["Severity"])
    target_data = df["Severity"]
    return train_data, target_data


def split_k_sets(df):
    k_fold = KFold(shuffle=True, random_state=42)
    return k_fold.split(df)


def parse_data(source, action):
    df = read_csv(filepath_or_buffer=source, na_values="?")
    processed_df = process_na(df=df, action=action)
    encoded_df = encode_columns(df=processed_df)
    test_data, target_data = split_train_target(df=encoded_df)
    return test_data, target_data

A continuación, mostraremos cada uno de los pasos que realizamos para obtener el dataset final:

Valores nulos

Nuestro dataset contiene valores nulos, representados mediante un signo de interrogación (?). Optamos por evaluar 2 estrategias:

Eliminar los valores nulos
df = read_csv(filepath_or_buffer="../data/mamografia.csv", na_values="?")
processed_df = process_na(df=df, action="drop")
print("DataFrame sin preprocesamiento: ")
print(df.describe())
print("DataFrame sin preprocesamiento: ")
print(processed_df.describe())
DataFrame sin preprocesamiento: 
          BI-RADS         Age      Margin     Density
count  959.000000  956.000000  913.000000  885.000000
mean     4.296142   55.487448    2.796276    2.910734
std      0.706291   14.480131    1.566546    0.380444
min      0.000000   18.000000    1.000000    1.000000
25%      4.000000   45.000000    1.000000    3.000000
50%      4.000000   57.000000    3.000000    3.000000
75%      5.000000   66.000000    4.000000    3.000000
max      6.000000   96.000000    5.000000    4.000000
DataFrame sin preprocesamiento: 
          BI-RADS         Age      Margin     Density
count  847.000000  847.000000  847.000000  847.000000
mean     4.322314   55.842975    2.833530    2.909091
std      0.703762   14.603754    1.564049    0.370292
min      0.000000   18.000000    1.000000    1.000000
25%      4.000000   46.000000    1.000000    3.000000
50%      4.000000   57.000000    3.000000    3.000000
75%      5.000000   66.000000    4.000000    3.000000
max      6.000000   96.000000    5.000000    4.000000

Observamos que el número de instancias disminuye considerablemente, hasta un máximo de 112, en el caso del BI-RADS. Aún así, los valores de la media y desviación estándar no se ven afectados de forma considerable.

Imputar su valor con la media
df = read_csv(filepath_or_buffer="../data/mamografia.csv", na_values="?")
processed_df = process_na(df=df, action="fill")
print("DataFrame sin preprocesamiento: ")
print(df.describe())
print("DataFrame sin preprocesamiento: ")
print(processed_df.describe())
DataFrame sin preprocesamiento: 
          BI-RADS         Age      Margin     Density
count  961.000000  961.000000  961.000000  961.000000
mean     4.296142   55.487448    2.796276    2.910734
std      0.705555   14.442373    1.526880    0.365074
min      0.000000   18.000000    1.000000    1.000000
25%      4.000000   45.000000    1.000000    3.000000
50%      4.000000   57.000000    3.000000    3.000000
75%      5.000000   66.000000    4.000000    3.000000
max      6.000000   96.000000    5.000000    4.000000
DataFrame sin preprocesamiento: 
          BI-RADS         Age      Margin     Density
count  961.000000  961.000000  961.000000  961.000000
mean     4.296142   55.487448    2.796276    2.910734
std      0.705555   14.442373    1.526880    0.365074
min      0.000000   18.000000    1.000000    1.000000
25%      4.000000   45.000000    1.000000    3.000000
50%      4.000000   57.000000    3.000000    3.000000
75%      5.000000   66.000000    4.000000    3.000000
max      6.000000   96.000000    5.000000    4.000000

Esta alternativa nos permite mantener el número de instancias en todas las columnas, sin alterar la media ni la desviación típica.

Valores no númericos

La mayoría de algoritmos de aprendizaje automática trabaja con datos numéricos, desafortunadamente nuestro dataset contiene dos columnas con datos descriptivos.

Procedemos a convertirlos en valores numéricos mediante un LabelEncoder:

encoded_df = encode_columns(df=processed_df)
print(encoded_df.head())
   BI-RADS   Age  Shape  Margin   Density  Severity
0      5.0  67.0      1     5.0  3.000000         1
1      4.0  43.0      4     1.0  2.910734         1
2      5.0  58.0      0     5.0  3.000000         1
3      4.0  28.0      4     1.0  3.000000         0
4      5.0  74.0      4     5.0  2.910734         1

Vemos como las columnas Shape y Severity se componen ahora únicamente de valores numéricos.

Separación de datos

Como último paso, separamos la columna objetivo de los demás datos.

test_data, target_data = split_train_target(df=encoded_df)
print("Datos de entrenamiento: ")
print(test_data.head())
print("Datos objetivo: ")
print(target_data.head())
Datos de entrenamiento: 
   BI-RADS   Age  Shape  Margin   Density
0      5.0  67.0      1     5.0  3.000000
1      4.0  43.0      4     1.0  2.910734
2      5.0  58.0      0     5.0  3.000000
3      4.0  28.0      4     1.0  3.000000
4      5.0  74.0      4     5.0  2.910734
Datos objetivo: 
0    1
1    1
2    1
3    0
4    1
Name: Severity, dtype: int64