Logotipo de Zephyrnet

Comprender los hiperparámetros de SVM

Fecha:

Introducción

Esta guía es la segunda parte de tres guías sobre Support Vector Machines (SVM). En esta guía, seguiremos trabajando en el caso de uso de billetes de banco falsificados, comprenderemos qué parámetros SVM ya están siendo establecidos por Scikit-learn, qué son los hiperparámetros C y Gamma, y ​​cómo ajustarlos mediante la validación cruzada y la búsqueda en cuadrícula.

En la serie completa de guías de SVM, además de los hiperparámetros de SVM, también aprenderá sobre SVM simple, un concepto llamado truco del granoy explore otros tipos de SVM.

Si deseas leer todas las guías, echa un vistazo a la primera guía, o mira cuáles te interesan más, a continuación se muestra la tabla de temas tratados en cada guía:

  1. Implementación de SVM y Kernel SVM con Scikit-Learn de Python
  • Caso de uso: olvidar los billetes de banco
  • Antecedentes de las SVM
  • Modelo SVM simple (lineal)
    • Acerca del conjunto de datos
    • Importación del conjunto de datos
    • Explorando el conjunto de datos
  • Implementación de SVM con Scikit-Learn
    • División de datos en conjuntos de prueba/entrenamiento
    • Entrenando el modelo
    • Haciendo predicciones
    • Evaluación del modelo
    • Interpretación de resultados

2. Comprender los hiperparámetros de SVM

  • El hiperparámetro C
  • El hiperparámetro gamma

3. Implementar otras versiones de SVM con Scikit-Learn de Python (¡próximamente!)

  • La idea general de las SVM (un resumen)
  • Núcleo (truco) SVM
  • Implementación de kernel SVM no lineal con Scikit-Learn
  • Importación de bibliotecas
    • Importando el conjunto de datos
    • Dividir datos en características (X) y destino (y)
    • División de datos en conjuntos de prueba/entrenamiento
    • Entrenamiento del algoritmo
  • Núcleo polinomial
    • Haciendo predicciones
    • Evaluación del algoritmo
  • Kernel gaussiano
    • Predicción y Evaluación
  • Núcleo sigmoide
    • Predicción y Evaluación
  • Comparación de rendimientos de núcleos no lineales

Aprendamos cómo implementar la validación cruzada y realizar un ajuste de hiperparámetros.

Hiperparámetros SVM

Para ver todos los parámetros del modelo que Scikit-learn ya ha establecido y sus valores predeterminados, podemos usar el get_params() método:

svc.get_params()

Este método muestra:

{'C': 1.0, 'break_ties': False, 'cache_size': 200, 'class_weight': None, 'coef0': 0.0, 'decision_function_shape': 'ovr', 'degree': 3, 'gamma': 'scale', 'kernel': 'linear', 'max_iter': -1, 'probability': False, 'random_state': None, 'shrinking': True, 'tol': 0.001, 'verbose': False}

Tenga en cuenta que ya se están configurando un total de 15 hiperparámetros, esto sucede porque el algoritmo SVM tiene muchas variaciones. Hemos usado el kernel lineal para obtener una función lineal, pero también hay kernels que describen otros tipos de funciones y esos kernels se parametrizan de diferentes maneras.

Estas variaciones hacen que el modelo sea más flexible y adecuado para encontrar una separación entre diferentes formas de datos. Si podemos trazar una línea para separar nuestras clases, entonces una kernel lineal será una buena opción, si necesitamos una curva, entonces una polinomio kernel podría ser la mejor opción, si nuestros datos tienen formas circulares, entonces un Funcion de base radial or RBF kernel se adaptará mejor a los datos, si hay valores por encima y por debajo de un umbral, un sigmoideo kernel podría separar mejor las clases. Por lo que hemos explorado en nuestros datos, parece que un RBF o un kernel polinomial serían más adecuados que un kernel lineal.

Ahora que tenemos una idea de que hay 4 tipos de funciones de kernel diferentes, podemos volver a los parámetros. Cuando el algoritmo SVM intenta encontrar una separación entre clases, ya hemos entendido que dibuja una clasificación margen entre los vectores de apoyo y la línea (o curva) de separación.

Este margen es, en cierto sentido, como un amortiguador entre la línea de separación y los puntos. El tamaño del margen puede variar, cuando el margen es menores, hay menos espacio para los puntos que quedan fuera del margen, lo que hace que la separación entre clases sea más clara, por lo que se están tomando más muestras correctamente clasificado, por el contrario, cuando el margen es mayores, la separación entre clases es menos clara y se pueden tomar más muestras. mal clasificado. En otras palabras, un margen más pequeño significa muestras mejor clasificadas, y también una mayor rígido clasificador, mientras que un margen más grande, denota más muestras mal clasificadas, pero una más flexible clasificador.

