images example component python numpy scikit-learn pca

python - example - Uso de archivos de Memmap para el procesamiento por lotes



principal component analysis example (2)

Tengo un enorme conjunto de datos en el que deseo PCA. Estoy limitado por la RAM y la eficiencia computacional de PCA. Por lo tanto, cambié al uso de Iterative PCA.

Tamaño del conjunto de datos- (140000,3504)

La documentación indica que This algorithm has constant memory complexity, on the order of batch_size, enabling use of np.memmap files without loading the entire file into memory.

Esto es realmente bueno, pero no está seguro de cómo aprovechar esto.

Intenté cargar un memmap con la esperanza de que tuviera acceso a él en fragmentos, pero mi RAM explotó. Mi código a continuación termina usando mucha RAM:

ut = np.memmap(''my_array.mmap'', dtype=np.float16, mode=''w+'', shape=(140000,3504)) clf=IncrementalPCA(copy=False) X_train=clf.fit_transform(ut)

Cuando digo "mi RAM estalló", el Traceback que veo es:

Traceback (most recent call last): File "<stdin>", line 1, in <module> File "C:/Python27/lib/site-packages/sklearn/base.py", line 433, in fit_transfo rm return self.fit(X, **fit_params).transform(X) File "C:/Python27/lib/site-packages/sklearn/decomposition/incremental_pca.py", line 171, in fit X = check_array(X, dtype=np.float) File "C:/Python27/lib/site-packages/sklearn/utils/validation.py", line 347, in check_array array = np.array(array, dtype=dtype, order=order, copy=copy) MemoryError

¿Cómo puedo mejorar esto sin comprender la precisión reduciendo el tamaño del lote?

Mis ideas para diagnosticar:

Miré el código fuente sklearn y en la función fit() Código fuente Puedo ver lo siguiente. Esto tiene sentido para mí, pero todavía no estoy seguro de lo que está mal en mi caso.

for batch in gen_batches(n_samples, self.batch_size_): self.partial_fit(X[batch]) return self

Edición: en el peor de los casos, tendré que escribir mi propio código para el PICA iterativo, que procesa por lotes leyendo y cerrando archivos .npy. Pero eso vencería el propósito de aprovechar el hack ya presente.

Edit2: Si de alguna manera pudiera eliminar un lote de memmap file procesado de memmap file . Tendría mucho sentido.

Edit3: Idealmente, si IncrementalPCA.fit () solo usa lotes, no debería bloquear mi RAM. Publicando todo el código, solo para asegurarme de que no estoy cometiendo un error antes de enjuagar completamente el memmap.

temp_train_data=X_train[1000:] temp_labels=y[1000:] out = np.empty((200001, 3504), np.int64) for index,row in enumerate(temp_train_data): actual_index=index+1000 data=X_train[actual_index-1000:actual_index+1].ravel() __,cd_i=pywt.dwt(data,''haar'') out[index] = cd_i out.flush() pca_obj=IncrementalPCA() clf = pca_obj.fit(out)

Sorprendentemente, noto que out.flush no libera mi memoria. ¿Hay alguna forma de utilizar del out para liberar completamente mi memoria y luego alguien pasa un puntero del archivo a IncrementalPCA.fit() .


¿Solo lo siguiente desencadena el bloqueo?

X_train_mmap = np.memmap(''my_array.mmap'', dtype=np.float16, mode=''w+'', shape=(n_samples, n_features)) clf = IncrementalPCA(n_components=50).fit(X_train_mmap)

De lo contrario, puede usar ese modelo para transformar (proyectar sus datos de forma iterativa) en datos más pequeños utilizando lotes:

X_projected_mmap = np.memmap(''my_result_array.mmap'', dtype=np.float16, mode=''w+'', shape=(n_samples, clf.n_components)) for batch in gen_batches(n_samples, self.batch_size_): X_batch_projected = clf.transform(X_train_mmap[batch]) X_projected_mmap[batch] = X_batch_projected

No he probado ese código, pero espero que entiendas la idea.


Ha sklearn un problema con sklearn en un entorno de 32 bits. Supongo que está usando np.float16 porque está en un entorno de 32 bits y necesita eso para permitirle crear el objeto memmap sin numpy thowing errors.

En un entorno de 64 bits (probado con Python3.3 de 64 bits en Windows), su código funciona de la caja. Por lo tanto, si tiene una computadora de 64 bits disponible, instale python 64 bit y numpy , scipy , scikit-learn 64 bit y listo.

Desafortunadamente, si no puedes hacer esto, no hay una solución fácil. He planteado un problema en github aquí , pero no es fácil de parchear. El problema fundamental es que dentro de la biblioteca, si su tipo es float16 , se float16 una copia de la matriz a la memoria. El detalle de esto está abajo.

Entonces, espero que tengas acceso a un entorno de 64 bits con mucha RAM. Si no, tendrás que dividir tu matriz por ti mismo y procesarla por lotes, una tarea bastante más grande ...

NB: es realmente bueno verte ir a la fuente para diagnosticar tu problema :) Sin embargo, si miras la línea donde falla el código (del Traceback), verás que el código del for batch in gen_batches que encontraste nunca alcanzado.

Diagnóstico detallado:

El error real generado por el código OP:

import numpy as np from sklearn.decomposition import IncrementalPCA ut = np.memmap(''my_array.mmap'', dtype=np.float16, mode=''w+'', shape=(140000,3504)) clf=IncrementalPCA(copy=False) X_train=clf.fit_transform(ut)

es

Traceback (most recent call last): File "<stdin>", line 1, in <module> File "C:/Python27/lib/site-packages/sklearn/base.py", line 433, in fit_transfo rm return self.fit(X, **fit_params).transform(X) File "C:/Python27/lib/site-packages/sklearn/decomposition/incremental_pca.py", line 171, in fit X = check_array(X, dtype=np.float) File "C:/Python27/lib/site-packages/sklearn/utils/validation.py", line 347, in check_array array = np.array(array, dtype=dtype, order=order, copy=copy) MemoryError

La llamada a check_array ( enlace de código ) usa dtype=np.float , pero la matriz original tiene dtype=np.float16 . Aunque la función check_array() defecto copy=False y pasa esto a np.array() , esto se ignora ( según los documentos ), para satisfacer el requisito de que el dtype sea ​​diferente; por lo tanto, np.array hace una copia.

Esto podría resolverse en el código IncrementalPCA asegurándose de que el tipo de dtype se conserva para las matrices con dtype in (np.float16, np.float32, np.float64) . Sin embargo, cuando probé ese parche, solo empujó el MemoryError más a lo largo de la cadena de ejecución.

El mismo problema de copia ocurre cuando el código llama a linalg.svd() desde el código scipy principal y esta vez el error ocurre durante una llamada a gesdd() , una función nativa lapack de lapack . Por lo tanto, no creo que haya una manera de parchear esto (al menos no de una manera fácil, es como mínimo la alteración del código en el núcleo del scipy).