Próbuję zaimplementować funkcję w NumPy/Scipy, aby obliczyć Jensen-Shannon divergence między pojedynczym (treningowym) wektorem i dużą liczbą innych wektorów (obserwacji). Wektory obserwacyjne są przechowywane w bardzo dużym (500 000 x 65536) Scipy sparse matrix (gęsta macierz nie mieści się w pamięci).Dodawanie macierzy bardzo powtarzalnej do rzadkiej w numpy/scipy?
jako część algorytmu potrzebne do obliczenia T + O i dla każdego wektora obserwacji O i, gdzie T jest wektorem szkolenia. Nie byłem w stanie znaleźć sposobu, aby to zrobić używając zwykłych reguł rozgłaszania NumPy, ponieważ rzadkie macierze nie wydają się wspierać tych (jeśli T jest pozostawiona jako gęstą tablicę, Scipy próbuje najpierw zrobić gęstą macierz, która działa brak pamięci, jeśli ustawię T na rzadką macierz, T + O i zawodzi, ponieważ kształty są niespójne).
Obecnie Biorę rażąco nieefektywne krok kafli wektor treningowy do 500,000x65536 rozrzedzony matrycy:
training = sp.csr_matrix(training.astype(np.float32))
tindptr = np.arange(0, len(training.indices)*observations.shape[0]+1, len(training.indices), dtype=np.int32)
tindices = np.tile(training.indices, observations.shape[0])
tdata = np.tile(training.data, observations.shape[0])
mtraining = sp.csr_matrix((tdata, tindices, tindptr), shape=observations.shape)
Ale to zajmuje ogromną ilość pamięci (około 6 GB), gdy jest przechowywanie tylko ~ 1500 "prawdziwych" elementów. Jest również dość powolny w konstruowaniu.
Próbowałem uzyskać sprytny przy użyciu stride_tricks, aby indptr w matrycy CSR i członkowie danych nie korzystali z dodatkowej pamięci na powtarzanych danych.
training = sp.csr_matrix(training)
mtraining = sp.csr_matrix(observations.shape,dtype=np.int32)
tdata = training.data
vdata = np.lib.stride_tricks.as_strided(tdata, (mtraining.shape[0], tdata.size), (0, tdata.itemsize))
indices = training.indices
vindices = np.lib.stride_tricks.as_strided(indices, (mtraining.shape[0], indices.size), (0, indices.itemsize))
mtraining.indptr = np.arange(0, len(indices)*mtraining.shape[0]+1, len(indices), dtype=np.int32)
mtraining.data = vdata
mtraining.indices = vindices
Ale to nie działa, ponieważ strided odsłony mtraining.data i mtraining.indices są niewłaściwy kształt (i według this answer nie ma sposobu, aby to prawo kształt). Próba sprawienia, by wyglądały płasko, używając iteratora płaskiego, nie działa, ponieważ nie wygląda wystarczająco jak tablica (np. Nie ma elementu typu dtype), a użycie metody spłaszczania() kończy się tworzeniem kopii.
Czy jest jakiś sposób, aby to zrobić?
Jeśli chcesz wygenerować wszystkie sumy na raz, to będziesz potrzebować 6GB pamięci masowej tak, tak naprawdę nie ma nic do wygrania, opóźniając to. Po prostu upewnij się, że dokonujesz podsumowania w miejscu, z '+ ='! Nawiasem mówiąc, twoja implementacja kafelkowania jest bardzo inteligentna i wydajna, nie sądzę, że możesz uzyskać coś lepszego: Próbowałem przesłać 'csr_matrix' widok wektora przekształconego' as_strided', który ma 500000 wierszy, oraz zajęło to znacznie dłużej niż twoje podejście, myślę, że wewnętrznie kopiuje się tablicę, łamiąc magię. Twoje drugie podejście, jak zauważyłeś, nie może być wykonane za pomocą numpy. – Jaime
Macierzy CSR nie mogą być modyfikowane w miejscu, niestety (+ = podbicie niezatwierdzone). Sądzę więc, że utknąłem z użyciem 3x tyle pamięci, ile ja (teoretycznie) potrzebuję, co jest bolesne, ponieważ zbliżam się do granic mojego (wspaniałego) 32GB. –