2017-02-10 9 views
8

एपीएल या जे जैसे अधिकांश सरणी उन्मुख भाषाओं में सामान्यीकृत आंतरिक उत्पाद का कुछ रूप है, जो मानक मैट्रिक्स गुणा की तरह कार्य कर सकता है, लेकिन मानक वाले स्थान पर मनमाने ढंग से संचालन का समर्थन करता है। उदाहरण के लिए, जे +/ . * में मानक गुणा-फिर-योग है, लेकिन आप यह भी कर सकते हैं उदा। <./ . + एक ऐड-एंड-मिन ऑपरेशन प्राप्त करने के लिए (ग्राफ़ के माध्यम से सबसे कम पथ की लंबाई को बढ़ाने के लिए कहें)।क्या numpy एक सामान्यीकृत आंतरिक उत्पाद प्रदान करता है?

import numpy as np 

def general_inner(f, g, x, y): 
    return np.array([[f(g(x1, y1)) for y1 in y.T] for x1 in x]) 

x = np.arange(1, 5, dtype="float").reshape((2, 2)) 
y = np.array([[0.9], [0.1]]) 
assert(x.dot(y) == general_inner(np.sum, np.multiply, x, y)) 

numpy कुछ भी सीधे इस पद्धति का समर्थन करने के प्रदान करता है:

धीमी गति से और 2 डी-केवल पायथन में, यह कुछ की तरह हो सकता है?

+0

तो (ज़िप में x + y एक्स के लिए, वाई (xx, yy)) 'मिनट में के रूप में मिनट, जोड़े' (नियमित अजगर में)? –

+0

हम सभी को जम्मू और पायथन दोनों के बारे में पता नहीं है। –

+0

@DietrichEpp बिल्कुल नहीं - मैंने यह दिखाने के लिए प्रश्न अपडेट किया कि मैं जो खोज रहा हूं उसके बारे में एक गरीब पायथन कार्यान्वयन कैसा दिखता है। – llasram

उत्तर

4

आप स्लाइसिंग के साथ वहां जा सकते हैं। हम दो तर्कों को दोबारा बदल सकते हैं ताकि एक ऑपरेशन तत्व के बजाए प्रसारण के बजाय प्रसारित हो सके, और फिर अवांछित धुरी के साथ एक कम करने वाला ऑपरेशन करें।

import numpy 

a = numpy.array([[1, 2, 3], 
       [4, 5, 6]]) 
b = numpy.array([[7, 8], 
       [9, 10], 
       [11, 12]]) 

# Ordinary matrix multiplication 
print(a @ b) 
# Matrix multiplication using broadcasting 
print(numpy.sum(a[:,:,numpy.newaxis] * b[numpy.newaxis,:,:], axis=1)) 
# Our "generalized" version 
print(numpy.min(a[:,:,numpy.newaxis] + b[numpy.newaxis,:,:], axis=1)) 

मैं इसे एक "सामान्यीकृत आंतरिक उत्पाद" कॉल करने के लिए है, क्योंकि भीतरी उत्पादों एक विशिष्ट गणितीय संरचना है कि इस नए संस्करण का अभाव है संकोच होगा।

तरीका यह मूल रूप से काम करता है कि किसी भी numpy.newaxis 1 की लंबाई है और प्रसारित हो जाता है, तो:

result[i,j,k] = a[i,j] * b[j,k] 

या अगर यह समझना मदद करता है (मुझे लगता है:

a[:,:,numpy.newaxis] * b[numpy.newaxis,:,:] 

हमें देता है कभी-कभी थोड़ा उलझन में प्रसारण),

aa = a[:,:,numpy.newaxis] 
bb = b[numpy.newaxis,:,:] 
result[i,j,k] = aa[i,j,0] * bb[0,j,k] 
+0

आह हा! मैंने numpy दस्तावेज में 'newaxis' देखा होगा, लेकिन यह समझ में नहीं आया कि यह उपयोगी होगा। धन्यवाद। – llasram

+0

ध्यान दें कि यदि इनपुट बड़े हैं, तो यह काफी मात्रा में स्मृति का उपयोग कर सकता है। –

4

इतना धीमा numpy समकक्ष g(x,y.T) है, प्रसारण का उपयोग करते हुए, f(..., axis=1) के बाद।

In [136]: general_inner(np.sum, np.multiply, x, y) 
Out[136]: 
array([[ 1.1], 
     [ 3.1]]) 
In [137]: np.multiply(x,y.T) 
Out[137]: 
array([[ 0.9, 0.2], 
     [ 2.7, 0.4]]) 
