SVM usando scikit learn se ejecuta sin cesar y nunca completa la ejecución


76

Estoy tratando de ejecutar SVR usando scikit learn (python) en un conjunto de datos de entrenamiento que tiene 595605 filas y 5 columnas (características) y un conjunto de datos de prueba que tiene 397070 filas. Los datos han sido preprocesados ​​y regularizados.

Puedo ejecutar con éxito los ejemplos de prueba, pero al ejecutar usando mi conjunto de datos y dejar que se ejecute durante más de una hora, aún no pude ver ningún resultado o finalización del programa. He intentado ejecutar usando un IDE diferente e incluso desde la terminal, pero ese no parece ser el problema. También he intentado cambiar el valor del parámetro 'C' de 1 a 1e3.

Estoy enfrentando problemas similares con todas las implementaciones de svm que usan scikit.

¿No estoy esperando lo suficiente para que se complete? ¿Cuánto tiempo debería llevar esta ejecución?

Desde mi experiencia, no debería requerir más de unos minutos.

Aquí está la configuración de mi sistema: Ubuntu 14.04, 8GB de RAM, mucha memoria libre, procesador i7 de cuarta generación


¿Podría proporcionar el código? Además, ¿el entrenamiento o las pruebas requieren tanto tiempo? ¿Qué tal conjuntos de datos de entrenamiento / prueba más pequeños?
amigo

Solo estoy leyendo datos de un archivo csv en un marco de datos de pandas y pasándolos a la función de aprendizaje scikit. ¡Eso es todo! Proporcionar código realmente no ayudaría aquí
tejaskhot

66
La implementación SVM de sklearn implica al menos 3 pasos: 1) crear un objeto SVR, 2) ajustar un modelo, 3) predecir el valor. El primer paso describe el kernel en uso, lo que ayuda a comprender los procesos internos mucho mejor. Los pasos segundo y tercero son bastante diferentes, y necesitamos saber al menos cuál de ellos lleva tanto tiempo. Si se trata de entrenamiento, entonces puede estar bien, porque a veces el aprendizaje es lento. Si está probando, entonces probablemente haya un error, porque probar en SVM es realmente rápido. Además, puede ser la lectura CSV lo que lleva tanto tiempo y no SVM en absoluto. Entonces, todos estos detalles pueden ser importantes.
Amigo

También estoy enfrentando el mismo problema a través de svm, pero ¿alguien puede decirme cuánto tiempo tomará después de la normalización?
kashyap kitchlu

Respuestas:


70

Las SVM kernelizadas requieren el cálculo de una función de distancia entre cada punto en el conjunto de datos, que es el costo dominante de . El almacenamiento de las distancias es una carga para la memoria, por lo que se vuelven a calcular sobre la marcha. Afortunadamente, la mayoría de las veces solo se necesitan los puntos más cercanos al límite de decisión. Las distancias calculadas con frecuencia se almacenan en un caché. Si la memoria caché se está agotando, el tiempo de ejecución aumenta a O ( n características × n 3 observaciones ) .O(nortecaracteristicas×norteobservaciones2)O(nortecaracteristicas×norteobservaciones3)

Puede aumentar este caché invocando SVR como

model = SVR(cache_size=7000)

En general, esto no va a funcionar. Pero no todo está perdido. Puede submuestrear los datos y usar el resto como un conjunto de validación, o puede elegir un modelo diferente. Por encima del rango de observación de 200,000, es aconsejable elegir estudiantes lineales.

Kernel SVM puede ser aproximado, aproximando la matriz del kernel y alimentándola a un SVM lineal. Esto le permite intercambiar entre precisión y rendimiento en tiempo lineal.

Una forma popular de lograr esto es usar aproximadamente 100 centros de clúster encontrados por kmeans / kmeans ++ como base de la función de su núcleo. Las nuevas características derivadas se introducen en un modelo lineal. Esto funciona muy bien en la práctica. Herramientas como sophia-ml y votepal wabbit son cómo Google, Yahoo y Microsoft hacen esto. La entrada / salida se convierte en el costo dominante para los aprendices lineales simples.

En la abundancia de datos, los modelos no paramétricos realizan aproximadamente lo mismo para la mayoría de los problemas. Las excepciones son entradas estructuradas, como texto, imágenes, series de tiempo, audio.

