paint-brush
Cómo trazar un límite de decisión para algoritmos de aprendizaje automático en Pythonpor@kvssetty
72,119 lecturas
72,119 lecturas

Cómo trazar un límite de decisión para algoritmos de aprendizaje automático en Python

por [email protected]11m2020/09/10
Read on Terminal Reader
Read this story w/o Javascript

Demasiado Largo; Para Leer

Cómo trazar un límite de decisión para algoritmos de aprendizaje automático en Python es un diagnóstico popular para comprender las decisiones tomadas por un algoritmo de clasificación en la superficie de decisión. 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. 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 por etiqueta de clase. El código fuente completo está disponible en mi repositorio git.

Company Mentioned

Mention Thumbnail
featured image - Cómo trazar un límite de decisión para algoritmos de aprendizaje automático en Python
kvssetty@gmail.com HackerNoon profile picture

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 superficie de decisión . 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.

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:

  1. Superficie de decisión
  2. Conjunto de datos y modelo
  3. Trazar una superficie de decisión
  4. 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 n variables de entrada, el espacio de características sería un hiperplano de n dimensiones . Espacios difíciles de visualizar más allá de las tres 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 superficie de decisión o límite de decisión y proporciona una herramienta de diagnóstico para comprender un modelo en una tarea de modelado de clasificación predictiva.

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 función scikit-learn make_blobs() 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.

 ... # generate dataset X, y = make_blobs(n_samples= 1000 , centers= 2 , n_features= 2 , random_state= 26 , cluster_std= 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 for samples from each class import numpy as np import pandas as pd import Matplotlib . pyplot as plt % matplotlib inline Import seaborn as sns sns . scatterplot ( x = "x1" , y= "x2" , hue= 'class' , data=data)

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 import numpy as np import pandas as pd import matplotlib.pyplot as plt %matplotlib inline import seaborn as sns from sklearn.datasets import make_blobs # generate dataset X, y = make_blobs(n_samples= 1000 , centers= 2 , n_features= 2 , random_state= 1 , cluster_std= 3 )

En 2]:

 X_df = pd.DataFrame(X, columns=[ 'x1' , 'x2' ]) X_df.head()

Salida[2]:

En 3]:

 y_df = pd.DataFrame(y, columns=[ "class" ])

En [4]:

 y_df.head()

Fuera[4]:

En [5]:

 frames = [ X_df , y_df] data = pd.concat( frames , axis =1) data .head()

Fuera[5]:

En [6]:

 # create scatter plot for samples from each class sns . scatterplot ( x = "x1" , y= "x2" , hue= 'class' , data=data)

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.

 ... # define the model model = LogisticRegression() # fit the model model.fit(X, y)

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( 'Accuracy: %.3f' % acc)

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 of fitting and evaluating a model on the classification dataset from sklearn.datasets import make_blobs from sklearn.linear_model import LogisticRegression from sklearn.metrics import accuracy_score # generate dataset X, y = make_blobs(n_samples= 1000 , centers= 2 , n_features= 2 , random_state= 1 , cluster_std= 3 ) # 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( 'Accuracy: %.3f' % acc)
 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 of the domain min1, max1 = X[:, 0 ].min() -1 , X[:, 0 ].max()+ 1 min2, max2 = X[:, 1 ].min() -1 , X[:, 1 ].max()+ 1

Entonces podemos crear una muestra uniforme en cada dimensión usando el

 arange()
función a una resolución elegida. Usaremos una resolución de 0.1 en este caso.

 ... # define the x and y scale x1grid = arange(min1, max1, 0.1 ) x2grid = arange(min2, max2, 0.1 )

Ahora tenemos que convertir esto en una cuadrícula.

