2011-07-27 6 views
26

Pracuję z dość dużymi, rzadkimi matrycami (od 5000x5000 do 20000x20000) i muszę znaleźć skuteczny sposób łączenia macierzy w elastyczny sposób, aby skonstruować stochastyczną macierz z oddzielnych części.Czy istnieje skuteczny sposób łączenia macierzy scipy.sparse?

W tej chwili używam poniższego sposobu do łączenia czterech macierzy, ale jest to strasznie nieefektywne. Czy istnieje lepszy sposób na zrobienie tego, który nie wymaga konwersji na gęstą matrycę?

rmat[0:m1.shape[0],0:m1.shape[1]] = m1 
rmat[m1.shape[0]:rmat.shape[0],m1.shape[1]:rmat.shape[1]] = m2 
rmat[0:m1.shape[0],m1.shape[1]:rmat.shape[1]] = bridge 
rmat[m1.shape[0]:rmat.shape[0],0:m1.shape[1]] = bridge.transpose() 

Odpowiedz

14

OK, znalazłem odpowiedź. Używanie scipy.sparse.coo_matrix jest znacznie szybsze niż użycie lil_matrix. Przekształciłem matryce na "coo" (bezbolesne i szybkie), a następnie połączyłem dane, wiersze i kolumny po dodaniu odpowiedniego wypełnienia.

data = scipy.concatenate((m1S.data,bridgeS.data,bridgeTS.data,m2S.data)) 
rows = scipy.concatenate((m1S.row,bridgeS.row,bridgeTS.row + m1S.shape[0],m2S.row + m1S.shape[0])) 
cols = scipy.concatenate((m1S.col,bridgeS.col+ m1S.shape[1],bridgeTS.col ,m2S.col + m1S.shape[1])) 

scipy.sparse.coo_matrix((data,(rows,cols)),shape=(m1S.shape[0]+m2S.shape[0],m1S.shape[1]+m2S.shape[1])) 
+1

Dzięki za powrót i skomentowanie tego, jak szybko to zrobiliście. Potrzebowałem go do mojej klasy NLP. – placeybordeaux

42

Rzadki biblioteki ma teraz hstack i vstack do odpowiednio łącząc macierze poziomo i pionowo.

+1

Upewnij się, że używasz scipy.sparse.hstack zamiast numpy.hstack – 0111001101110000

9

Używanie hstack, vstack lub concatenate, jest znacznie wolniejsze niż konkatenacja samych wewnętrznych obiektów danych. Powodem jest to, że hstack/vstack konwertuje rzadką macierz na format coo, który może być bardzo powolny, gdy macierz jest bardzo duża, a nie w formacie coo. Oto kod na łączenie CSC matryce podobny sposób mogą być wykorzystane na rzecz CSR matryc:

def concatenate_csc_matrices_by_columns(matrix1, matrix2): 
    new_data = np.concatenate((matrix1.data, matrix2.data)) 
    new_indices = np.concatenate((matrix1.indices, matrix2.indices)) 
    new_ind_ptr = matrix2.indptr + len(matrix1.data) 
    new_ind_ptr = new_ind_ptr[1:] 
    new_ind_ptr = np.concatenate((matrix1.indptr, new_ind_ptr)) 

    return csc_matrix((new_data, new_indices, new_ind_ptr)) 
+1

Właśnie patrzyłeś na szybki sposób dodawania nowych wierszy do matrycy CSR. Dokładnie tego potrzebuję. Dzięki @amos. – singleton

+0

Jeśli użyjesz tej metody, musisz określić kształt w 'return csc_matrix ((new_data, new_indices, new_ind_ptr))' ie ': return csc_matrix ((nowa_data, nowe_indeksy, nowy_ind_ptr), kształt = (matrix1.shape [1], matrix1.shape [1] + matrix2.shape [1]) ' – simeon

4

odpowiedź Amos nie jest już konieczne. Scipy robi teraz coś podobnego wewnętrznie, jeśli macierze wejściowe są w formacie csr lub csc, a żądany format wyjściowy jest ustawiony na brak lub taki sam format jak matryce wejściowe. Skuteczne jest pionowe układanie macierzy w formacie csr lub poziomo układanie macierzy w formacie csc, przy użyciu odpowiednio scipy.sparse.vstack lub scipy.sparse.hstack.

+0

Która z wersji odnosi się do "teraz"? Czy masz jakieś odniesienie do tego? – lenz

+0

Odpowiedni kod to [ten fragment] (https://github.com /scipy/scipy/blob/master/scipy/sparse/construct.py#L552) z 'scipy.sparse.bmat', którego używają zarówno' vstack', jak i 'hstack'. Ten hack został pierwotnie dodany [tutaj] (https: //github.com/scipy/scipy/commit/10b2cbdc980c6e1695c732c90fba99f722437171) w roku 2013. wygląda na to, że został pierwotnie zawarte w scipy 1.0.0. –

+0

Dzięki! scipy 1.0.0 jest nadal w fazie RC, choć ... – lenz