2012-04-22 19 views
9

Me agarraron el conjunto de datos pista1 KDD de Kaggle y decidieron cargar un archivo CSV de 3 columnas ~ 2,5 GB en la memoria, en mi 16GB instancia EC2 de alta memoria:principales problemas de la memoria de lectura en un archivo CSV con numpy

data = np.loadtxt('rec_log_train.txt') 

la sesión de pitón consumió toda mi memoria (100%), y luego me mataron.

Luego leí el mismo archivo usando R (a través de read.table) y utilizó menos de 5GB de memoria RAM, que colapsó a menos de 2GB después de llamar al recolector de basura.

Mi pregunta es por qué esto falló en numpy, y cuál es la forma correcta de leer un archivo en la memoria. Sí, puedo usar generadores y evitar el problema, pero ese no es el objetivo.

+0

relacionado http://stackoverflow.com/questions/8956832/python-out-of-memory-on-large-csv-file-numpy – Anycorn

+0

Si la precisión es simple, 'np.fromfile/np.loadtxt (dtype = np.float32) 'tomará menos memoria, luego' X = X.astype (np.float64) 'cuando termine. – denis

Respuesta

6
import pandas, re, numpy as np 

def load_file(filename, num_cols, delimiter='\t'): 
    data = None 
    try: 
     data = np.load(filename + '.npy') 
    except: 
     splitter = re.compile(delimiter) 

     def items(infile): 
      for line in infile: 
       for item in splitter.split(line): 
        yield item 

     with open(filename, 'r') as infile: 
      data = np.fromiter(items(infile), float64, -1) 
      data = data.reshape((-1, num_cols)) 
      np.save(filename, data) 

    return pandas.DataFrame(data) 

Esto lee en el archivo de 2,5 GB, y serializa la matriz de salida. El archivo de entrada se lee "perezosamente", por lo que no se construyen estructuras de datos intermedias y se utiliza una memoria mínima. La carga inicial lleva mucho tiempo, pero cada carga posterior (del archivo serializado) es rápida. Por favor, déjame si tienes consejos!

+1

Si especifica el número de columnas a priori, ¿por qué no hacer algo como esto: https://gist.github.com/2465280? En una nota lateral, para hacer una matriz desde un generador, use 'np.fromiter'. –

+0

¡actualizado! Muchas gracias! – vgoklani

Cuestiones relacionadas