En este ejercicio se utiliza un algoritmo de clasificación para construir un modelo basado en datos históricos de pacientes y sus respectivos medicamentos. Luego, se usa el árbol de decisión para predecir la clase de paciente desconocido o para encontrar la droga adecuada para el mismo.

Importación de los paquetes básicos

import numpy as np 
import pandas as pd
from sklearn.tree import DecisionTreeClassifier

Un investigador médico ha recolectado datos de un grupo de pacientes con la misma enfermedad. Durante su tratamiento, cada paciente respondio a uno de 5 medicaciones: Droga A, Droga B, Droga c, Droga x e y. Construir un modelo para encontrar la droga apropiada para pacientes con la misma enfermedad. Las características son Edad, Sexo, Presión Sanguínea y Colesterol.

Es un ejemplo de un clasificador binario para construir un árbol de decisión para predecir la clase de pacientes desconocidos o para prescribirle a un nuevo paciente.

Descargando los Datos

Para descagar los datos, utilizaremos !wget desde IBM Object Storage.

!wget -O drug200.csv https://s3-api.us-geo.objectstorage.softlayer.net/cf-courses-data/CognitiveClass/ML0101ENv3/labs/drug200.csv
--2020-01-20 16:12:03--  https://s3-api.us-geo.objectstorage.softlayer.net/cf-courses-data/CognitiveClass/ML0101ENv3/labs/drug200.csv
Resolving s3-api.us-geo.objectstorage.softlayer.net (s3-api.us-geo.objectstorage.softlayer.net)... 67.228.254.196
Connecting to s3-api.us-geo.objectstorage.softlayer.net (s3-api.us-geo.objectstorage.softlayer.net)|67.228.254.196|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 6027 (5.9K)

Saving to: ‘drug200.csv’

drug200.csv 100%[===================>] 5.89K –.-KB/s in 0s

2020-01-20 16:12:03 (12.4 MB/s) – ‘drug200.csv’ saved [6027/6027]

my_data = pd.read_csv("drug200.csv", delimiter=",")
my_data[0:5]
Age Sex BP Cholesterol Na_to_K Drug
0 23 F HIGH HIGH 25.355 drugY
1 47 M LOW HIGH 13.093 drugC
2 47 M LOW HIGH 10.114 drugC
3 28 F NORMAL HIGH 7.798 drugX
4 61 F LOW HIGH 18.043 drugY
my_data['Drug'].value_counts()

drugY    91
drugX    54
drugA    23
drugC    16
drugB    16
Name: Drug, dtype: int64

Pre-procesamiento

Utilizando my_data como los datos de panda el archivo Drug.csv, declara las siguientes variables:

  • X como la matriz de características (datos de my_data)
  • y como el vector de respuesta (target)

Elimina la columna que contiene el target ya que no posee valores numéricos.

X = my_data[['Age', 'Sex', 'BP', 'Cholesterol', 'Na_to_K']].values
X[0:5]
array([[23, 'F', 'HIGH', 'HIGH', 25.355],
       [47, 'M', 'LOW', 'HIGH', 13.093],
       [47, 'M', 'LOW', 'HIGH', 10.113999999999999],
       [28, 'F', 'NORMAL', 'HIGH', 7.797999999999999],
       [61, 'F', 'LOW', 'HIGH', 18.043]], dtype=object)

Algunas características son de categoría, tales como __Sex__ o__BP__. Desafortunadamente, los árboles de Decisión Sklearn no manejan variables categóricas. Pero las podemos convertir en valores numéricos.

from sklearn import preprocessing
le_sex = preprocessing.LabelEncoder()
le_sex.fit(['F','M'])
X[:,1] = le_sex.transform(X[:,1]) 

le_BP = preprocessing.LabelEncoder()
le_BP.fit([ 'LOW', 'NORMAL', 'HIGH'])
X[:,2] = le_BP.transform(X[:,2])

le_Chol = preprocessing.LabelEncoder()
le_Chol.fit([ 'NORMAL', 'HIGH'])
X[:,3] = le_Chol.transform(X[:,3]) 

