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í:
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.
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/:
#+begin_src python
encoded_df = encode_columns(df=processed_df)
print(encoded_df.head())
#+end_src
#+begin_example
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
#+end_example
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.
Procedemos a evaluar el rendimiento de cada algoritmo, usando las siguientes métricas:
- Accuracy score
- Matriz de confusión
- Cross validation score
- Area under the curve (AUC)
Vamos a realizar 2 ejecuciones por algoritmo, para evaluar las diferencias que obtenemos según el preprocesado utilizado (eliminación de valores nulos o imputación).
La implementación se encuentra en el archivo /processing.py/, cuyo contenido mostramos a continuación:
#+begin_src python
from numpy import mean
from sklearn.metrics import confusion_matrix, accuracy_score, roc_auc_score
from sklearn.model_selection import cross_val_score
from sklearn.naive_bayes import GaussianNB
from sklearn.neural_network import MLPClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.preprocessing import scale
from sklearn.svm import LinearSVC
from sklearn.tree import DecisionTreeClassifier
from sys import argv
from preprocessing import parse_data, split_k_sets
def choose_model(model):
if model == "gnb":
return GaussianNB()
elif model == "svc":
return LinearSVC(random_state=42)
elif model == "knn":
return KNeighborsClassifier(n_neighbors=10)
elif model == "tree":
return DecisionTreeClassifier(random_state=42)
elif model == "neuralnet":
return MLPClassifier(hidden_layer_sizes=10)
else:
print("Unknown model selected. The choices are: ")
print("gnb: Gaussian Naive Bayes")
print("svc: Linear Support Vector Classification")
print("knn: K-neighbors")
print("tree: Decision tree")
print("neuralnet: MLP Classifier")
exit()
def predict_data(data, target, model):
model = choose_model(model)
if model == "knn":
data = scale(data)
accuracy_scores = []
confusion_matrices = []
auc = []
for train_index, test_index in split_k_sets(data):
Tras ejecutar todos los algoritmos elegidos, podemos analizar los resultados obtenidos.
Observamos que la imputación de la media en los valores nulos no es una estrategia que aporte demasiados beneficios, y según ciertas métricas puede ser hasta dañino para nuestro modelo.
Vemos que nuestros modelos obtienen unos resultados bastante correctos, con un /accuracy score/, /cross validation score/ y /AUC/ en el intervalo $[0.7, 0.82]$.
Por lo tanto, concluimos que nuestro problema de clasificación es suficientemente genérico para ser resuelto por distintos modelos de aprendizaje, sin variaciones significantes en el rendimientos de éstos.