python - images - principal component analysis example
Uso de archivos de Memmap para el procesamiento por lotes (2)
¿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 usando 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.
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 al enjuagar el memmap por completo en el disco.
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()
.
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).