Podemos usar la función meshgrid() NumPy para crear una cuadrícula a partir de estos dos vectores.

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

 meshgrid()
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.

 ... # create all of the lines and rows of the grid xx, yy = meshgrid(x1grid, x2grid)

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), 1 )), r2.reshape((len(r2), 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 for the model grid = hstack((r1,r2))

Luego podemos introducir esto en nuestro modelo y obtener una predicción para cada punto de la cuadrícula.

 ... # make predictions for the grid yhat = model.predict(grid)

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 función contourf() toma cuadrículas separadas para cada eje, tal como lo devolvió nuestra llamada anterior a meshgrid(). ¡Excelente!

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 of x, y and z values as a surface pyplot.contourf(xx, yy, zz, cmap= '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]:

 # decision surface for logistic regression on a binary classification dataset import numpy as np from sklearn.datasets import make_blobs from sklearn.linear_model import LogisticRegression # generate dataset X, y = make_blobs( n_samples=1000, centers=2, n_features=2, random_state=1, cluster_std=3) # define bounds of the domain min1, max1 = X[:, 0 ].min()- 1 , X[:, 0 ].max()+ 1 min2, max2 = X[:, 1 ].min()- 1 , X[:, 1 ].max()+ 1 # define the x and y scale x1grid = np.arange(min1, max1, 0.1 ) x2grid = np.arange(min2, max2, 0.1 ) # create all of the lines and rows of 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), 1 )), r2.reshape((len(r2), 1 )) # horizontal stack vectors to create x1,x2 input for the model grid = np.hstack((r1,r2)) # define the model model = LogisticRegression() # fit the model model.fit(X, y) # make predictions for the grid yhat = model.predict(grid) # reshape the predictions back into a grid zz = yhat.reshape(xx.shape) # plot the grid of x, y and z values as a surface plt.contourf(xx, yy, zz, cmap='Paired') # create scatter plot for samples from each class for class_value in range( 2 ): # get row indexes for samples with this class row_ix = np.where( y == class_value) # create scatter of these samples plt.scatter(X[row_ix, 0 ], X[row_ix, 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 for the grid yhat = model.predict_proba(grid) # keep just the probabilities for class 0 yhat = 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 mapa de color diferente que tenga gradaciones y mostrar una leyenda para que podamos interpretar los colores.

 ... # plot the grid of x, y and z values as a surface c = pyplot.contourf(xx, yy, zz, cmap= 'RdBu' ) # add a legend, called a color bar pyplot.colorbar(c)

El ejemplo completo de creación de una superficie de decisión usando probabilidades se muestra a continuación.

En [9]:

 # probability decision surface for logistic regression on a binary classification dataset import numpy as np from sklearn.datasets import make_blobs from sklearn.linear_model import LogisticRegression # generate dataset X, y = make_blobs(n_samples= 1000 , centers= 2 , n_features= 2 , random_state= 1 , cluster_std= 3 ) # define bounds of the domain min1, max1 = X[:, 0 ].min() -1 , X[:, 0 ].max()+ 1 min2, max2 = X[:, 1 ].min() -1 , X[:, 1 ].max()+ 1 # define the x and y scale x1grid = np.arange(min1, max1, 0.1 ) x2grid = np.arange(min2, max2, 0.1 ) # create all of the lines and rows of 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), 1 )), r2.reshape((len(r2), 1 )) # horizontal stack vectors to create x1,x2 input for the model grid = np.hstack((r1,r2)) # define the model model = LogisticRegression() # fit the model model.fit(X, y) # make predictions for the grid yhat = model.predict_proba(grid) # keep just the probabilities for class 0 yhat = yhat[:, 0 ] # reshape the predictions back into a grid zz = yhat.reshape(xx.shape) # plot the grid of x, y and z values as a surface c = plt.contourf(xx, yy, zz, cmap= 'RdBu' ) # add a legend, called a color bar plt.colorbar(c) # create scatter plot for samples from each class for class_value in range (2): # get row indexes for samples with this class row_ix = np.where(y == class_value) # create scatter of these samples plt.scatter(X[row_ix, 0 ], X[row_ix, 1 ], cmap= '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 el árbol de decisiones para obtener más información sobre el estimador.

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]:

 import numpy as np import matplotlib.pyplot as plt from sklearn.datasets import load_iris from sklearn.tree import DecisionTreeClassifier, plot_tree # Parameters n_classes = 3 plot_colors = "ryb" plot_step = 0.02 # Load data iris = load_iris() for pairidx, pair in enumerate([[ 0 , 1 ], [ 0 , 2 ], [ 0 , 3 ], [ 1 , 2 ], [ 1 , 3 ], [ 2 , 3 ]]): # 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( 2 , 3 , pairidx + 1 ) x_min, x_max = X[:, 0 ].min() - 1 , X[:, 0 ].max() + 1 y_min, y_max = X[:, 1 ].min() - 1 , X[:, 1 ].max() + 1 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= 0.5 , w_pad= 0.5 , pad= 2.5 ) 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[ 0 ]]) plt.ylabel(iris.feature_names[pair[ 1 ]]) # Plot the training points for i, color in zip(range(n_classes), plot_colors): idx = np.where(y == i) plt.scatter(X[idx, 0 ], X[idx, 1 ], c=color, label=iris.target_names[i], cmap=plt.cm.RdYlBu, edgecolor= 'black' , s= 15 ) plt.suptitle( "Decision surface of a decision tree using paired features" ) plt.legend(loc= 'lower right' , borderpad= 0 , handletextpad= 0 ) plt.axis( "tight" ) plt.figure() clf = DecisionTreeClassifier().fit(iris.data, iris.target) plot_tree(clf, filled=True) plt.show()

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/