de ejecutar el ejemplo de código precedente, deberíamos ver el siguiente diagrama de dispersión:
El diagrama de dispersión anterior muestra la distribución de las muestras de flor en el conjunto de datos Iris sobre los dos ejes de características, longitud del pétalo y longitud del sépalo. En este subespacio de características bidimensional, podemos ver que un límite de decisión lineal puede ser suficiente para separar flores Setosa de flores Versicolor. Por tanto, un clasificador lineal como el perceptrón podría ser capaz de clasificar las flores en este conjunto de datos perfectamente.
Ahora, ha llegado el momento de entrenar nuestro algoritmo de perceptrón en el subconjunto de datos Iris que acabamos de extraer. Además, reflejaremos en un gráfico el error de clasificación incorrecta para cada época para comprobar si el algoritmo ha convergido y encontrado un límite de decisión que separa las dos clases de flor Iris:
>>> ppn = Perceptron(eta=0.1, n_iter=10)
>>> ppn.fit(X, y)
>>> plt.plot(range(1, len(ppn.errors_) + 1),
... ppn.errors_, marker='o')
>>> plt.xlabel('Epochs')
>>> plt.ylabel('Number of updates')
>>> plt.show()
Después de ejecutar el código anterior, deberíamos ver el diagrama de los errores de clasificación incorrecta frente al número de épocas, como se muestra a continuación:
Como podemos ver en el diagrama anterior, nuestro perceptrón ha convergido después de seis épocas y debería ser capaz de clasificar perfectamente las muestras de entrenamiento. Vamos a implementar una pequeña función de conveniencia para visualizar los límites de decisión para dos conjuntos de datos bidimensionales:
from matplotlib.colors import ListedColormap
def plot_decision_regions(X, y, classifier, resolution=0.02):
# definir un generador de marcadores y un mapa de colores
markers = ('s', 'x', 'o', '^', 'v')
colors = ('red', 'blue', 'lightgreen', 'gray', 'cyan')
cmap = ListedColormap(colors[:len(np.unique(y))])
# representar la superficie de decisión
x1_min, x1_max = X[:, 0].min() - 1, X[:, 0].max() + 1
x2_min, x2_max = X[:, 1].min() - 1, X[:, 1].max() + 1
xx1, xx2 = np.meshgrid(np.arange(x1_min, x1_max, resolution),
np.arange(x2_min, x2_max, resolution))
Z = classifier.predict(np.array([xx1.ravel(), xx2.ravel()]).T)
Z = Z.reshape(xx1.shape)
plt.contourf(xx1, xx2, Z, alpha=0.3, cmap=cmap)
plt.xlim(xx1.min(), xx1.max())
plt.ylim(xx2.min(), xx2.max())
# representar muestras de clase
for idx, cl in enumerate(np.unique(y)):
plt.scatter(x=X[y == cl, 0],
y=X[y == cl, 1],
alpha=0.8,
c=colors[idx],
marker=markers[idx],
label=cl,
edgecolor='black')
En primer lugar, definimos un número de colors y markers y creamos un mapa de colores a partir de la lista de colores a través de ListedColormap. A continuación, determinamos los valores mínimos y máximos para las dos características y utilizamos los vectores de características para crear un par de matrices de cuadrícula xx1 y xx2 mediante la función meshgrid de NumPy. Como hemos entrenado nuestro clasificador de perceptrón en dos dimensiones de características, necesitamos acoplar las matrices y crear una matriz que tenga el mismo número de columnas que el subconjunto de entrenamiento Iris. Para ello, podemos utilizar el método predict para predecir las etiquetas de clase Z de los correspondientes puntos de la cuadrícula. Después de remodelar las etiquetas de clase Z predichas en una cuadrícula con las mismas dimensiones que xx1 y xx2, ya podemos dibujar un diagrama de contorno con la función contourf de Matplotlib, que mapea las diferentes regiones de decisión en distintos colores para cada clase predicha en la matriz de cuadrícula:
>>> plot_decision_regions(X, y, classifier=ppn)
>>> plt.xlabel('sepal length [cm]')
>>> plt.ylabel('petal length [cm]')
>>> plt.legend(loc='upper left')
>>> plt.show()
Después de ejecutar el ejemplo de código anterior, deberíamos ver un diagrama de las regiones de decisión, como se muestra en la siguiente figura:
Como podemos ver en el diagrama, el perceptrón ha aprendido un límite de decisión capaz de clasificar perfectamente todas las muestras de flor en el subconjunto de entrenamiento Iris.
Aunque el perceptrón ha clasificado a la perfección las dos clases de flor Iris, la convergencia es uno de los mayores problemas del perceptrón. Frank Rosenblatt probó matemáticamente que la regla de aprendizaje del perceptrón converge si las dos clases pueden ser separadas por un hiperplano lineal. Sin embargo, si las clases no pueden ser separadas perfectamente por un límite de decisión lineal, los pesos no dejarán nunca de actualizarse a menos que indiquemos un número máximo de épocas. |
Neuronas lineales adaptativas y la convergencia del aprendizaje
En esta sección, echaremos un vistazo a otro tipo de red neuronal de capa única: las neuronas lineales adaptativas, en inglés ADAptive LInear NEuron (Adaline). Adaline fue publicada por Bernard Widrow y su alumno Ted Hoff, pocos años después del algoritmo de perceptrón de Frank Rosenblatt, y puede considerarse como una mejora de este último. (Puedes consultar An Adaptive "Adaline" Neuron Using Chemical "Memistors", Technical Report Number 1553-2, B. Widrow and others, Stanford Electron Labs, Stanford, CA, October 1960).
El algoritmo Adaline es especialmente interesante porque ilustra los conceptos clave para definir y minimizar las funciones de coste continuas. Esto sienta las bases para la comprensión de algoritmos de aprendizaje automático más avanzados para la clasificación, como la regresión logística, máquinas de vectores de soporte y modelos de regresión, que trataremos en capítulos posteriores.
La diferencia clave entre la regla Adaline (también conocida como regla Widrow-Hoff) y el perceptrón de Rosenblatt es que los pesos se actualizan en base a una función de activación lineal en vez de en base a una función escalón unitario como sucede en el perceptrón. En Adaline, esta función de activación lineal
Mientras que la función de activación lineal se utiliza para aprender los pesos, seguimos utilizando una función de umbral que realiza la predicción final, que es parecida a la función escalón unitario que hemos visto anteriormente. Las diferencias principales entre el perceptrón y el algoritmo