Cuando se eligen esos márgenes, el parámetro que los determina es el C parámetro.

El hiperparámetro C

El C parámetro es inversamente proporcional al tamaño del margen, esto significa que el mayores el valor de C, la menores el margen y, por el contrario, el menores el valor de C, la mayores el margen. El C El parámetro se puede usar junto con cualquier kernel, le dice al algoritmo cuánto debe evitar clasificar erróneamente cada muestra de entrenamiento, debido a eso, también se conoce como regularización. Nuestro núcleo lineal SVM ha utilizado un C de 1.0, que es un large valor y da un margen más pequeño.

Podemos experimentar con un menores valor de 'C' y entender en la práctica lo que sucede con un margen más grande. Para hacer eso, crearemos un nuevo clasificador, svc_c, y cambiar sólo el valor de C a 0.0001. Repitamos también el fit y predict pasos:

svc_c = SVC(kernel='linear', C=0.0001)
svc_c.fit(X_train, y_train)
y_pred_c = svc_c.predict(X_test)

Ahora podemos ver los resultados de los datos de prueba:

print(classification_report(y_test, y_pred_c)) cm_c = confusion_matrix(y_test, y_pred_c)
sns.heatmap(cm_c, annot=True, fmt='d').set_title('Confusion matrix of linear SVM with C=0.0001')

Esto produce:

 precision recall f1-score support 0 0.82 0.96 0.88 148 1 0.94 0.76 0.84 127 accuracy 0.87 275 macro avg 0.88 0.86 0.86 275
weighted avg 0.88 0.87 0.86 275

Al usar una más pequeña C y al obtener un mayor margen, el clasificador se ha vuelto más flexible y con más errores de clasificación. En el informe de clasificación, podemos ver que el f1-score, anteriormente de 0.99 para ambas clases, ha bajado a 0.88 para la clase 0 ya 0.84 para la clase 1. En la matriz de confusión, el modelo pasó de 2 a 6 falsos positivos y de 2 a 31 falsos negativos.

También podemos repetir el predict paso y mire los resultados para verificar si todavía hay un sobreajuste al usar datos de tren:

y_pred_ct = svc_c.predict(X_train) cm_ct = confusion_matrix(y_train, y_pred_ct)
sns.heatmap(cm_ct, annot=True, fmt='d').set_title('Confusion matrix of linear SVM with C=0.0001 and train data') print(classification_report(y_train, y_pred_ct))

Esto resulta en:

 precision recall f1-score support 0 0.88 0.96 0.92 614 1 0.94 0.84 0.88 483 accuracy 0.90 1097 macro avg 0.91 0.90 0.90 1097
weighted avg 0.91 0.90 0.90 1097

Al observar los resultados con un tamaño más pequeño C y entrenar datos, podemos ver que hubo una mejora en el sobreajuste, pero una vez que la mayoría de las métricas siguen siendo más altas para entrenar datos, parece que el sobreajuste no se ha resuelto. Entonces, simplemente cambiando el C parámetro no fue suficiente para flexibilizar el modelo y mejorar su generalización.

Note: Intentar encontrar el equilibrio entre una función que se aleja demasiado de los datos, que es demasiado fija o que tiene alto sesgo o es lo contrario, una función que se ajusta a los datos, es demasiado flexible o tiene alta varianza suele denominarse como el compensación de varianza de sesgo. Encontrar ese equilibrio no es trivial, pero cuando se logra, no hay un ajuste insuficiente o excesivo del modelo a los datos. Como una forma de reducir la varianza y evitar el sobreajuste, los datos se pueden reducir uniformemente para hacerlos más regulares y simplificados al obtener una función que los describa. Eso es lo que el parámetro C hace cuando se usa en SVM, por eso también se le llama Regularización L2 or Regresión de cresta.

Hasta este punto, hemos entendido acerca de los márgenes en SVM y cómo impactan el resultado general del algoritmo, pero ¿qué hay de la línea (o curva) que separa las clases? Esta línea es la límite de decisión. Entonces, ya sabemos que los márgenes tienen un impacto en la flexibilidad del límite de decisión hacia los errores, ahora podemos echar un vistazo a otro parámetro que también afecta el límite de decisión.

Consulte nuestra guía práctica y práctica para aprender Git, con las mejores prácticas, los estándares aceptados por la industria y la hoja de trucos incluida. Deja de buscar en Google los comandos de Git y, de hecho, aprenden ella!

