python - example - Función correcta para normalizar la entrada de sklearn SVM
sklearn svm example (1)
Debe elegir el esquema de escala en función de lo que tenga sentido con sus datos. Existen diferentes formas de escalar , y cuál usará depende de los datos. Cada esquema trae valores de diferentes características a rangos comparables, pero cada uno de ellos conserva diferentes tipos de información (y distorsiona otros) a medida que lo hacen. Y aunque hay explicaciones racionales detrás de por qué algunos esquemas de escala son más adecuados para un caso específico, no hay nada de malo con solo probar estos diferentes (como lo hizo con la escala y normalización estándar) y usar el que funciona mejor (siempre y cuando al realizar una validación cruzada o asegurarse de que su medición del rendimiento sea general y precisa).
StandardScaler
Esto es lo que sklearn.preprocessing.scale(X)
. Asume que sus características se distribuyen normalmente (cada característica con una media y desviación estándar diferente) y las escala de manera que la distribución gaussiana de cada entidad se centre en torno a 0 y su desviación estándar sea 1.
Hace esto calculando la media y stdev para cada característica, luego convierte cada valor real para la característica en un puntaje z : ¿cuántos stdevs lejos de la media es este valor? z = (valor-media) / stdev
Esto a menudo funciona bien, pero si la suposición de normalidad es completamente incorrecta para su caso, entonces este puede no ser el mejor esquema de escalado para usted. Prácticamente, en muchos casos donde la suposición de normalidad no se cumple, pero las distribuciones son algo cercanas, este esquema todavía funciona bastante bien. Sin embargo, si los datos están completamente lejos de la normalidad, por ejemplo, distribuciones muy asimétricas, de cola gruesa (como una ley de poder), este esquema no dará buenos resultados.
Normalizador
Esto es lo que sklearn.preprocessing.normalize(X, axis=0)
. Mira todos los valores de características para un punto de datos dado como un vector y normaliza ese vector dividiéndolo por su magnitud. Por ejemplo, supongamos que tienes 3 funciones. Los valores para un punto específico son [x1, x2, x3]
. Si usa la normalización ''l2''
predeterminada, divide cada valor por sqrt(x1^2 + x2^2 + x3^2)
. Si usa ''l1''
normalización ''l1''
, divida cada uno entre x1+x2+x3
. Esto asegura que los valores estén en rangos similares para cada característica, ya que cada vector de característica es un vector unitario. Si los valores de las características para un punto son grandes, también lo es la magnitud y se divide por un número grande. Si son pequeños, los divides por un número pequeño.
El razonamiento es que puede pensar en sus datos como puntos en un espacio n-dimensional, donde n es el número de características. Cada característica es un eje. La normalización tira cada punto de regreso al origen de una manera que está solo a 1 unidad de distancia del origen. Básicamente colapsas el espacio en el hipercubo de la unidad. Los ángulos entre los vectores para cada punto (desde el origen hasta el punto de datos) permanecen iguales.
Esto se usa mucho con los datos de texto, ya que tiene mucho sentido intuitivo allí: si cada característica es el recuento de una palabra diferente, ''l1''
normalización ''l1''
básicamente convierte esos recuentos a frecuencias (se divide por el recuento total de palabras). Esto tiene sentido. Si usa ''l2''
normalización ''l2''
, el ángulo entre dos vectores (esto se conoce como distancia o similitud del coseno) se mantendrá igual cuando normalice ambos, y esta distancia se aproxima más a una distancia de significado, ya que corresponde a razones de frecuencias entre palabras y no se ve afectado por el tiempo que representa cada vector.
Si conservar un tipo de relación coseno distancia entre puntos es lo que tiene más sentido para sus datos, o si la normalización corresponde a una escala natural (como tomar frecuencias en lugar de conteos), entonces esta es más adecuada.
MinMaxScaler
Puede usar este como sklearn.preprocessing.MinMaxScaler().fit_transform(X)
. Para cada característica, esto mira el valor mínimo y máximo. Este es el rango de esta característica. Luego se encoge o estira al mismo rango para cada característica (el valor predeterminado es 0 a 1).
Hace esto convirtiendo cada valor en (value-feature_min)/(feature_max - feature_min)
. Básicamente, ¿a qué porcentaje del rango estoy mintiendo? Recuerde que el rango solo está determinado por el mínimo y máximo para la función. Por todo esto, todos los valores pueden estar alrededor de 10, 11, y hay un valor atípico único que es 900. No importa, su rango es de 10 a 900. Puede ver que en algunos casos eso es deseable, y en otros esto será problemático, dependiendo del problema específico y de los datos.
Este esquema funciona mucho mejor en ciertos casos donde StandardScaler podría no funcionar bien. Por ejemplo, si las desviaciones estándar son muy pequeñas para las características , StandardScaler es muy sensible a los pequeños cambios entre las desviaciones estándar de diferentes características, pero MinMaxScaler es muy robusto . Además, para las características con distribuciones muy asimétricas, o casos dispersos donde cada característica tiene muchos ceros que alejan la distribución de un gaussiano, MinMaxScaler es una mejor opción.
Encontré varias preguntas relacionadas con esto, pero nadie resolvió mis dudas. En particular, las dos respuestas a esta pregunta me confundieron aún más.
Estoy entrenando un SVM lineal además de un conjunto de características: funciones de red neuronal convolucional como resultado de imágenes. Tengo, por ejemplo, una matriz X
3500x4096 con ejemplos en filas y características en columnas, como de costumbre.
Me pregunto cómo estandarizar / normalizar correctamente esta matriz antes de alimentar el SVM. Veo dos formas (usando sklearn):
Funciones de estandarización. Resulta en características con 0 std estándar y unitario.
X = sklearn.preprocessing.scale(X)
Funciones de normalización. Resulta en características con una norma unitaria.
X = sklearn.preprocessing.normalize(X, axis=0)
Mis resultados son sensiblemente mejores con la normalización (76% de precisión) que con la estandarización (68% de precisión).
¿Es una elección completamente dependiente del conjunto de datos? ¿O cómo se puede elegir entre las dos técnicas?