vectorial soporte regresion maquinas machine lineal learning hacer ejemplo decision curso como clasificacion arbol algoritmos python numpy matrix scikit-learn regression

regresion - maquinas de soporte vectorial en python



Regresión de ScikitLearn: la matriz de diseño X es demasiado grande para la regresión. ¿Qué debo hacer? (2)

Es un problema bien conocido que se puede abordar utilizando el aprendizaje fuera del núcleo. Al buscar en Google el término, encontrará varias formas de abordar el problema.

Para su problema específico, primero tiene que crear un generador que genere una fila (o varias de ellas) de su matriz y que use el método partial_fit de su algoritmo.

Los algoritmos estándar de scikit-learn usan en realidad un cálculo exacto de la solución, como sklearn.linear_model.LinearRegression o sklearn.linear_model.LinearRegression.RidgeCV . Otros métodos se basan en el aprendizaje por lotes y tienen un método partial_fit como sklearn.linear_model.SGDRegressor , que permite sklearn.linear_model.SGDRegressor solo un mini lote. Es lo que estás buscando.

El proceso es: use el generador para producir un mini lote, aplique el método partial_fit , elimine el mini lote de la memoria y obtenga uno nuevo.

Sin embargo, como este método es estocástico y depende del orden de sus datos y su inicialización de los pesos, es lo opuesto a la solución dada por los métodos de regresión estándar que pueden ajustarse a todos los datos en la memoria. No entraré en los detalles, pero miro la optimización de la pendiente del degradado para entender cómo funciona ( http://ruder.io/optimizing-gradient-descent/ )

Tengo una matriz X que tiene algo así como 7000 columnas y 38000 filas. Por lo tanto, es una numpy array con forma (38000, 7000) .

Yo instalé el modelo

model = RidgeCV(alphas = (0.001,0.01, 0.1, 1)

y luego se ajustó

model.fit(X, y)

donde y es el vector de respuesta que es una matriz numpy con forma (38000,) .

Al ejecutar esto obtengo un Memory Error .

¿Como puedo resolver esto?

Mi idea

Mi primer pensamiento fue dividir la matriz X "horizontalmente". Con esto quiero decir que divido X en, digamos, dos matrices con el mismo número de columnas (manteniendo así todas las características) pero con menos filas. ¿Entonces ajusto el modelo cada vez para cada una de estas submatrices? Pero me temo que esto no es realmente equivalente a ajustar toda la matriz ...

¿Algunas ideas?


En mi opinión, no es realmente una gran escala y probablemente no necesites utilizar el aprendizaje fuera del núcleo (aunque no sé cuánta memoria tienes).

Si utiliza enfoques fuera del núcleo cuando no los necesite, tendrá que pagar un precio (¡no robusto sin una gran afinación)!

También sería interesante saber si sus características son dispersas o densas, lo que puede marcar una gran diferencia (¡ya que la mayoría de los solucionadores pueden explotar datos dispersos!).

Algunas cosas para decir aquí:

  • RidgeCV utiliza un enfoque de validación cruzada sin problemas y, probablemente, por esta razón, no hay ningún parámetro para controlar el solucionador subyacente.
    • No es raro usar un método de CV ajustado al problema cuando el arranque en caliente eficiente puede ayudar al proceso (rendimiento)
  • Al hacer CV manualmente, todas las herramientas están disponibles en sklearn, puede elegir diferentes solucionadores
    • Esos son muy diferentes en términos del enfoque y las características

solucionador: {''auto'', ''svd'', ''cholesky'', ''lsqr'', ''sparse_cg'', ''sag'', ''saga''}

Solver para usar en las rutinas computacionales:

''auto'' elige el solucionador automáticamente en función del tipo de datos.

''svd'' usa una Descomposición de Valor Singular de X para calcular los coeficientes de Ridge. Más estable para matrices singulares que ''cholesky''.

''cholesky'' usa la función estándar scipy.linalg.solve para obtener una solución cerrada.

''sparse_cg'' usa el solucionador de gradiente conjugado como se encuentra en scipy.sparse.linalg.cg. Como un algoritmo iterativo, este solucionador es más apropiado que ''cholesky'' para datos a gran escala (posibilidad de establecer tol y max_iter).

''lsqr'' usa la rutina dedicada de mínimos cuadrados regularizados scipy.sparse.linalg.lsqr. Es el más rápido, pero puede no estar disponible en versiones antiguas de scipy. También usa un procedimiento iterativo.

''sag'' usa un descenso de Gradiente promedio estocástico, y ''saga'' usa su versión mejorada e imparcial llamada SAGA. Ambos métodos también usan un procedimiento iterativo, y suelen ser más rápidos que otros solucionadores cuando tanto n_samples como n_features son grandes. Tenga en cuenta que la convergencia rápida ''sag'' y ''saga'' solo está garantizada en funciones con aproximadamente la misma escala. Puede preprocesar los datos con un escalador desde sklearn.preprocessing.

Los últimos cinco solucionadores admiten datos densos y escasos. Sin embargo, solo ''sag'' y ''saga'' admiten entradas dispersas cuando fit_intercept es True.

Así que recomiendo probar: sparse_cg o quizás lsqr junto con CV manual. Si eso funciona (lo hago a mi perfección), lo que esperaría, este enfoque es mucho más estable / robusto (en comparación con los enfoques fuera del núcleo que utilizan SGD) y no es necesario ajustar mucho sus parámetros, que es una gran ventaja.

Por supuesto, uno siempre puede usar sag y sgd , pero la teoría de la convergencia se basa en algunas suposiciones fuertes con respecto al ajuste de parámetros. En entornos de gran escala, estos dos son candidatos viables (ya que otros no funcionarán), pero aquí no veo mucho merrit (una vez más: no estoy seguro de la cantidad de memoria que tienes). Si el enfoque anterior no funciona, pruebe saga before sgd y respete las reglas (estandarización + param-tuning). ( editar: ¡la caída es bastante mala para mis datos de prueba!)

Ejemplo:

from sklearn.datasets import make_regression from sklearn.linear_model import Ridge from time import perf_counter X, y, = make_regression(n_samples=38000, n_features=7000, n_informative=500, bias=-2.0, noise=0.1, random_state=0) print(type(X)) # dense!!! if your data is sparse; use that fact! clf = Ridge(alpha=1.0, solver="lsqr") start = perf_counter() clf.fit(X, y) end = perf_counter() print(''LSQR: used secs: '', end-start)

Salida:

LSQR: used secs: 8.489622474064486

Entonces, incluso en el caso denso, eso no es tan difícil de optimizar (y usa ~ 6-8 GB de memoria).

Y si bien tendría cuidado de implicar la equivalencia entre el modelo Ridge y el siguiente modelo Ridge basado en SGD (cuidado con qué variable es parte de la regularización, demasiado vago para verificarlo), aquí solo una demostración de lo difícil que es ajustar el SGD . Tome esto con un grano de sal (y tal vez no evalúe el puntaje absoluto, pero la varianza depende de los parámetros):

Observación: ¡ ese es un ejemplo más pequeño! Usando su ejemplo original, ninguno de los enfoques SGD obtendrá la convergencia sin establecer manualmente la tasa de aprendizaje eta_0 (¡ya que la heurística interna no puede hacer eso por usted!)

Código parcial:

X, y, = make_regression(n_samples=3800, n_features=700, n_informative=500, noise=0.1, random_state=0) print(type(X)) # dense!!! if your data is sparse; use that fact! clf = Ridge(alpha=1.0, solver="lsqr", fit_intercept=False) start = perf_counter() clf.fit(X, y) end = perf_counter() print(''LSQR: used secs: '', end-start) print(''train-score: '', clf.score(X, y)) clf = Ridge(alpha=1.0, solver="sparse_cg", fit_intercept=False) start = perf_counter() clf.fit(X, y) end = perf_counter() print(''sparse_cg: used secs: '', end-start) print(''train-score: '', clf.score(X, y)) clf = SGDRegressor(loss=''squared_loss'', penalty=''l2'', alpha=1., fit_intercept=False, random_state=0) start = perf_counter() clf.fit(X, y) end = perf_counter() print(''SGD: used secs: '', end-start) print(''train-score: '', clf.score(X, y)) clf = SGDRegressor(loss=''squared_loss'', penalty=''l2'', alpha=1., fit_intercept=False, random_state=0, average=True) start = perf_counter() clf.fit(X, y) end = perf_counter() print(''SGD: used secs: '', end-start) print(''train-score: '', clf.score(X, y)) clf = SGDRegressor(loss=''squared_loss'', penalty=''l2'', alpha=1., fit_intercept=False, random_state=0, learning_rate="constant", eta0=0.001) start = perf_counter() clf.fit(X, y) end = perf_counter() print(''SGD: used secs: '', end-start) print(''train-score: '', clf.score(X, y)) clf = SGDRegressor(loss=''squared_loss'', penalty=''l2'', alpha=1., fit_intercept=False, random_state=0, n_iter=50, average=True) start = perf_counter() clf.fit(X, y) end = perf_counter() print(''SGD: used secs: '', end-start) print(''train-score: '', clf.score(X, y))

Salida:

LSQR: used secs: 0.08252486090450709 train-score: 0.999999907282 sparse_cg: used secs: 0.13668818702548152 train-score: 0.999999181151 SGD: used secs: 0.04154542095705427 train-score: 0.743448766459 SGD: used secs: 0.05300238587407993 train-score: 0.774611911034 SGD: used secs: 0.038653031605587 train-score: 0.733585661919 SGD: used secs: 0.46313909066321507 train-score: 0.776444474871

Además: cuando se mini_batches el enfoque partial_fit / out-of-memory , también se necesita ajustar el tamaño de mini_batches (que se ignora en la demostración anterior -> SGD puro -> ¡una muestra a la vez)! Y otra vez: ¡esto no es fácil!