2011-12-06 7 views
5

Soy nuevo en Python, que viene de MATLAB. Tengo una gran matriz dispersa guardada en el formato de matlab v7.3 (HDF5). Hasta ahora he encontrado dos maneras de cargar en el archivo, usando h5py y tables. Sin embargo, operar en la matriz parece ser extremadamente lento después de cualquiera. Por ejemplo, en Matlab:Cargando Matlab matriz dispersa guardado con -v7.3 (HDF5) en Python y operar en él

>> whos  
    Name   Size     Bytes Class  Attributes 

    M  11337x133338   77124408 double sparse  

>> tic, sum(M(:)); toc 
Elapsed time is 0.086233 seconds. 

Uso de tablas:

t = time.time() 
sum(f.root.M.data) 
elapsed = time.time() - t 
print elapsed 
35.929461956 

Usando h5py:

t = time.time() 
sum(f["M"]["data"]) 
elapsed = time.time() - t 
print elapsed 

(renuncié a la espera ...)

[EDIT]

Según los comentarios de @bpgergo, debo añadir que he intentado convertir el resultado cargada en por h5py (f) en una matriz de numpy o una matriz dispersa scipy de las dos maneras siguientes:

from scipy import sparse 
A = sparse.csc_matrix((f["M"]["data"], f["M"]["ir"], f["tfidf"]["jc"])) 

o

data = numpy.asarray(f["M"]["data"]) 
ir = numpy.asarray(f["M"]["ir"]) 
jc = numpy.asarray(f["M"]["jc"])  
    A = sparse.coo_matrix(data, (ir, jc)) 

pero ambas operaciones son extremadamente lentas también.

¿Hay algo que me falta aquí?

Respuesta

3

mayor parte de su problema es que estás usando Python sum en lo que es efectivamente una matriz de memoria mapeada (es decir, es en el disco, no en la memoria).

En primer lugar, usted está comparando el tiempo que se tarda en leer cosas desde el disco al tiempo que se tarda en leer cosas en la memoria. Primero, cargue la matriz en la memoria, si desea compararla con lo que está haciendo en matlab.

En segundo lugar, de orden interna sum Python es muy inefficent para matrices numpy. (O, más bien, iterar a través de todos los elementos de una matriz numpy es independiente muy lento, lo que es lo pitón de orden interna sum está haciendo.) Use numpy.sum(yourarray) o yourarray.sum() lugar para las matrices numpy.

A modo de ejemplo:

(. Usando h5py, porque estoy más familiarizado con él)

import h5py 
import numpy as np 

f = h5py.File('yourfile.hdf', 'r') 
dataset = f['/M/data'] 

# Load the entire array into memory, like you're doing for matlab... 
data = np.empty(dataset.shape, dataset.dtype) 
dataset.read_direct(data) 

print data.sum() #Or alternately, "np.sum(data)" 
+0

Cargando el archivo fue casi instantáneo en Matlab (<1seg), así que creo que la comparación fue justa, pero considero su punto acerca de la función de suma incorporada. Creo que cada vez más personas harán lo que estoy haciendo (pasar de Matlab a Python), por lo que sería bueno si hubiera un poco más de soporte para cargar en los archivos de Matlab en mi humilde opinión ... – tdc

+1

Bueno, no puedo pruébalo sin tu archivo, pero cargar el arreglo en python también debería ser muy rápido. Lo que estás haciendo actualmente no es realmente cargarlo. Renueve lo que efectivamente es una matriz mapeada en memoria. Acceder a él de manera independiente será muy lento en cualquier idioma, ya que es principalmente disco busca. ¿El código de ejemplo anterior es lento? Además, eche un vistazo a 'scipy.io.loadmat' http://docs.scipy.org/doc/scipy/reference/generated/scipy.io.loadmat.html#scipy.io.loadmat, aunque no estoy seguro si es compatible con matrices dispersas. –

+0

no tuve la oportunidad de probarlo, pero gracias por la entrada – tdc

0
+0

más pistas? Si hago 'M = numpy.asarray (f [" M "] [" data "])' esto parece llevar una eternidad ... – tdc

+0

@tdc, ni siquiera sé qué es 'f' en tu código. Intente consultar en esta página: http://docs.scipy.org/doc/scipy/reference/generated/scipy.io.loadmat.html. Aunque lo leí, todavía necesitarás una lib lib de HDF5 para cargar los archivos de v7.3 Matlab. – bpgergo

+0

También no hay nada allí sobre matrices dispersas – tdc

1

La respuesta final para la posteridad:

import tables, warnings 
from scipy import sparse 

def load_sparse_matrix(fname) : 
    warnings.simplefilter("ignore", UserWarning) 
    f = tables.openFile(fname) 
    M = sparse.csc_matrix((f.root.M.data[...], f.root.M.ir[...], f.root.M.jc[...])) 
    f.close() 
    return M 
Cuestiones relacionadas