Note: El límite de decisión también se puede llamar hiperplano. Un hiperplano es un concepto geométrico para referirse al número de dimensiones de un espacio menos uno (dims-1). Si el espacio es bidimensional, como un plano con coordenadas x e y, las líneas (o curvas) unidimensionales son los hiperplanos. En el contexto del aprendizaje automático, dado que el número de columnas utilizadas en el modelo son sus dimensiones planas, cuando trabajamos con 2 columnas y un clasificador SVM, encontramos un hiperplano tridimensional que separa las clases.

El hiperparámetro gamma

Se pueden elegir límites de decisión infinitos, algunos de esos límites separarán las clases y otros no. Al elegir un límite de decisión efectivo, ¿se deben considerar los primeros 10 puntos más cercanos de cada clase? ¿O deberían considerarse más puntos, incluidos los puntos que están lejos? En SVM, esa elección de rango está definida por otro hiperparámetro, gamma.

Me gusta C, gamma es algo inversamente proporcional a su distancia. El más alto su valor, el más parecido son los puntos que se consideran para el límite de decisión, y los más bajo las gamma, la más lejos También se consideran puntos para elegir el límite de decisión.

Otro impacto de gamma es que cuanto más alto es su valor, más se acerca el alcance del límite de decisión a los puntos que lo rodean, lo que lo hace más irregular y propenso a sobreajustarse, y cuanto más bajo es su valor, más suave y regular es el límite de decisión. la superficie se vuelve, además, menos propensa al sobreajuste. Esto es cierto para cualquier hiperplano, pero se puede observar más fácilmente cuando se separan los datos en dimensiones más altas. En algunas documentaciones, gamma también puede denominarse sigma.

En el caso de nuestro modelo, el valor por defecto de gamma fue scale. Como se puede ver en el Documentación de SVC de Scikit-learn, significa que su valor es:

$$
gamma = (1/ texto{n_features} * X.var())
$$

or

$$
gamma = (1/ texto{número_de_características} * texto{características_varianza})
$$

En nuestro caso, necesitamos calcular la varianza de X_train, multiplícalo por 4 y divide el resultado por 1. Esto lo podemos hacer con el siguiente código:

number_of_features = X_train.shape[1] features_variance = X_train.values.var()
gamma = 1/(number_of_features * features_variance)
print('gamma:', gamma)

Esto produce:

gamma: 0.013924748072859962

También hay otra manera de ver el valor de gamma, accediendo al objeto del clasificador gamma parámetro con ._gamma:

svc._gamma 

Podemos ver que el gamma utilizado en nuestro clasificador fue bajo, por lo que también consideró puntos más lejanos.

Note: Como hemos visto, C y gamma son importantes para algunas definiciones del modelo. Otro hiperparámetro, random_state, a menudo se usa en Scikit Learn para garantizar la combinación aleatoria de datos o una semilla aleatoria para modelos, por lo que siempre tenemos los mismos resultados, pero esto es un poco diferente para SVM. Particularmente, el random_state solo tiene implicaciones si otro hiperparámetro, probability, se establece en verdadero. Esto se debe a que barajará los datos para obtener estimaciones de probabilidad. Si no queremos estimaciones de probabilidad para nuestras clases y la probabilidad se establece en falso, SVM random_state parámetro no tiene implicaciones en los resultados del modelo.

No existe una regla sobre cómo elegir los valores para los hiperparámetros, como C y gamma; dependerá de cuánto tiempo y qué recursos estén disponibles para experimentar con diferentes valores de hiperparámetros, qué transformaciones se pueden realizar en los datos y qué resultados se esperan. . La forma habitual de buscar los valores de los hiperparámetros es combinando cada uno de los valores propuestos a través de un búsqueda de cuadrícula junto con un procedimiento que aplica esos valores de hiperparámetros y obtiene métricas para diferentes partes de los datos llamados validación cruzada. En Scikit-learn, esto ya está implementado como el GridSearchCV (CV de validación cruzada) método.

Para ejecutar una búsqueda de cuadrícula con validación cruzada, necesitamos importar el GridSearchCV, definir un diccionario con los valores de los hiperparámetros con los que se experimentará, como el tipo de kernel, el rango de C, Y para gamma, crea una instancia del SVC, definir el score o métrica se usará para evaluar (aquí elegiremos optimizar tanto para la precisión como para la recuperación, por lo que usaremos f1-score), el número de divisiones que se harán en los datos para ejecutar la búsqueda en cv – el valor predeterminado es 5, pero es una buena práctica usar al menos 10 – aquí, usaremos 5 pliegues de datos para que quede más claro al comparar resultados.

