Support Vector Machine es otro algoritmo simple que funciona relativamente bien con menos costo computacional. En regresión, SVM funciona encontrando un hiperplano en un espacio N-dimensional (N número de características) que se ajusta a los datos multidimensionales mientras considera un margen. En la clasificación, se calcula el mismo hiperplano pero para clasificar claramente los puntos de datos nuevamente mientras se considera un margen. Puede haber muchos posibles hiperplanos que podrían seleccionarse. Sin embargo, el objetivo es encontrar el hiperplano con el margen máximo, es decir, la distancia máxima entre las clases objetivo.
SVM se puede usar tanto para problemas de regresión como de clasificación, pero se usa ampliamente para la clasificación.
Expliquemos algunos términos antes de continuar.
Kernel es la función utilizada para convertir datos en una dimensión superior.
Hiperplano es la línea que separa las clases (para problemas de clasificación). Para la regresión, es la línea que ajustamos a nuestros datos para predecir valores de resultados continuos.
Las líneas de contorno son las líneas que forman el área con el error que mencionamos anteriormente. Son las dos líneas alrededor del hiperplano que representan el margen.
Los vectores de soporte son los puntos de datos más cercanos a estas líneas de límite.
Mencionamos que kernel es la función para convertir nuestros datos en dimensiones más altas. Bueno, ¿cómo es eso útil para nosotros?
A veces, los datos se distribuyen de tal manera que es imposible obtener un ajuste preciso mediante el uso de una línea lineal (separador). SVR puede manejar datos altamente no lineales utilizando la función kernel. La función asigna implícitamente las características a dimensiones más altas, lo que significa un espacio de características más alto. Esto nos permite describirlo también usando un hiperplano lineal.
Los tres núcleos más utilizados son:
Similar a los modelos de regresión lineal, SVR también intenta encontrar una curva que mejor se ajuste al conjunto de datos. Recordando nuestra ecuación para el conjunto de datos con una característica de la regresión lineal:
y=w1x1+c
Teniendo en cuenta el SVR para un conjunto de datos también con una característica, la ecuación parece similar pero con la consideración de un error.
−e≤y−(w1x1+c)≤e
Mirando la ecuación, es claro ver que solo los puntos fuera del área de error e serán considerados en el cálculo del costo.
Por supuesto, SVR también se puede usar para conjuntos de datos complicados con más características mediante el uso de términos de características de mayor dimensión similares a los de la regresión polinomial.
El hiperplano es el que mejor se ajusta a los datos cuando coincide con el máximo número de puntos posible. Determinamos las líneas de límite (el valor de e que es la distancia desde el hiperplano) de modo que los puntos más cercanos al hiperplano estén dentro de las líneas de límite.
Tenga en cuenta que debido a que se tolerará el margen (entre las líneas de límite), no se calculará como error. Supongo que ya puedes imaginarte cómo este término nos permitirá ajustar la complejidad de nuestro modelo (underfitting/overfitting).
import numpy as np from sklearn.svm import SVR import matplotlib.pyplot as plt np.random.seed(5) X = np.sort(5 * np.random.rand(40, 1), axis=0) T = np.linspace(0, 5, 5)[:, np.newaxis] y = np.sin(X).ravel() # Add noise to targets y[::5] += 1 * (0.5 - np.random.rand(8)) # Fit regression model SVR_rbf = SVR(kernel='rbf' ) SVR_lin = SVR(kernel='linear') SVR_poly = SVR(kernel='poly') y_rbf = SVR_rbf.fit(X, y).predict(X) y_lin = SVR_lin.fit(X, y).predict(X) y_poly = SVR_poly.fit(X, y).predict(X) # look at the results plt.scatter(X, y, c='k', label='data') plt.plot(X, y_rbf, c='b', label='RBF') plt.plot(X, y_lin, c='r',label='Linear') plt.plot(X, y_poly, c='g',label='Polynomial') plt.xlabel('data') plt.ylabel('outcome') plt.title('Support Vector Regression') plt.legend() plt.show()
Ya vimos cómo funciona el algoritmo “Support Vector Machines (SVM)” para la regresión. Para la clasificación, la idea es en realidad casi la misma. De hecho, SVM se usa principalmente para problemas de clasificación. Creo que ya te puedes imaginar por qué…
Para la regresión, mencionamos que SVM intenta encontrar una curva que se ajuste mejor al conjunto de datos y luego hace una predicción para un nuevo punto usando esa curva. Bueno, la misma curva se puede usar fácilmente para clasificar los datos en dos clases diferentes. Para un espacio multidimensional con n dimensiones (es decir, datos con n número de características), el modelo se ajusta a un hiperplano (también llamado límite de decisión) que diferencia mejor las dos clases. Recordando la imagen de la sección de regresión donde explicábamos el kernel…
El margen es la brecha entre los dos puntos más cercanos de cada clase, que es la distancia desde el hiperplano hasta los puntos más cercanos (vectores de soporte). El hiperplano que mejor se ajusta a los datos, es decir, que separa mejor las dos clases, es el hiperplano con el máximo margen posible. Por lo tanto, el algoritmo SVM busca el hiperplano con el máximo margen (distancia a los puntos más cercanos).
Como ya mencionamos en la sección de regresión, algunos conjuntos de datos simplemente no son adecuados para ser clasificados por un hiperplano lineal... En este caso, nuevamente el "truco del kernel" viene a nuestro rescate mapeando implícitamente los datos a dimensiones más altas, por lo tanto haciendo posible para los datos a ser clasificados por un hiperplano lineal. Como ya discutimos los tipos de Kernel y cómo funciona, continuaré con un ejemplo de implementación...
Continuemos usando el conjunto de datos de cáncer de la biblioteca de aprendizaje de scikit:
from sklearn.datasets import load_breast_cancer from sklearn.model_selection import train_test_split X, y = load_breast_cancer(return_X_y = True) X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) X_sub = X[:, 0:2] # create a mesh to plot in x_min, x_max = X_sub[:, 0].min() - 1, X_sub[:, 0].max() + 1 y_min, y_max = X_sub[:, 1].min() - 1, X_sub[:, 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)) #import the SVM model from sklearn import svm C = 1.0 # SVM regularization parameter svc = svm.SVC(kernel='linear').fit(X_sub, y) #play with this, change kernel to rbf plt.subplot(1, 1, 1) Z = svc.predict(np.c_[xx.ravel(), yy.ravel()]) Z = Z.reshape(xx.shape) plt.contourf(xx, yy, Z, cmap=plt.cm.Paired, alpha=0.8) plt.scatter(X_sub[:, 0], X_sub[:, 1], c=y, cmap=plt.cm.Paired) plt.scatter(X_sub[svc.support_, 0], X_sub[svc.support_, 1],c='k', cmap=plt.cm.Paired) plt.xlabel('Sepal length') plt.ylabel('Sepal width') plt.xlim(xx.min(), xx.max()) plt.title('SVC with linear kernel') plt.show()
#Create and instance of the classifier model with a linear kernel lsvm = svm.SVC(kernel="linear") #fit the model to our train split from previous example lsvm.fit(X_train,y_train) #Make predictions using the test split so we can evaluate its performance y_pred = lsvm.predict(X_test)
Comparemos el rendimiento del modelo comparando las predicciones con los valores reales del conjunto de prueba...
from sklearn import metrics print("Accuracy:",metrics.accuracy_score(y_test, y_pred)) print("Precision:",metrics.precision_score(y_test, y_pred)) print("Recall:",metrics.recall_score(y_test, y_pred))
Pudimos lograr una precisión del 95,6%, lo cual es muy bueno. Comparemos los puntajes de entrenamiento y prueba para verificar si hay sobreajuste...
print("training set score: %f" % lsvm.score(X_train, y_train)) print("test set score: %f" % lsvm.score(X_test, y_test))
La puntuación de entrenamiento parece ser un poco más alta que la puntuación de la prueba. Podemos decir que el modelo está sobreajustado aunque no mucho.
Si te gusta esto, no dudes en seguirme para obtener más tutoriales y cursos gratuitos de aprendizaje automático.