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
[sourcecode language=»python» wraplines=»false» collapse=»false»]
import numpy as np
import pandas as pd
from sklearn.tree import DecisionTreeClassifier
[/sourcecode]
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.
[sourcecode language=»python» wraplines=»false» collapse=»false»]
!wget -O drug200.csv https://s3-api.us-geo.objectstorage.softlayer.net/cf-courses-data/CognitiveClass/ML0101ENv3/labs/drug200.csv
[/sourcecode]
--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)
[text language=»/csv»][/text]
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]
[sourcecode language=»python» wraplines=»false» collapse=»false»]
my_data = pd.read_csv("drug200.csv", delimiter=",")
my_data[0:5]
[/sourcecode]
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 |
[sourcecode language=»python» wraplines=»false» collapse=»false»]
my_data[‘Drug’].value_counts()
[/sourcecode]
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.
[sourcecode language=»python» wraplines=»false» collapse=»false»]
X = my_data[[‘Age’, ‘Sex’, ‘BP’, ‘Cholesterol’, ‘Na_to_K’]].values
X[0:5]
[/sourcecode]
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.
[sourcecode language=»python» wraplines=»false» collapse=»false»]
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]
[/sourcecode]
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).
[sourcecode language=»python» wraplines=»false» collapse=»false»]
y = my_data["Drug"]
y[0:5]
[/sourcecode]
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.
[sourcecode language=»python» wraplines=»false» collapse=»false»]
from sklearn.model_selection import train_test_split
[/sourcecode]
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.
[sourcecode language=»python» wraplines=»false» collapse=»false»]
X_trainset, X_testset, y_trainset, y_testset = train_test_split(X, y, test_size=0.3, random_state=3)
[/sourcecode]
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.
[sourcecode language=»python» wraplines=»false» collapse=»false»]
drugTree = DecisionTreeClassifier(criterion="entropy", max_depth = 4)
drugTree # muestra los parámetros por omisión
[/sourcecode]
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
[sourcecode language=»python» wraplines=»false» collapse=»false»]
drugTree.fit(X_trainset,y_trainset)
[/sourcecode]
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.
[sourcecode language=»python» wraplines=»false» collapse=»false»]
predTree = drugTree.predict(X_testset)
[/sourcecode]
Puedes imprimir predTree y y_testset si quieres comparar visualmente la predicción con los valores actuales.
[sourcecode language=»python» wraplines=»false» collapse=»false»]
print (predTree [0:5])
print (y_testset [0:5])
[/sourcecode]
['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.
[sourcecode language=»python» wraplines=»false» collapse=»false»]
from sklearn import metrics
import matplotlib.pyplot as plt
print("Precisión de los Arboles de Decisión: ", metrics.accuracy_score(y_testset, predTree))
[/sourcecode]
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
[sourcecode language=»python» wraplines=»false» collapse=»false»]
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’)
[/sourcecode]