2011-06-08 13 views
9

Próbuję wczytać rzadką tablicę, którą wcześniej zapisałem. Zapisanie rzadkiej tablicy było dość łatwe. Próba przeczytania tego jest jednak uciążliwa. scipy.load zwraca tablicę 0d wokół mojej sparse array.Załaduj rzadką tablicę z pliku npy

import scipy as sp 
A = sp.load("my_array"); A 
array(<325729x325729 sparse matrix of type '<type 'numpy.int8'>' 
with 1497134 stored elements in Compressed Sparse Row format>, dtype=object) 

W celu uzyskania macierzy rzadkiej muszę spłaszczenia 0d tablicy lub użyć sp.asarray (A). Wydaje się, że to naprawdę trudny sposób robienia rzeczy. Czy Scipy jest na tyle sprytny, aby zrozumieć, że załadował rzadką tablicę? Czy istnieje lepszy sposób na załadowanie rzadkiej tablicy?

Odpowiedz

13

Funkcje w scipy.io mogą zapisywać/ładować rzadkie macierze w formacie Matrix Market.

scipy.io.mmwrite('/tmp/my_array',x) 
scipy.io.mmread('/tmp/my_array').tolil()  

mmwrite i mmread może być wszystko, czego potrzebujesz. Jest dobrze przetestowany i używa dobrze znanego formatu.

Jednak dodaje może być nieco szybciej:

Możemy zapisać się wierszy i kolumn współrzędnych i dane jako 1-D tablic w formacie NPZ.

import random 
import scipy.sparse as sparse 
import scipy.io 
import numpy as np 

def save_sparse_matrix(filename,x): 
    x_coo=x.tocoo() 
    row=x_coo.row 
    col=x_coo.col 
    data=x_coo.data 
    shape=x_coo.shape 
    np.savez(filename,row=row,col=col,data=data,shape=shape) 

def load_sparse_matrix(filename): 
    y=np.load(filename) 
    z=sparse.coo_matrix((y['data'],(y['row'],y['col'])),shape=y['shape']) 
    return z 

N=20000 
x = sparse.lil_matrix((N,N)) 
for i in xrange(N): 
    x[random.randint(0,N-1),random.randint(0,N-1)]=random.randint(1,100) 

save_sparse_matrix('/tmp/my_array',x) 
load_sparse_matrix('/tmp/my_array.npz').tolil() 

Oto kod, który proponuje zapisanie macierz rzadką w pliku NPZ może być szybsza niż w przypadku użycia mmwrite/mmread:

def using_np_savez():  
    save_sparse_matrix('/tmp/my_array',x) 
    return load_sparse_matrix('/tmp/my_array.npz').tolil() 

def using_mm(): 
    scipy.io.mmwrite('/tmp/my_array',x) 
    return scipy.io.mmread('/tmp/my_array').tolil()  

if __name__=='__main__': 
    for func in (using_np_savez,using_mm): 
     y=func() 
     print(repr(y)) 
     assert(x.shape==y.shape) 
     assert(x.dtype==y.dtype) 
     assert(x.__class__==y.__class__)  
     assert(np.allclose(x.todense(),y.todense())) 

wydajności

% python -mtimeit -s'import test' 'test.using_mm()' 
10 loops, best of 3: 380 msec per loop 

% python -mtimeit -s'import test' 'test.using_np_savez()' 
10 loops, best of 3: 116 msec per loop 
+1

+1, 'scipy.io' jest właściwym rozwiązaniem. Dodam, że jeśli chcesz zejść z drogi optymalizacji, możesz rozważyć opcję 'numpy.load (mmap_mode = 'r'/'c')'. Mapowanie pamięci plików z dysku daje natychmiastowe obciążenie ** i ** może zaoszczędzić pamięć, ponieważ ta sama tablica odwzorowana w pamięci może być współużytkowana w wielu procesach. – Radim

+0

scipy.io.savemat jest prawdopodobnie najlepszym – mathtick

