2013-06-07 21 views
6

bir çok büyük bir dizinin iç ilave şimdi işlem bir vermelidirçarpımı ve şekli (M, N) ait bir dizi A sahip

R = (A[:,newaxis,:] * A[newaxis,:,:]).sum(2) yapmak istiyorum (MxM) dizisi. Sorun şu ki, dizi oldukça büyük ve MxMxN dizisi belleğe sığmayacağı için bir Bellek hatası alıyorum.

Bunu yapmak için en iyi strateji ne olurdu? C? harita()? ya da bunun için henüz özel bir işlev var mı?

Sana diziler ne kadar büyük olduğundan emin değilim Davut'a

+0

Gerçekten bir MxN dizisi var mı? Sanırım bir [:, newaxis,:] 'bir MxN dizisidir. O zaman bile, 'A [:, yeni eksen ,:] * A [yeni eksen,:,:] '2 boyutlu bir dizi vermelidir, bu yüzden' toplamı (2) anlamıyorum, çünkü üçüncü bir eksen yoktur (veya newaxis bir dilim değil, tek bir sayıdır). Burada bir şey eksik. – Evert

+0

Gereken hassasiyete bağlı olarak, dizinin içindeki değerler için farklı bir tür kullanmayı deneyebilirsiniz. Örneğin, numpy.float32' veya "numpy.int16". Bu, bellek gereksinimlerinizi yarıya indirebilir. – Evert

+0

@Evert A [:, np.newaxis,:]. Şekil == (M, 1, N) ve (A [:, np.newaxis ,:] * A [np.newaxis,:,:]). == (M, M, N) – JoshAdel

cevap

7

, teşekkür ederim ancak aşağıdaki eşdeğerdir:

R = np.einsum('ij,kj',A,A) 

Ve biraz daha hızlı olabilir ve daha az bellek yoğun olduğu:

In [7]: A = np.random.random(size=(500,400)) 

In [8]: %timeit R = (A[:,np.newaxis,:] * A[np.newaxis,:,:]).sum(2) 
1 loops, best of 3: 1.21 s per loop 

In [9]: %timeit R = np.einsum('ij,kj',A,A) 
10 loops, best of 3: 54 ms per loop 

Ben Calculatio aracılığıyla A(500,4000) için, np.einsum pullukların boyutunu artırırsanız n yaklaşık 2 saniye içinde orijinal formülasyon, oluşturmam gereken geçici dizinin boyutu nedeniyle makinemi durduracaktır.

Güncelleme: @Jaime olarak

Açıklamalarda belirttiği, np.dot(A,A.T) da sorunun eşdeğer formülasyon olduğunu ve daha da hızlı np.einsum çözümden çok olabilir. Bunu belirtmek için ona tam kredi, ancak resmi bir çözüm olarak yayınlamaması durumunda, ana cevaba çekmek istedim.

+7

+1 Ancak OP'nin hesaplaması da np.dot (A, AT) 'ile eşdeğerdir ve sistemimde bir (500, 400) şekilli dizi için, np.einsum'dan yaklaşık 10x daha hızlıdır. zaten OP'nin yönteminden 6 kat daha hızlı. – Jaime

+0

@Jaime iyi yakalamak. Bunu bir cevap olarak yayınla ve onu tekrar yazalım. fwiw, 'np.dot', makinemde (500.400) np.einsum'dan sadece 2,5 kat daha hızlıdır. (500,4000) için, np.dot, yaklaşık 10x daha hızlıdır. – JoshAdel

+0

Ben bir itibar fahişe değilim, sadece o kadar değil ... ;-) Eğer istiyorsanız, np.dot zamanlamaları göndermek için çekinmeyin, tek bir cevap ile daha temiz olacağını düşünüyorum. – Jaime

İlgili konular