Otras lecturas


16

SVM resuelve un problema de optimización de orden cuadrático.

No tengo nada que agregar que no se haya dicho aquí. Solo quiero publicar un enlace en la página de sklearn sobre SVC que aclara lo que está sucediendo:

La implementación se basa en libsvm. La complejidad del tiempo de ajuste es más que cuadrática con el número de muestras, lo que dificulta escalar al conjunto de datos con más de un par de 10000 muestras.

Si no desea utilizar núcleos, y un SVM lineal es suficiente, existe LinearSVR, que es mucho más rápido porque utiliza un enfoque de optimización para las regresiones lineales. Sin embargo, tendrá que normalizar sus datos, en caso de que aún no lo haga, porque aplica la regularización al coeficiente de intercepción, que probablemente no sea lo que desea. Significa que si su promedio de datos está lejos de cero, no podrá resolverlo satisfactoriamente.

Lo que también puede usar es el descenso de gradiente estocástico para resolver el problema de optimización. Sklearn presenta SGDRegressor . Debe usar loss='epsilon_insensitive'para tener resultados similares a SVM lineal. Ver la documentación. Sin embargo, solo usaría el descenso de gradiente como último recurso porque implica muchos ajustes de los hiperparámetros para evitar quedar atrapado en los mínimos locales. Úselo LinearSVRsi puede.


Tenía un conjunto de datos con muchas líneas. SVC comenzó a tomar demasiado tiempo para mí alrededor de 150,000 filas de datos. Utilicé su sugerencia con LinearSVR y un millón de filas lleva solo un par de minutos. PS también encontró que el clasificador LogisticRegression produce resultados similares a LinearSVR (en mi caso) y es aún más rápido.
jeffery_the_wind

8

¿Incluyó el escalado en su paso de preprocesamiento? Tuve este problema al ejecutar mi SVM. Mi conjunto de datos es de ~ 780,000 muestras (fila) con 20 características (col). Mi conjunto de entrenamiento es de ~ 235k muestras. ¡Resulta que olvidé escalar mis datos! Si este es el caso, intente agregar este bit a su código:

escalar datos a [-1,1]; aumentar la velocidad SVM:

desde sklearn.preprocessing import MinMaxScaler
scaling = MinMaxScaler (feature_range = (- 1,1)). fit (X_train)
X_train = scaling.transform (X_train)
X_test = scaling.transform (X_test)


2
¿Alguien puede explicar por qué esto acelera el ajuste SVM?
feliz

1
¿Hay alguna razón por la que elegiste MinMaxScaler en lugar de cualquier otra? StandardScaler por ejemplo?
raspi

@Ippier: esencialmente está reduciendo el espacio límite posible para cada opción de una manera que hace que el nivel de esfuerzo sea mucho menor para su máquina.
ike

7

Con un conjunto de datos tan grande, creo que sería mejor usar una red neuronal, aprendizaje profundo, bosque aleatorio (son sorprendentemente buenos), etc.

Como se mencionó en las respuestas anteriores, el tiempo necesario es proporcional a la tercera potencia del número de muestras de entrenamiento. Incluso el tiempo de predicción es polinómico en términos de número de vectores de prueba.

Si realmente debe usar SVM, le recomiendo usar GPU para acelerar o reducir el tamaño del conjunto de datos de entrenamiento. Pruebe primero con una muestra (quizás 10,000 filas) de los datos para ver si no es un problema con el formato o la distribución de datos.

Como se mencionó en otras respuestas, los núcleos lineales son más rápidos.


3

Recientemente encontré un problema similar porque olvidé escalar características en mi conjunto de datos que se utilizó anteriormente para entrenar el tipo de modelo de conjunto. La imposibilidad de escalar los datos puede ser el culpable probable según lo indicado por Shelby Matlock. Puede probar diferentes escaladores disponibles en sklearn, como RobustScaler :

from sklearn.preprocessing import RobustScaler scaler = RobustScaler() X = scaler.fit_transfrom(X)

X ahora se transforma / escala y está listo para ser alimentado a su modelo deseado.


2