El GridSearchCV tiene un fit método que recibe nuestros datos de tren y los divide aún más en conjuntos de tren y prueba para la validación cruzada. podemos establecer return_train_score a true para comparar los resultados y garantizar que no haya sobreajuste.

Este es el código para la búsqueda en cuadrícula con validación cruzada:

from sklearn.model_selection import GridSearchCV parameters_dictionary = {'kernel':['linear', 'rbf'], 'C':[0.0001, 1, 10], 'gamma':[1, 10, 100]}
svc = SVC() grid_search = GridSearchCV(svc, parameters_dictionary, scoring = 'f1', return_train_score=True, cv = 5, verbose = 1) grid_search.fit(X_train, y_train)

Este código genera:

Fitting 5 folds for each of 18 candidates, totalling 90 fits
# and a clickable GridSeachCV object schema

Después de hacer la búsqueda de hiperparámetros, podemos usar el best_estimator_, best_params_ y best_score_ propiedades para obtener el mejor modelo, los valores de los parámetros y la puntuación f1 más alta:

best_model = grid_search.best_estimator_
best_parameters = grid_search.best_params_
best_f1 = grid_search.best_score_ print('The best model was:', best_model)
print('The best parameter values were:', best_parameters)
print('The best f1-score was:', best_f1)

Esto resulta en:

The best model was: SVC(C=1, gamma=1)
The best parameter values were: {'C': 1, 'gamma': 1, 'kernel': 'rbf'}
The best f1-score was: 0.9979166666666666

Confirmando nuestra suposición inicial al observar los datos, el mejor modelo no tiene un kernel lineal, sino uno no lineal, RBF.

Consejo: al seguir investigando, es interesante que incluya más núcleos no lineales en la búsqueda de cuadrícula.

Ambos C y gamma tienen el valor de 1, y el f1-score es muy alto, 0.99. Dado que el valor es alto, veamos si hubo un sobreajuste observando las puntuaciones medias de las pruebas y del tren que hemos devuelto, dentro del cv_results_ :

gs_mean_test_scores = grid_search.cv_results_['mean_test_score']
gs_mean_train_scores = grid_search.cv_results_['mean_train_score'] print("The mean test f1-scores were:", gs_mean_test_scores)
print("The mean train f1-scores were:", gs_mean_train_scores)

Las puntuaciones medias fueron:

The mean test f1-scores were: [0.78017291 0. 0.78017291 0. 0.78017291 0. 0.98865407 0.99791667 0.98865407 0.76553515 0.98865407 0.040291 0.98656 0.99791667 0.98656 0.79182565 0.98656 0.09443985] The mean train f1-scores were: [0.78443424 0. 0.78443424 0. 0.78443424 0. 0.98762683 1. 0.98762683 1. 0.98762683 1. 0.98942923 1. 0.98942923 1. 0.98942923 1. ]

Al observar las puntuaciones medias, podemos ver que la más alta, 0.99791667, aparece dos veces y, en ambos casos, la puntuación en los datos del tren fue 1. Esto indica que persiste el sobreajuste. A partir de aquí, sería interesante volver a la preparación de datos y comprender si tiene sentido normalizar los datos, realizar algún otro tipo de transformación de datos y también crear nuevas características con ingeniería de características.

Acabamos de ver una técnica para encontrar los hiperparámetros del modelo y ya hemos mencionado algo sobre la separabilidad lineal, los vectores de soporte, el límite de decisión, la maximización de los márgenes y el truco del kernel. SVM es un algoritmo complejo, generalmente con muchos conceptos matemáticos involucrados y pequeñas partes modificables que deben ajustarse para unirse como un todo.

Combinemos lo que hemos visto hasta ahora, hagamos un resumen de cómo funcionan todas las partes de SVM y luego echemos un vistazo a algunas de las otras implementaciones del kernel junto con sus resultados.

Conclusión

En este artículo, comprendimos los parámetros predeterminados detrás de la implementación de SVM de Scikit-Learn. Entendimos qué son los parámetros C y Gamma, y ​​cómo cambiar cada uno de ellos puede afectar el modelo SVM.

También aprendimos sobre la búsqueda en cuadrícula para buscar los mejores valores de C y Gamma, y ​​a usar la validación cruzada para generalizar mejor nuestros resultados y garantizar que no haya ningún tipo de fuga de datos.

Realizar un ajuste de hiperparámetros con búsqueda en cuadrícula y validación cruzada es una práctica común en la ciencia de datos, por lo que le sugiero que implemente las técnicas, ejecute el código y vea los vínculos entre los valores de hiperparámetros y los cambios en las predicciones de SVM.

punto_img

Información más reciente

punto_img