Los algoritmos de clasificación aprenden a asignar etiquetas de clase a ejemplos (observaciones o puntos de datos), aunque sus decisiones pueden parecer opacas. Este tutorial está escrito por KVS Setty Puedes encontrar el código fuente completo en mi repositorio git Un diagnóstico popular para comprender las decisiones tomadas por un algoritmo de clasificación es la . Esta es una gráfica que muestra cómo un algoritmo de aprendizaje automático entrenado predice una cuadrícula gruesa en el espacio de características de entrada. superficie de decisión Un gráfico de superficie de decisión es una herramienta poderosa para comprender cómo un modelo determinado "ve" la tarea de predicción y cómo ha decidido dividir el espacio de características de entrada por etiqueta de clase. En este tutorial, descubrirá cómo trazar una superficie de decisión para un algoritmo de aprendizaje automático de clasificación. Después de completar este tutorial, sabrás: La superficie de decisión es una herramienta de diagnóstico para comprender cómo un algoritmo de clasificación divide el espacio de características. Cómo trazar una superficie de decisión para usar etiquetas de clase nítidas para un algoritmo de aprendizaje automático. Cómo trazar e interpretar una superficie de decisión usando probabilidades predichas. Empecemos. Descripción general del tutorial Este tutorial se divide en cuatro partes; están: Superficie de decisión Conjunto de datos y modelo Trazar una superficie de decisión Trace la superficie de decisión de un árbol de decisión en el conjunto de datos del iris Superficie de decisión Los algoritmos de aprendizaje automático de clasificación aprenden a asignar etiquetas a los ejemplos de entrada (observaciones). Considere las características de entrada numérica para la tarea de clasificación que define un espacio de características de entrada continuo. Podemos pensar en cada característica de entrada que define un eje o dimensión en un espacio de características. Dos características de entrada definirían un espacio de características que es un plano, con puntos que representan las coordenadas de entrada en el espacio de entrada. Si hubiera tres variables de entrada, el espacio de características sería un volumen tridimensional. Si hubiera variables de entrada, el espacio de características sería un hiperplano de . Espacios difíciles de visualizar más allá de las tres dimensiones. n n dimensiones A cada punto del espacio se le puede asignar una etiqueta de clase. En términos de un espacio de características bidimensionales, podemos pensar que cada punto en el plano tiene un color diferente, de acuerdo con su clase asignada. El objetivo de un algoritmo de clasificación es aprender a dividir el espacio de características de modo que las etiquetas se asignen correctamente a los puntos en el espacio de características o, al menos, lo más correctamente posible. Esta es una comprensión geométrica útil del modelado de clasificación predictiva. Podemos llevarlo un paso más allá. Una vez que un algoritmo de aprendizaje automático de clasificación divide un espacio de características, podemos clasificar cada punto en el espacio de características, en una cuadrícula arbitraria, para tener una idea de cómo exactamente el algoritmo eligió dividir el espacio de características. Esto se denomina de de decisión y proporciona una herramienta de diagnóstico para comprender un modelo en una tarea de modelado de clasificación predictiva. superficie decisión o límite Aunque la noción de "superficie" sugiere un espacio de características de dos dimensiones, el método se puede utilizar con espacios de características con más de dos dimensiones, donde se crea una superficie para cada par de características de entrada. Ahora que estamos familiarizados con lo que es una superficie de decisión, a continuación, definamos un conjunto de datos y un modelo para el cual luego exploraremos el límite de decisión. Conjunto de datos y modelo En esta sección, definiremos una tarea de clasificación y un modelo predictivo para aprender la tarea. Conjunto de datos de clasificación sintética Podemos usar la para definir una tarea de clasificación con un espacio de características numéricas bidimensionales y cada punto asignado a una de las dos etiquetas de clase, por ejemplo, una tarea de clasificación binaria. función scikit-learn make_blobs() ... # generate dataset X, y = make_blobs(n_samples= , centers= , n_features= , random_state= , cluster_std= ) 1000 2 2 26 3 Una vez definido, podemos crear un diagrama de dispersión del espacio de características con la primera característica definiendo el eje x, la segunda característica definiendo el eje y, y cada muestra representada como un punto en el espacio de características. Luego podemos colorear los puntos en el diagrama de dispersión de acuerdo con su etiqueta de clase como 0 o 1. ... # create scatter plot samples each = , y= , hue= , data=data) for from . % . ( class import numpy as np import pandas as pd import Matplotlib pyplot as plt matplotlib inline Import seaborn as sns sns scatterplot x "x1" "x2" 'class' Combinando todo esto, el ejemplo completo de definición y trazado de un conjunto de datos de clasificación sintética se enumera a continuación. En 1]: # generate binary classification dataset and plot numpy np pandas pd matplotlib.pyplot plt %matplotlib inline seaborn sns sklearn.datasets make_blobs # generate dataset X, y = make_blobs(n_samples= , centers= , n_features= , random_state= , cluster_std= ) import as import as import as import as from import 1000 2 2 1 3 En 2]: X_df = pd.DataFrame(X, columns=[ , ]) X_df.head() 'x1' 'x2' Salida[2]: En 3]: y_df = pd.DataFrame(y, columns=[ ]) "class" En [4]: y_df.head() Fuera[4]: En [5]: = [ , y_df] frames X_df = pd.concat( , =1) data frames axis .head() data Fuera[5]: En [6]: # create scatter plot samples each = , y= , hue= , data=data) for from . ( class sns scatterplot x "x1" "x2" 'class' Fuera[6]: <matplotlib.axes._subplots.AxesSubplot at > 0x1a62b1ec0f0 Ejecutar el ejemplo anterior creó el conjunto de datos, luego traza el conjunto de datos como un diagrama de dispersión con puntos coloreados por etiqueta de clase. Podemos ver una separación clara entre los ejemplos de las dos clases y podemos imaginar cómo un modelo de aprendizaje automático podría dibujar una línea para separar las dos clases, por ejemplo, quizás una línea diagonal justo en el medio de los dos grupos. Ajustar modelo de clasificación predictiva Ahora podemos ajustar un modelo en nuestro conjunto de datos. En este caso, ajustaremos un algoritmo de regresión logística porque podemos predecir etiquetas de clase nítidas y probabilidades, las cuales podemos usar en nuestra superficie de decisión. Podemos definir el modelo y luego ajustarlo al conjunto de datos de entrenamiento. ... model = LogisticRegression() model.fit(X, y) # define the model # fit the model Una vez definido, podemos usar el modelo para hacer una predicción para el conjunto de datos de entrenamiento para tener una idea de qué tan bien aprendió a dividir el espacio de características del conjunto de datos de entrenamiento y asignar etiquetas. pyhton ... # make predictions yhat = model.predict(X) Las predicciones se pueden evaluar utilizando la precisión de la clasificación. ... # evaluate the predictions acc = accuracy_score(y, yhat) print( % acc) 'Accuracy: %.3f' combinando todo esto, el ejemplo completo de ajuste y evaluación de un modelo en el conjunto de datos de clasificación binaria sintética se enumera a continuación. En [7]: # example fitting and evaluating a model on the classification dataset sklearn.datasets make_blobs sklearn.linear_model LogisticRegression sklearn.metrics accuracy_score # generate dataset X, y = make_blobs(n_samples= , centers= , n_features= , random_state= , cluster_std= ) # define the model model = LogisticRegression() # fit the model model.fit(X, y) # make predictions yhat = model.predict(X) # evaluate the predictions acc = accuracy_score(y, yhat) print( % acc) of from import from import from import 1000 2 2 1 3 'Accuracy: %.3f' Accuracy: 0.972 Ejecutar el ejemplo ajusta el modelo y hace una predicción para cada ejemplo. Sus resultados específicos pueden variar dada la naturaleza estocástica del algoritmo de aprendizaje. Intente ejecutar el ejemplo varias veces. En este caso, podemos ver que el modelo logró un rendimiento de alrededor del 97,2 por ciento. Ahora que tenemos un conjunto de datos y un modelo, exploremos cómo podemos desarrollar una superficie de decisión. Trazar una superficie de decisión Podemos crear un límite de decisión ajustando un modelo en el conjunto de datos de entrenamiento y luego usando el modelo para hacer predicciones para una cuadrícula de valores en todo el dominio de entrada. Una vez que tenemos la cuadrícula de predicciones, podemos trazar los valores y su etiqueta de clase. Se podría usar un diagrama de dispersión si se tomara una cuadrícula lo suficientemente fina. Un mejor enfoque es utilizar un gráfico de contorno que pueda interpolar los colores entre los puntos. Se puede utilizar la . función contourf() Matplotlib Esto requiere algunos pasos. Primero, necesitamos definir una cuadrícula de puntos a través del espacio de características. Para hacer esto, podemos encontrar los valores mínimos y máximos para cada función y expandir la cuadrícula un paso más allá para asegurar que se cubra todo el espacio de funciones. ... # define bounds the domain min1, max1 = X[:, ].min() , X[:, ].max()+ min2, max2 = X[:, ].min() , X[:, ].max()+ of 0 -1 0 1 1 -1 1 1 Entonces podemos crear una muestra uniforme en cada dimensión usando el función a una resolución elegida. Usaremos una resolución de 0.1 en este caso. arange() ... # define the x and y scale x1grid = arange(min1, max1, ) x2grid = arange(min2, max2, ) 0.1 0.1 Ahora tenemos que convertir esto en una cuadrícula. Podemos usar la para crear una cuadrícula a partir de estos dos vectores. función meshgrid() NumPy Si la primera característica x1 es nuestro eje x del espacio de características, entonces necesitamos una fila de valores x1 de la cuadrícula para cada punto en el eje y. De manera similar, si tomamos x2 como nuestro eje y del espacio de características, entonces necesitamos una columna de valores x2 de la cuadrícula para cada punto en el eje x. los hará esto por nosotros, duplicando las filas y columnas según sea necesario. Devuelve dos cuadrículas para los dos vectores de entrada. La primera cuadrícula de valores x y la segunda de valores y, organizadas en una cuadrícula de filas y columnas de tamaño adecuado en todo el espacio de características. meshgrid() ... # create all the lines and rows the grid xx, yy = meshgrid(x1grid, x2grid) of of Luego, debemos aplanar la cuadrícula para crear muestras que podamos introducir en el modelo y hacer una predicción. Para hacer esto, primero, aplanamos cada cuadrícula en un vector. ... # flatten each grid to a vector r1, r2 = xx.flatten(), yy.flatten() r1, r2 = r1.reshape((len(r1), )), r2.reshape((len(r2), )) 1 1 Luego apilamos los vectores uno al lado del otro como columnas en un conjunto de datos de entrada, por ejemplo, como nuestro conjunto de datos de entrenamiento original, pero con una resolución mucho más alta. ... # horizontal stack vectors to create x1,x2 input the model grid = hstack((r1,r2)) for Luego podemos introducir esto en nuestro modelo y obtener una predicción para cada punto de la cuadrícula. ... # make predictions the grid yhat = model.predict(grid) for Hasta aquí todo bien. Tenemos una cuadrícula de valores en el espacio de características y las etiquetas de clase según lo predicho por nuestro modelo. A continuación, necesitamos trazar la cuadrícula de valores como un gráfico de contorno. La toma cuadrículas separadas para cada eje, tal como lo devolvió nuestra llamada anterior a meshgrid(). ¡Excelente! función contourf() Entonces podemos usar xx e yy que preparamos anteriormente y simplemente remodelar las predicciones (yhat) del modelo para que tengan la misma forma. ... # reshape the predictions back into a grid zz = yhat.reshape(xx.shape) Luego trazamos la superficie de decisión con un mapa de color de dos colores. ... # plot the grid x, y and z values a surface pyplot.contourf(xx, yy, zz, cmap= ) of as 'Paired' Luego podemos trazar los puntos reales del conjunto de datos en la parte superior para ver qué tan bien fueron separados por la superficie de decisión de la regresión logística. El ejemplo completo de trazar una superficie de decisión para un modelo de regresión logística en nuestro conjunto de datos de clasificación binaria sintética se enumera a continuación. En [8]: numpy as np from sklearn.datasets make_blobs from sklearn.linear_model LogisticRegression X, = make_blobs( min1, = X[:, ].min()- , X[:, ].max()+ min2, = X[:, ].min()- , X[:, ].max()+ = np.arange(min1, max1, ) = np.arange(min2, max2, ) xx, = np.meshgrid(x1grid, x2grid) r1, = xx.flatten(), yy.flatten() r1, = r1.reshape((len(r1), )), r2.reshape((len(r2), )) = np.hstack((r1,r2)) = LogisticRegression() model.fit(X, y) = model.predict(grid) = yhat.reshape(xx.shape) plt.contourf(xx, yy, zz, for class_value range( ): = np.where( == class_value) plt.scatter(X[row_ix, ], X[row_ix, ], # decision surface for logistic regression on a binary classification dataset import import import # generate dataset y n_samples=1000, centers=2, n_features=2, random_state=1, cluster_std=3) # define bounds of the domain max1 0 1 0 1 max2 1 1 1 1 # define the x and y scale x1grid 0.1 x2grid 0.1 # create all of the lines and rows of the grid yy # flatten each grid to a vector r2 r2 1 1 # horizontal stack vectors to create x1,x2 input for the model grid # define the model model # fit the model # make predictions for the grid yhat # reshape the predictions back into a grid zz # plot the grid of x, y and z values as a surface cmap='Paired') # create scatter plot for samples from each class in 2 # get row indexes for samples with this class row_ix y # create scatter of these samples 0 1 cmap='Paired') Podemos agregar más profundidad a la superficie de decisión usando el modelo para predecir probabilidades en lugar de etiquetas de clase. ... # make predictions the grid yhat = model.predict_proba(grid) # keep just the probabilities = yhat[:, ] for for 0 class yhat 0 Cuando se grafica, podemos ver qué tan seguro o probable es que cada punto en el espacio de características pertenezca a cada una de las etiquetas de clase, como lo ve el modelo. Podemos usar un que tenga gradaciones y mostrar una leyenda para que podamos interpretar los colores. mapa de color diferente ... # plot the grid x, y and z values a surface c = pyplot.contourf(xx, yy, zz, cmap= ) # add a legend, called a color bar pyplot.colorbar(c) of as 'RdBu' El ejemplo completo de creación de una superficie de decisión usando probabilidades se muestra a continuación. En [9]: # probability decision surface logistic regression on a binary classification dataset numpy np sklearn.datasets make_blobs sklearn.linear_model LogisticRegression # generate dataset X, y = make_blobs(n_samples= , centers= , n_features= , random_state= , cluster_std= ) # define bounds the domain min1, max1 = X[:, ].min() , X[:, ].max()+ min2, max2 = X[:, ].min() , X[:, ].max()+ # define the x and y scale x1grid = np.arange(min1, max1, ) x2grid = np.arange(min2, max2, ) # create all the lines and rows the grid xx, yy = np.meshgrid(x1grid, x2grid) # flatten each grid to a vector r1, r2 = xx.flatten(), yy.flatten() r1, r2 = r1.reshape((len(r1), )), r2.reshape((len(r2), )) # horizontal stack vectors to create x1,x2 input the model grid = np.hstack((r1,r2)) # define the model model = LogisticRegression() # fit the model model.fit(X, y) # make predictions the grid yhat = model.predict_proba(grid) # keep just the probabilities = yhat[:, ] # reshape the predictions back into a grid zz = yhat.reshape(xx.shape) # plot the grid x, y and z values a surface c = plt.contourf(xx, yy, zz, cmap= ) # add a legend, called a color bar plt.colorbar(c) # create scatter plot samples each = np.where(y == class_value) # create scatter these samples plt.scatter(X[row_ix, ], X[row_ix, ], cmap= ) for import as from import from import 1000 2 2 1 3 of 0 -1 0 1 1 -1 1 1 0.1 0.1 of of 1 1 for for for 0 class yhat 0 of as 'RdBu' for from (2): # class for class_value in range get row indexes for samples with this class row_ix of 0 1 'Paired' Ejecutar el ejemplo predice la probabilidad de pertenencia a una clase para cada punto de la cuadrícula en el espacio de características y traza el resultado. Aquí, podemos ver que el modelo no está seguro (colores más claros) en la mitad del dominio, dado el ruido de muestreo en esa área del espacio de características. También podemos ver que el modelo tiene mucha confianza (colores completos) en las mitades inferior izquierda y superior derecha del dominio. Juntas, las superficies de decisión de probabilidad y clase nítidas son poderosas herramientas de diagnóstico para comprender su modelo y cómo divide el espacio de características para su tarea de modelado predictivo. Trace la superficie de decisión de un árbol de decisión en el conjunto de datos del iris Trace la superficie de decisión de un árbol de decisión entrenado en pares de características del conjunto de datos del iris. Consulte para obtener más información sobre el estimador. el árbol de decisiones Para cada par de características del iris, el árbol de decisión aprende límites de decisión hechos de combinaciones de reglas de umbral simples deducidas de las muestras de entrenamiento. También mostramos la estructura de árbol de un modelo basado en todas las características. En [10]: numpy np matplotlib.pyplot plt sklearn.datasets load_iris sklearn.tree DecisionTreeClassifier, plot_tree # Parameters n_classes = plot_colors = plot_step = # Load data iris = load_iris() pairidx, pair enumerate([[ , ], [ , ], [ , ], [ , ], [ , ], [ , ]]): # We only take the two corresponding features X = iris.data[:, pair] y = iris.target # Train clf = DecisionTreeClassifier().fit(X, y) # Plot the decision boundary plt.subplot( , , pairidx + ) x_min, x_max = X[:, ].min() - , X[:, ].max() + y_min, y_max = X[:, ].min() - , X[:, ].max() + xx, yy = np.meshgrid(np.arange(x_min, x_max, plot_step), np.arange(y_min, y_max, plot_step)) plt.tight_layout(h_pad= , w_pad= , pad= ) Z = clf.predict(np.c_[xx.ravel(), yy.ravel()]) Z = Z.reshape(xx.shape) cs = plt.contourf(xx, yy, Z, cmap=plt.cm.RdYlBu) plt.xlabel(iris.feature_names[pair[ ]]) plt.ylabel(iris.feature_names[pair[ ]]) # Plot the training points i, color zip(range(n_classes), plot_colors): idx = np.where(y == i) plt.scatter(X[idx, ], X[idx, ], c=color, label=iris.target_names[i], cmap=plt.cm.RdYlBu, edgecolor= , s= ) plt.suptitle( ) plt.legend(loc= , borderpad= , handletextpad= ) plt.axis( ) plt.figure() clf = DecisionTreeClassifier().fit(iris.data, iris.target) plot_tree(clf, filled=True) plt.show() import as import as from import from import 3 "ryb" 0.02 for in 0 1 0 2 0 3 1 2 1 3 2 3 2 3 1 0 1 0 1 1 1 1 1 0.5 0.5 2.5 0 1 for in 0 1 'black' 15 "Decision surface of a decision tree using paired features" 'lower right' 0 0 "tight" Resumen En este tutorial, descubrió cómo trazar una superficie de decisión para un algoritmo de aprendizaje automático de clasificación. Específicamente, aprendiste: La superficie de decisión es una herramienta de diagnóstico para comprender cómo un algoritmo de clasificación divide el espacio de características. Cómo trazar una superficie de decisión para usar etiquetas de clase nítidas para un algoritmo de aprendizaje automático. Cómo trazar e interpretar una superficie de decisión usando probabilidades predichas. ¿Tiene usted alguna pregunta? Haga sus preguntas en la sección de comentarios de la publicación, trato de hacer lo mejor para responder. Publicado anteriormente en h ttps://kvssetty.com/plot-a-decision-surface-for-machine-learning-algorithms-in-python/