Estou procurando uma maneira rápida de preservar grandes matrizes numpy. Quero salvá-los no disco em um formato binário e depois lê-los de volta na memória de forma relativamente rápida. Infelizmente, o cPickle não é rápido o suficiente.
Encontrei numpy.savez e numpy.load . Mas o mais estranho é que o numpy.load carrega um arquivo npy no "mapa da memória". Isso significa que a manipulação regular de matrizes é realmente lenta. Por exemplo, algo assim seria muito lento:
#!/usr/bin/python
import numpy as np;
import time;
from tempfile import TemporaryFile
n = 10000000;
a = np.arange(n)
b = np.arange(n) * 10
c = np.arange(n) * -0.5
file = TemporaryFile()
np.savez(file,a = a, b = b, c = c);
file.seek(0)
t = time.time()
z = np.load(file)
print "loading time = ", time.time() - t
t = time.time()
aa = z['a']
bb = z['b']
cc = z['c']
print "assigning time = ", time.time() - t;
mais precisamente, a primeira linha será realmente rápida, mas as linhas restantes que atribuem as matrizes obj
são ridiculamente lentas:
loading time = 0.000220775604248
assining time = 2.72940087318
Existe alguma maneira melhor de preservar matrizes numpy? Idealmente, desejo poder armazenar várias matrizes em um arquivo.
np.load
deve mapear o arquivo.numpy.savez
), o padrão é "carregar preguiçosamente" as matrizes. Ele não está mapeando-os, mas não os carrega até que oNpzFile
objeto seja indexado. (Assim, o atraso do OP está se referindo.) A documentação paraload
saltos isso, e é, portanto, um toque enganosa ...Respostas:
Sou um grande fã do hdf5 por armazenar grandes matrizes numpy. Existem duas opções para lidar com o hdf5 em python:
http://www.pytables.org/
http://www.h5py.org/
Ambos são projetados para trabalhar com matrizes numpy de maneira eficiente.
fonte
Comparei o desempenho (espaço e tempo) de várias maneiras de armazenar matrizes numpy. Poucos deles suportam várias matrizes por arquivo, mas talvez seja útil de qualquer maneira.
Arquivos Npy e binários são realmente rápidos e pequenos para dados densos. Se os dados forem escassos ou muito estruturados, convém usar o npz com compactação, o que economizará muito espaço, mas custará algum tempo de carregamento.
Se a portabilidade é um problema, o binário é melhor que o npy. Se a legibilidade humana for importante, você terá que sacrificar muito desempenho, mas isso pode ser alcançado bastante bem usando o csv (que também é muito portátil, é claro).
Mais detalhes e o código estão disponíveis no repositório do github .
fonte
binary
é melhor do quenpy
a portabilidade? Isso também se aplicanpz
?Agora existe um clone baseado em HDF5
pickle
chamadohickle
!https://github.com/telegraphic/hickle
EDITAR:
Também existe a possibilidade de "selecionar" diretamente em um arquivo compactado, fazendo:
Apêndice
fonte
savez () salva dados em um arquivo zip. Pode levar algum tempo para compactar e descompactar o arquivo. Você pode usar a função save () & load ():
Para salvar várias matrizes em um arquivo, basta abrir o arquivo primeiro e depois salvar ou carregar as matrizes em sequência.
fonte
Outra possibilidade de armazenar matrizes numpy com eficiência é o Bloscpack :
e a saída do meu laptop (um MacBook Air relativamente antigo com um processador Core2):
isso significa que ele pode armazenar muito rápido, ou seja, o gargalo é tipicamente o disco. No entanto, como as taxas de compressão são muito boas aqui, a velocidade efetiva é multiplicada pelas taxas de compressão. Aqui estão os tamanhos para essas matrizes de 76 MB:
Observe que o uso do compressor Blosc é fundamental para conseguir isso. O mesmo script, mas usando 'clevel' = 0 (ou seja, desativando a compactação):
está claramente afunilado pelo desempenho do disco.
fonte
O tempo de pesquisa é lento porque, quando você usa
mmap
, não carrega o conteúdo da matriz na memória quando invoca oload
método. Os dados são carregados com preguiça quando dados específicos são necessários. E isso acontece na pesquisa no seu caso. Mas a segunda pesquisa não será tão lenta.Esse é um recurso interessante
mmap
quando você tem uma grande matriz e não precisa carregar dados inteiros na memória.Para resolver o seu pode usar joblib, você pode despejar qualquer objeto que desejar usando
joblib.dump
dois ou maisnumpy arrays
, veja o exemplofonte