ofrece implementaciones alternativas mediante la clase SGDClassifier, que también soporta aprendizaje online a través del método partial_fit. El concepto que se esconde detrás de la clase SGDClassifier es similar al algoritmo de gradiente estocástico que implementamos en el Capítulo 2, Entrenar algoritmos simples de aprendizaje automático para clasificación para Adaline. Podríamos inicializar la versión del descenso del gradiente estocástico, una regresión logística y una máquina de vectores de soporte con parámetros predeterminados de la siguiente forma:
>>> from sklearn.linear_model import SGDClassifier
>>> ppn = SGDClassifier(loss='perceptron')
>>> lr = SGDClassifier(loss='log')
>>> svm = SGDClassifier(loss='hinge')
Resolver problemas no lineales con una SVM kernelizada
Otra razón por la cual las SVM gozan de gran popularidad entre los que trabajan con el aprendizaje automático es que pueden ser fácilmente kernelizadas para resolver problemas de clasificación no lineal. Antes de tratar el concepto principal que se esconde detrás de una SVM kernelizada, vamos primero a crear un conjunto de datos de muestra para ver qué aspecto tendría un problema de clasificación no lineal.
Métodos kernel para datos inseparables lineales
Con el siguiente código, crearemos un sencillo conjunto de datos que tiene la forma de una puerta XOR mediante la función logical_or de NumPy, donde se asignarán 100 muestras a la etiqueta de clase 1 y otras 100 a la etiqueta de clase -1:
>>> import matplotlib.pyplot as plt
>>> import numpy as np
>>> np.random.seed(1)
>>> X_xor = np.random.randn(200, 2)
>>> y_xor = np.logical_xor(X_xor[:, 0] > 0,
... X_xor[:, 1] > 0)
>>> y_xor = np.where(y_xor, 1, -1)
>>> plt.scatter(X_xor[y_xor == 1, 0],
... X_xor[y_xor == 1, 1],
... c='b', marker='x',
... label='1')
>>> plt.scatter(X_xor[y_xor == -1, 0],
... X_xor[y_xor == -1, 1],
... c='r',
... marker='s',
... label='-1')
>>> plt.xlim([-3, 3])
>>> plt.ylim([-3, 3])
>>> plt.legend(loc='best')
>>> plt.show()
Después de ejecutar el código, tendremos un conjunto de datos XOR con ruido aleatorio, como se muestra en la siguiente imagen:
Evidentemente, no podríamos separar correctamente las muestras de las clases positivas y negativas utilizando un hiperplano lineal como límite de decisión a través de la regresión logística lineal o del modelo de SVM lineal que tratamos en secciones anteriores.
La idea fundamental que hay detrás de los métodos kernel para tratar datos inseparables lineales como estos es crear combinaciones no lineales de las características originales para proyectarlas hacia un espacio de dimensiones mayores, mediante una función de mapeo
Esto nos permite separar las dos clases que aparecen en el gráfico mediante un hiperplano lineal que se convierte en un límite de decisión no lineal si lo volvemos a proyectar en el espacio de características original:
El truco de kernel para encontrar hiperplanos separados en un espacio de mayor dimensionalidad
Para resolver un problema no lineal utilizando una SVM, debemos transformar los datos de entrenamiento en un espacio de características de mayor dimensionalidad mediante una función de mapeo
Sin embargo, un problema con este enfoque de mapeo es que la construcción de nuevas características es computacionalmente muy costosa, especialmente si tratamos con datos de mayor dimensionalidad. Y aquí es donde el denominado truco de kernel entra en juego. No entraremos mucho en detalle sobre cómo resolver la tarea de programación cuadrática para entrenar un SVM, ya que a la práctica todo cuanto necesitamos es sustituir el producto escalar
Uno de los kernels más ampliamente utilizados es la Función de base radial (RBF), también denominada kernel Gaussiana:
Habitualmente se simplifica como:
En este caso,
Más o menos, el término kernel puede ser interpretado como una función de similitud entre un par de muestras. El signo menos invierte la medida de distancia de una puntuación de similitud y, debido al término exponencial, la puntuación de similitud resultante caerá en un rango entre 1 (para muestras exactamente similares) y 0 (para muestras muy diferentes).
Ahora que ya hemos definido a grandes rasgos cuanto hay detrás del truco de kernel, podemos entrenar una SVM kernelizada que sea capaz de dibujar un límite de decisión no lineal que separe correctamente los datos XOR. En este caso, simplemente utilizamos la clase SVC de scikit-learn que importamos anteriormente y sustituimos el parámetro kernel='linear' por kernel='rbf':
>>> svm = SVC(kernel='rbf', random_state=1, gamma=0.10, C=10.0)
>>> svm.fit(X_xor, y_xor)
>>> plot_decision_regions(X_xor, y_xor, classifier=svm)
>>> plt.legend(loc='upper left')
>>> plt.show()
Como podemos ver en el diagrama resultante, la SVM kernelizada separa los datos XOR relativamente bien:
El parámetro