2013-02-07 5 views
18

2 NumPy सरणी होने की कल्पना कीजिए:क्या कोई नुकीला/scipy डॉट उत्पाद है, परिणाम की केवल विकर्ण प्रविष्टियों की गणना?

> A, A.shape = (n,p) 
> B, B.shape = (p,p) 

आमतौर पर पी, एक छोटी संख्या (पी < = 200) है, जबकि एन मनमाने ढंग से बड़ा हो सकता है।

मैं निम्नलिखित कर रहा हूँ:

result = np.diag(A.dot(B).dot(A.T)) 

आप देख सकते हैं, मैं सिर्फ n विकर्ण प्रविष्टियों रख रहा हूँ, लेकिन वहाँ एक मध्यवर्ती (एन एक्स एन) सरणी गणना की है जहाँ से केवल विकर्ण प्रविष्टियों रखा जाता है।

मैं diag_dot() जैसे फ़ंक्शन की कामना करता हूं, जो केवल परिणाम की विकर्ण प्रविष्टियों की गणना करता है और पूर्ण स्मृति आवंटित नहीं करता है।

एक परिणाम होगा:

> result = diag_dot(A.dot(B), A.T) 

वहाँ इस तरह एक premade कार्यक्षमता है और इस कुशलता से मध्यवर्ती (एन एक्स एन) सरणी आवंटित करने के लिए आवश्यकता के बिना किया जा सकता है?

उत्तर

18

मैं मैं अपने दम पर यह मिल गया लगता है, लेकिन फिर भी समाधान का हिस्सा होगा: एक आव्यूह गुणन

> Z = N.diag(X.dot(Y)) 

का केवल विकर्ण हो रही के बाद से

अदिश उत्पाद के अलग-अलग राशि के बराबर है

> Z = (X * Y.T).sum(-1) 

मूल चर इसका मतलब यह है के लिए:: एक्स और वाई के स्तंभों की पंक्तियों की, पिछले बयान के बराबर है

> result = (A.dot(B) * A).sum(-1) 

कृपया मुझे सही कर अगर मैं गलत हूँ लेकिन यह यह होना चाहिए ...

+5

+1 स्मार्ट बीजगणित हमेशा परिष्कृत एल्गोरिदम से बेहतर है। – Jaime

21

आप क्या तुमने कभी numpy.einsum साथ का सपना देखा लगभग कुछ भी प्राप्त कर सकते हैं। जब तक आप इसके बारे में लटका हो रही शुरू करते हैं, यह मूल रूप से काले वूडू की तरह लगता है ...

>>> a = np.arange(15).reshape(5, 3) 
>>> b = np.arange(9).reshape(3, 3) 

>>> np.diag(np.dot(np.dot(a, b), a.T)) 
array([ 60, 672, 1932, 3840, 6396]) 
>>> np.einsum('ij,ji->i', np.dot(a, b), a.T) 
array([ 60, 672, 1932, 3840, 6396]) 
>>> np.einsum('ij,ij->i', np.dot(a, b), a) 
array([ 60, 672, 1932, 3840, 6396]) 

संपादित आप वास्तव में एक भी गोली में पूरी बात प्राप्त कर सकते हैं, यह हास्यास्पद है ...

>>> np.einsum('ij,jk,ki->i', a, b, a.T) 
array([ 60, 672, 1932, 3840, 6396]) 
>>> np.einsum('ij,jk,ik->i', a, b, a) 
array([ 60, 672, 1932, 3840, 6396]) 

EDIT आप इसे अपने आप पर बहुत अधिक नहीं दिखाना चाहते हैं ... तुलना के लिए ओपी का उत्तर अपने प्रश्न के उत्तर में भी जोड़ा गया।

n, p = 10000, 200 
a = np.random.rand(n, p) 
b = np.random.rand(p, p) 

In [2]: %timeit np.einsum('ij,jk,ki->i', a, b, a.T) 
1 loops, best of 3: 1.3 s per loop 

In [3]: %timeit np.einsum('ij,ij->i', np.dot(a, b), a) 
10 loops, best of 3: 105 ms per loop 

In [4]: %timeit np.diag(np.dot(np.dot(a, b), a.T)) 
1 loops, best of 3: 5.73 s per loop 

In [5]: %timeit (a.dot(b) * a).sum(-1) 
10 loops, best of 3: 115 ms per loop 
+0

मुझे यह फ़ंक्शन ज्ञात नहीं है - लेकिन निश्चित रूप से अब ऐसा करेगा। साझा करने के लिए Thx !!! – user2051916

1

एक पैदल यात्री जवाब, जो बड़े मध्यवर्ती सरणियों के निर्माण से बचा जाता है है:

result=np.empty([n.], dtype=A.dtype) 
for i in xrange(n): 
    result[i]=A[i,:].dot(B).dot(A[i,:]) 
संबंधित मुद्दे