Máquina de vectores de soporte (SVM)
Introducción a SVM
Las máquinas de vectores de soporte (SVM) son algoritmos de aprendizaje automático supervisados potentes pero flexibles que se utilizan tanto para clasificación como para regresión. Pero generalmente se usan en problemas de clasificación. En la década de 1960, se introdujeron por primera vez las SVM, pero luego se refinaron en 1990. Las SVM tienen su forma única de implementación en comparación con otros algoritmos de aprendizaje automático. Últimamente, son extremadamente populares debido a su capacidad para manejar múltiples variables continuas y categóricas.
Funcionamiento de SVM
Un modelo SVM es básicamente una representación de diferentes clases en un hiperplano en un espacio multidimensional. SVM generará el hiperplano de manera iterativa para minimizar el error. El objetivo de SVM es dividir los conjuntos de datos en clases para encontrar un hiperplano marginal máximo (MMH).
Los siguientes son conceptos importantes en SVM:
Support Vectors- Los puntos de datos que están más cerca del hiperplano se denominan vectores de soporte. La línea de separación se definirá con la ayuda de estos puntos de datos.
Hyperplane - Como podemos ver en el diagrama anterior, es un plano o espacio de decisión que se divide entre un conjunto de objetos de diferentes clases.
Margin- Puede definirse como el espacio entre dos líneas en los puntos de datos del armario de diferentes clases. Se puede calcular como la distancia perpendicular desde la línea a los vectores de apoyo. Un margen grande se considera un buen margen y un margen pequeño se considera un margen incorrecto.
El objetivo principal de SVM es dividir los conjuntos de datos en clases para encontrar un hiperplano marginal máximo (MMH) y se puede hacer en los siguientes dos pasos:
Primero, SVM generará hiperplanos iterativamente que segrega las clases de la mejor manera.
Luego, elegirá el hiperplano que separa las clases correctamente.
Implementando SVM en Python
Para implementar SVM en Python, comenzaremos con la importación de bibliotecas estándar de la siguiente manera:
import numpy as np
import matplotlib.pyplot as plt
from scipy import stats
import seaborn as sns; sns.set()
A continuación, estamos creando un conjunto de datos de muestra, con datos separables linealmente, de sklearn.dataset.sample_generator para la clasificación usando SVM -
from sklearn.datasets.samples_generator import make_blobs
X, y = make_blobs(n_samples=100, centers=2, random_state=0, cluster_std=0.50)
plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='summer');
El siguiente sería el resultado después de generar un conjunto de datos de muestra con 100 muestras y 2 grupos:
Sabemos que SVM admite la clasificación discriminativa. divide las clases entre sí simplemente encontrando una línea en el caso de dos dimensiones o una variedad en el caso de múltiples dimensiones. Se implementa en el conjunto de datos anterior de la siguiente manera:
xfit = np.linspace(-1, 3.5)
plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='summer')
plt.plot([0.6], [2.1], 'x', color='black', markeredgewidth=4, markersize=12)
for m, b in [(1, 0.65), (0.5, 1.6), (-0.2, 2.9)]:
plt.plot(xfit, m * xfit + b, '-k')
plt.xlim(-1, 3.5);
La salida es la siguiente:
Podemos ver en la salida anterior que hay tres separadores diferentes que discriminan perfectamente las muestras anteriores.
Como se discutió, el objetivo principal de SVM es dividir los conjuntos de datos en clases para encontrar un hiperplano marginal máximo (MMH), por lo tanto, en lugar de dibujar una línea cero entre clases, podemos dibujar alrededor de cada línea un margen de algún ancho hasta el punto más cercano. Se puede hacer de la siguiente manera:
xfit = np.linspace(-1, 3.5)
plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='summer')
for m, b, d in [(1, 0.65, 0.33), (0.5, 1.6, 0.55), (-0.2, 2.9, 0.2)]:
yfit = m * xfit + b
plt.plot(xfit, yfit, '-k')
plt.fill_between(xfit, yfit - d, yfit + d, edgecolor='none',
color='#AAAAAA', alpha=0.4)
plt.xlim(-1, 3.5);
De la imagen de arriba en la salida, podemos observar fácilmente los “márgenes” dentro de los clasificadores discriminativos. SVM elegirá la línea que maximice el margen.
A continuación, utilizaremos el clasificador de vectores de soporte de Scikit-Learn para entrenar un modelo SVM sobre estos datos. Aquí, estamos usando kernel lineal para ajustar SVM de la siguiente manera:
from sklearn.svm import SVC # "Support vector classifier"
model = SVC(kernel='linear', C=1E10)
model.fit(X, y)
La salida es la siguiente:
SVC(C=10000000000.0, cache_size=200, class_weight=None, coef0=0.0,
decision_function_shape='ovr', degree=3, gamma='auto_deprecated',
kernel='linear', max_iter=-1, probability=False, random_state=None,
shrinking=True, tol=0.001, verbose=False)
Ahora, para una mejor comprensión, lo siguiente trazará las funciones de decisión para 2D SVC:
def decision_function(model, ax=None, plot_support=True):
if ax is None:
ax = plt.gca()
xlim = ax.get_xlim()
ylim = ax.get_ylim()
Para evaluar el modelo, necesitamos crear una cuadrícula de la siguiente manera:
x = np.linspace(xlim[0], xlim[1], 30)
y = np.linspace(ylim[0], ylim[1], 30)
Y, X = np.meshgrid(y, x)
xy = np.vstack([X.ravel(), Y.ravel()]).T
P = model.decision_function(xy).reshape(X.shape)
A continuación, necesitamos trazar los límites y márgenes de decisión de la siguiente manera:
ax.contour(X, Y, P, colors='k',
levels=[-1, 0, 1], alpha=0.5,
linestyles=['--', '-', '--'])
Ahora, grafique de manera similar los vectores de soporte de la siguiente manera:
if plot_support:
ax.scatter(model.support_vectors_[:, 0],
model.support_vectors_[:, 1],
s=300, linewidth=1, facecolors='none');
ax.set_xlim(xlim)
ax.set_ylim(ylim)
Ahora, use esta función para ajustar nuestros modelos de la siguiente manera:
plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='summer')
decision_function(model);
Podemos observar a partir de la salida anterior que un clasificador SVM se ajusta a los datos con márgenes, es decir, líneas discontinuas y vectores de soporte, los elementos fundamentales de este ajuste, tocando la línea discontinua. Estos puntos de vectores de soporte se almacenan en el atributo support_vectors_ del clasificador de la siguiente manera:
model.support_vectors_
La salida es la siguiente:
array([[0.5323772 , 3.31338909],
[2.11114739, 3.57660449],
[1.46870582, 1.86947425]])
Núcleos SVM
En la práctica, el algoritmo SVM se implementa con el kernel que transforma un espacio de datos de entrada en la forma requerida. SVM utiliza una técnica llamada truco del núcleo en la que el núcleo toma un espacio de entrada de baja dimensión y lo transforma en un espacio de dimensión superior. En palabras simples, el kernel convierte los problemas no separables en problemas separables al agregarle más dimensiones. Hace que SVM sea más potente, flexible y preciso. Los siguientes son algunos de los tipos de kernel utilizados por SVM:
Kernel lineal
Se puede utilizar como un producto escalar entre dos observaciones. La fórmula del núcleo lineal es la siguiente:
k (x, x i ) = suma (x * x i )
De la fórmula anterior, podemos ver que el producto entre dos vectores dice & es la suma de la multiplicación de cada par de valores de entrada.
Kernel polinomial
Es una forma más generalizada de kernel lineal y distingue el espacio de entrada curvo o no lineal. A continuación se muestra la fórmula para el núcleo polinomial:
K (x, xi) = 1 + suma (x * xi) ^ d
Aquí d es el grado de polinomio, que necesitamos especificar manualmente en el algoritmo de aprendizaje.
Kernel de función de base radial (RBF)
El kernel RBF, que se utiliza principalmente en la clasificación SVM, asigna el espacio de entrada en un espacio dimensional indefinido. La siguiente fórmula lo explica matemáticamente:
K (x, xi) = exp (-gamma * suma ((x - xi ^ 2))
Aquí, gamma varía de 0 a 1. Necesitamos especificarlo manualmente en el algoritmo de aprendizaje. Un buen valor predeterminado de gamma es 0,1.
Como implementamos SVM para datos linealmente separables, podemos implementarlo en Python para los datos que no son linealmente separables. Se puede hacer usando kernels.
Ejemplo
El siguiente es un ejemplo para crear un clasificador SVM usando kernels. Usaremos el conjunto de datos de iris de scikit-learn -
Comenzaremos importando los siguientes paquetes:
import pandas as pd
import numpy as np
from sklearn import svm, datasets
import matplotlib.pyplot as plt
Ahora, necesitamos cargar los datos de entrada -
iris = datasets.load_iris()
De este conjunto de datos, tomamos las dos primeras características de la siguiente manera:
X = iris.data[:, :2]
y = iris.target
A continuación, trazaremos los límites de SVM con datos originales de la siguiente manera:
x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
h = (x_max / x_min)/100
xx, yy = np.meshgrid(np.arange(x_min, x_max, h),
np.arange(y_min, y_max, h))
X_plot = np.c_[xx.ravel(), yy.ravel()]
Ahora, debemos proporcionar el valor del parámetro de regularización de la siguiente manera:
C = 1.0
A continuación, el objeto clasificador SVM se puede crear de la siguiente manera:
Svc_classifier = svm.SVC (kernel = 'lineal', C = C) .fit (X, y)
Z = svc_classifier.predict(X_plot)
Z = Z.reshape(xx.shape)
plt.figure(figsize=(15, 5))
plt.subplot(121)
plt.contourf(xx, yy, Z, cmap=plt.cm.tab10, alpha=0.3)
plt.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.Set1)
plt.xlabel('Sepal length')
plt.ylabel('Sepal width')
plt.xlim(xx.min(), xx.max())
plt.title('Support Vector Classifier with linear kernel')
Salida
Text(0.5, 1.0, 'Support Vector Classifier with linear kernel')
Para crear clasificador SVM con rbf kernel, podemos cambiar el kernel a rbf como sigue -
Svc_classifier = svm.SVC(kernel='rbf', gamma =‘auto’,C=C).fit(X, y)
Z = svc_classifier.predict(X_plot)
Z = Z.reshape(xx.shape)
plt.figure(figsize=(15, 5))
plt.subplot(121)
plt.contourf(xx, yy, Z, cmap=plt.cm.tab10, alpha=0.3)
plt.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.Set1)
plt.xlabel('Sepal length')
plt.ylabel('Sepal width')
plt.xlim(xx.min(), xx.max())
plt.title('Support Vector Classifier with rbf kernel')
Salida
Text(0.5, 1.0, 'Support Vector Classifier with rbf kernel')
Ponemos el valor de gamma en 'auto' pero también puede proporcionar su valor entre 0 y 1.
Pros y contras de los clasificadores SVM
Ventajas de los clasificadores SVM
Los clasificadores SVM ofrecen una gran precisión y funcionan bien con espacios de gran dimensión. Los clasificadores SVM básicamente usan un subconjunto de puntos de entrenamiento, por lo que el resultado usa muy menos memoria.
Contras de los clasificadores SVM
Tienen un alto tiempo de entrenamiento, por lo que en la práctica no son adecuados para grandes conjuntos de datos. Otra desventaja es que los clasificadores SVM no funcionan bien con clases superpuestas.