Esto tiene sentido. IIUC, la velocidad de ejecución de las operaciones de vectores de soporte está limitada por el número de muestras, no por la dimensionalidad. En otras palabras, está limitado por el tiempo de CPU y no por la RAM. No estoy seguro exactamente cuánto tiempo debería llevar esto, pero estoy ejecutando algunos puntos de referencia para averiguarlo.


1

Déjelo correr durante la noche o mejor durante 24 horas. ¿Cuál es la utilización de tu CPU? Si ninguno de los núcleos funciona al 100%, entonces tiene un problema. Probablemente con memoria. ¿Ha verificado si su conjunto de datos se ajusta a 8 GB? ¿Has probado el SGDClassifier? Es uno de los más rápidos allí. Vale la pena intentarlo primero con la esperanza de que se complete en una hora más o menos.


SGDClassifierno es compatible con los núcleos. Si el OP quiere SVM lineal, entonces recomendaría primero intentarlo LinearSVR. Es mucho más rápido que SVRporque resuelve el problema usando una biblioteca de regresión lineal, y el mínimo global está garantizado (a diferencia del gradiente decente).
Ricardo Cruz

Agradezco tu comentario. ¿Podría explicar por qué el soporte del kernel es un problema?
Diego

De la documentación , lo The loss function to be used. Defaults to ‘hinge’, which gives a linear SVM.mismo para SGDRegressor. SGDRegressores equivalente a usar SVR(kernel='linear'). Si eso es lo que OP quiere, eso es genial. Tenía la impresión de que quería usar SVM con un núcleo. Si ese no es el caso, recomendaría que primero lo intente LinearSVR.
Ricardo Cruz

1

Intente normalizar los datos a [-1,1]. Me enfrenté a un problema similar y sobre la normalización todo funcionó bien. Puede normalizar datos fácilmente usando:

from sklearn import preprocessing X_train = preprocessing.scale(X_train) X_test = preprocessing.scale(X_test)


@ Archie Esta es una respuesta a una pregunta, no una pregunta.
timleathart

1

Me he encontrado con este problema y, cache_sizecomo otros sugieren, no ayuda en absoluto. Puede ver esta publicación y esta, ya que el principal contribuyente sugirió que debería cambiar el código manualmente.

Como ya saben, SVCy SVRson problemas de optimización y se detendrá cuando el margen de error es tan pequeño que la optimización adicional es inútil. Entonces, hay otro parámetro en estos, max_iterdonde puede establecer cuántas iteraciones debe hacer.

Lo he usado sklearnen Python y e1071en R y R es mucho más rápido llegar al resultado sin configurar el max_itery sklearntarda 2-4 veces más. La única forma en que podía reducir el tiempo de cálculo para Python era usando max_iter. Es relativo a la complejidad de su modelo, número de cuenta, granos y hiperparámetros, pero por lo pequeño conjunto de datos utilizado por alrededor de 4.000 puntos de datos y max_iterse 10000los resultados no fueron diferentes en absoluto y que era aceptable.


0

Acabo de tener un problema similar con un conjunto de datos que contiene solo 115 elementos y una sola característica (datos de aerolíneas internacionales). La solución fue escalar los datos. Lo que me perdí en las respuestas hasta ahora fue el uso de una tubería:

from sklearn.svm import SVR
from sklearn.preprocessing import StandardScaler, MinMaxScaler

model = Pipeline([('scaler', StandardScaler()),
                  ('svr', SVR(kernel='linear'))])

Puede entrenar modelcomo un modelo habitual de clasificación / regresión y evaluarlo de la misma manera. Nada cambia, solo la definición del modelo.


¿Qué es Pipeline? No lo estás importando.
Bram Vanroy

0

Necesita escalar sus datos. El escalado normalizará sus puntos de datos a un rango de -1 a 1, lo que ayudará a una convergencia más rápida.

Intenta usar el siguiente código:

# X is your numpy data array.

from sklearn import preprocessing

X = preprocessing.scale(X)

bienvenido a Data Science SE! ¿Podría explicar cómo su sugerencia ayudará a OP? Lo que está sugiriendo es una escala de una matriz. No está claro cómo eso puede o no afectar el algoritmo SVR en scikit learn.
Estéreo
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.