In [138]: np.sum(np.multiply(x,y.T),axis=1) 
Out[138]: array([ 1.1, 3.1]) 
इसी तरह रकम की अधिकतम के लिए

:

In [145]: general_inner(np.max, np.add, x, y) 
Out[145]: 
array([[ 2.1], 
     [ 4.1]]) 
In [146]: np.max(np.add(x,y.T), axis=1) 
Out[146]: array([ 2.1, 4.1]) 

वहाँ में संभावित भ्रम है कि np.add, np.multiply, np.maximum, ufunc रहे हैं, जबकि np.sum, np.prod, np.max नहीं हैं, लेकिन एक axis पैरामीटर लेते हैं, और keepdims। (संपादित करें: np.add.reducenp.sum की ufunc बराबर है।)

In [152]: np.max(np.add(x,y.T), axis=1, keepdims=True) 
Out[152]: 
array([[ 2.1], 
     [ 4.1]]) 

np.einsum भीतर बात की इस तरह लागू करने के लिए एक पुराने वृद्धि अनुरोध किया गया था। यह इंडेक्सिंग पर उच्च स्तर पर नियंत्रण के साथ sum of products गणना लागू करता है। तो अवधारणा यह एक ही अनुक्रमण नियंत्रण के साथ max of sums प्रदर्शन कर सकता है। लेकिन जहां तक ​​मुझे पता है कि किसी ने इसे लागू करने की कोशिश नहीं की है।

सामान्यीकृत आंतरिक उत्पाद एपीएल की एक प्यारी विशेषता थी (यह कई दशकों पहले मेरी प्राथमिक भाषा थी)। लेकिन स्पष्ट रूप से इतना उपयोगी नहीं है कि यह भाषाओं के उस परिवार से निकल गया। MATLAB में ऐसा कुछ भी नहीं है।

क्या कुछ ऐसा है जो एपीएल & जे इस निर्माण के साथ कर सकता है, जिसे numpy में किया जा सकता है जिस तरह से हमने प्रदर्शित किया है?


अधिक सामान्य x और y आकार के साथ, मैं newaxis जोड़ने के लिए अन्य जवाब

In [176]: x = np.arange(3*4).reshape(4,3) 
In [177]: y = np.arange(3*2).reshape(3,2) 
In [178]: np.sum(np.multiply(x[...,None],y[None,...]),axis=1) 
Out[178]: 
array([[10, 13], 
     [28, 40], 
     [46, 67], 
     [64, 94]]) 
In [179]: np.max(np.add(x[...,None],y[None,...]),axis=1) 
Out[179]: 
array([[ 6, 7], 
     [ 9, 10], 
     [12, 13], 
     [15, 16]]) 

3 डी का सामान्यीकरण के रूप में दी, के अंतिम मद्धिम/2 पिछले की matmul विचार का उपयोग करते समय की जरूरत है matmul:

In [195]: x = np.arange(2*4*5).reshape(2,4,5) 
In [196]: y = np.arange(2*5*3).reshape(2,5,3) 
In [197]: np.einsum('ijk,ikm->ijm', x, y).shape 
Out[197]: (2, 4, 3) 
In [203]: np.add.reduce(np.multiply(x[...,None], y[...,None,:,:]), axis=-2).shape 
Out[203]: (2, 4, 3) 

# shapes broadcast: (2,4,5,n) * (2,n,5,3) => (2,4,5,3); sum on the 5 

तो numpy (और MATLAB) एक विशेष नहीं है, जबकि APL जैसे सिंटैक्स, एक विस्तार (आउटटर) ऑपरेशन का विचार कमी के बाद काफी आम है।

अन्य ufunc परीक्षण:

In [205]: np.maximum.reduce(np.add(x[...,None], y[...,None,:,:]), axis=-2).shape 
Out[205]: (2, 4, 3) 
In [208]: np.logical_or.reduce(np.greater(x[...,None], y[...,None,:,:]), axis=-2).shape 
Out[208]: (2, 4, 3) 
+0

सूचक के लिए धन्यवाद 'einsum' और अतिरिक्त ऐतिहासिक संदर्भ, लेकिन यह' newaxis' की कमी के कारण थोड़ा गलत लगता है। – llasram

+0

हां, मैंने उस विवरण की उपेक्षा की। तथ्य यह है कि 'वाई.टी.' (1, एन) आकार दिया गया था, मुझे बिना 'न्यूएक्सिस' के, इसे (2,2) के साथ प्रसारित करने दें। और मैंने एक त्वरित फिक्स के रूप में उपयोग किया, 'keepdims'' '1' आयाम को पुनर्स्थापित करने के लिए। – hpaulj

संबंधित मुद्दे