X[0:5]

array([[23, 0, 0, 0, 25.355],
       [47, 1, 1, 0, 13.093],
       [47, 1, 1, 0, 10.113999999999999],
       [28, 0, 2, 0, 7.797999999999999],
       [61, 0, 1, 0, 18.043]], dtype=object)

Ahora, podemos completar la variable objetivo (target).

y = my_data["Drug"]
y[0:5]
0    drugY
1    drugC
2    drugC
3    drugX
4    drugY
Name: Drug, dtype: object

Configurando el Arbol de Decisión

Importamos train_test_split de sklearn.cross_validation.

from sklearn.model_selection import train_test_split

Con la función train_test_split obtenemos parámetros diferentes. Los nombraremos: X_trainset, X_testset, y_trainset, y_testset
El train_test_split necesitará los parámetros: X, y, test_size=0.3, and random_state=3.
La X e y son los arrays necesarios antes de la operación dividir/separar, test_size representa el grado del dataset de pruebas, y el random_state asegura que obtendremos las mismas divisiones.

X_trainset, X_testset, y_trainset, y_testset = train_test_split(X, y, test_size=0.3, random_state=3)

Modelando

Primero crearemos una instancia del DecisionTreeClassifier llamada drugTree. Dentro del clasificador, especificaremos criterion=”entropy” para que podamos ver la nueva información de cada nodo.

drugTree = DecisionTreeClassifier(criterion="entropy", max_depth = 4)
drugTree # muestra los parámetros por omisión
DecisionTreeClassifier(class_weight=None, criterion='entropy', max_depth=4,
            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=False, random_state=None,
            splitter='best')

Luego, adaptaremos los datos con la matriz de entrenamiento X_trainset y el vector de respuesta y_trainset

drugTree.fit(X_trainset,y_trainset)
DecisionTreeClassifier(class_weight=None, criterion='entropy', max_depth=4,
            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=False, random_state=None,
            splitter='best')

Predicción

Ahora hagamos algunas predicciones en el dataset de pruebas y guardémoslas en una variable llamada predTree.

predTree = drugTree.predict(X_testset)

Puedes imprimir predTree y y_testset si quieres comparar visualmente la predicción con los valores actuales.

print (predTree [0:5])
print (y_testset [0:5])

['drugY' 'drugX' 'drugX' 'drugX' 'drugX']
40     drugY
51     drugX
139    drugX
197    drugX
170    drugX
Name: Drug, dtype: object

Evaluación

Luego, importemos __metrics__ de sklearn y revisemos la precisión de nuestro modelo.

from sklearn import metrics
import matplotlib.pyplot as plt
print("Precisión de los Arboles de Decisión: ", metrics.accuracy_score(y_testset, predTree))
Precisión de los Arboles de Decisión:  0.9833333333333333

Accuracy classification score calcula la precisión del subconjunto: las etiquetas predichas para una muestra deben coincidir con las correspondientes etiquetas en y_true.

En la clasificación multietiqueta, la función devuelve un subconjunto de precisión. Si el conjunto de etiquetas predichas para una muestra coincide totalmente con el conjunto de etiquetas, entonces la precisión del subconjunto es 1.0; de no ser así, es 0.0.

Visualización

Observemos el árbol

from sklearn.externals.six import StringIO
import pydotplus
import matplotlib.image as mpimg
from sklearn import tree
%matplotlib inline 
dot_data = StringIO()
filename = "drugtree.png"
featureNames = my_data.columns[0:5]
targetNames = my_data["Drug"].unique().tolist()
out=tree.export_graphviz(drugTree,feature_names=featureNames, out_file=dot_data, class_names= np.unique(y_trainset), filled=True,  special_characters=True,rotate=False)  
graph = pydotplus.graph_from_dot_data(dot_data.getvalue())  
graph.write_png(filename)
img = mpimg.imread(filename)
plt.figure(figsize=(100, 200))
plt.imshow(img,interpolation='nearest')