+0

Użycie np_savez zamiast mm zmniejszyło mój czas ładowania dużej rozrzedzonej matrycy z 8min47 na 3s! Dzięki ! Próbowałem również savez_compressed, ale rozmiar jest taki sam, a czas ładowania znacznie dłuższy. – MatthieuBizien

4

Można wyodrębnić obiekt ukryty w tablicy 0d za pomocą() jako indeks:

A = sp.load("my_array")[()] 

To wygląda dziwnie, ale i tak wydaje się działać, i jest to bardzo krótkie obejście.

+0

Jestem prawie pewny, że możesz również użyć .item(), ale nie cytuj mnie na ten temat :) – David

0

Za wszystkie głosy w górę odpowiedzi mmwrite jestem zaskoczony, że nikt nie próbował odpowiedzieć na pytanie. Ale odkąd został reaktywowany, spróbuję.

ten odtwarza sprawę OP:

In [90]: x=sparse.csr_matrix(np.arange(10).reshape(2,5)) 
In [91]: np.save('save_sparse.npy',x) 
In [92]: X=np.load('save_sparse.npy') 
In [95]: X 
Out[95]: 
array(<2x5 sparse matrix of type '<type 'numpy.int32'>' 
    with 9 stored elements in Compressed Sparse Row format>, dtype=object) 
In [96]: X[()].A 
Out[96]: 
array([[0, 1, 2, 3, 4], 
     [5, 6, 7, 8, 9]]) 

In [93]: X[()].A 
Out[93]: 
array([[0, 1, 2, 3, 4], 
     [5, 6, 7, 8, 9]]) 
In [94]: x 
Out[94]: 
<2x5 sparse matrix of type '<type 'numpy.int32'>' 
    with 9 stored elements in Compressed Sparse Row format 

[()] że `user4713166 dał nam nie jest„twardy”sposób wyodrębnić rzadki tablicę.

np.save i np.load są przeznaczone do pracy na ndarrays. Ale rzadka macierz nie jest taką tablicą, ani nie jest podklasą (tak jak jest to np.matrix). Wygląda na to, że np.save zawija obiekt nieszablonowy w postaci object dtype array i zapisuje go wraz z piklowaną formą obiektu.

Gdy próbuję zapisać inny rodzaj obiektu, taki, który nie może być marynowane, pojawia się komunikat o błędzie na stronie:

403 # We contain Python objects so we cannot write out the data directly. 
404 # Instead, we will pickle it out with version 2 of the pickle protocol. 

-> 405 pickle.dump (array, fp, protokół = 2)

Tak więc w odpowiedzi na Is Scipy smart enough to understand that it has loaded a sparse array?, nie. np.load nie wie o rzadkich tablicach.Ale np.save jest na tyle sprytny, że daje punt, gdy otrzymuje coś, co nie jest tablicą, a np.load robi to, co może, jeśli znajdzie w pliku.

Jeśli chodzi o alternatywne metody zapisywania i ładowania rzadkich macierzy, wspomniano o metodzie zgodnej z MATLAB, io.savemat. To byłby mój pierwszy wybór. Ale ten przykład pokazuje również, że możesz używać zwykłego Pythona pickling. To może być lepsze, jeśli chcesz zapisać konkretny format. I np.save nie jest zły, jeśli możesz żyć z krokiem ekstrakcji [()]. :)


https://github.com/scipy/scipy/blob/master/scipy/io/matlab/mio5.py write_sparse - rzadki są zapisywane w formacie csc. Wraz z nagłówkami zapisuje A.indices.astype('i4')), A.indptr.astype('i4')), A.data.real i opcjonalnie A.data.imag.


W szybkich testów uważam, że np.save/load obsługuje wszystkie formaty rzadkie, z wyjątkiem dok, gdzie load o brakującym shape. W przeciwnym razie nie znajdę żadnego specjalnego kodu wytrawiania w plikach rozrzedzonych.

Powiązane problemy