2015-08-24 26 views
5

मेरे पास एक numpy सरणी ए है, जिसमें आकार (10,) है।मनमानी आयामों के सरणी के साथ numpy सरणी गुणा

मेरे पास भी है, इस पल के रूप में, आकार के साथ एक numpy सरणी बी (10,3,5)। मैं सी प्राप्त करने के लिए इन दोनों के बीच गुणा करना चाहता हूं जैसे सी [0,:,:] = ए [0] * बी [0,:,:], सी [1] = ए [1] * बी [1 ,:,:], आदि

मैं इसे लूप के साथ काम नहीं करना चाहता, एक कारण यह सौंदर्य की बात है, दूसरा यह है कि इस कोड को बहुत सामान्य होना चाहिए। मैं चाहता हूं कि जब तक अग्रणी आयाम 10 हो, तब तक उपयोगकर्ता किसी भी आकार के किसी भी बी को इनपुट करने में सक्षम होना चाहता है। उदाहरण के लिए, मैं चाहता हूं कि उपयोगकर्ता आकार के बी (10,4) में भी सक्षम हो।

तो: मैं numpy का उपयोग करके इस गुणा को कैसे कार्यान्वित कर सकता हूं? धन्यवाद।

अतिरिक्त: उदाहरण के लिए पूछा गया है। छोटा हो जाएगा। मान लें कि ए numpy सरणी है [1,2,3] और बी numpy सरणी [[1,2], [4,5], [7,8]] है। मैं चाहता हूं कि दोनों के गुणा [[1,2], [8,10], [21,24]] में हो। ...

>>> a 
array([1, 2, 3]) 
>>> b 
array([[1, 2], 
     [4, 5], 
     [7, 8]]) 
>>> #result 
>>> c 
array([[ 1, 2], 
     [ 8, 10], 
     [21, 24]]) 
>>> 
+1

शामिल करें, * छोटे *, उदाहरण के सरणियों और उम्मीद उत्पादन। – wwii

+0

यदि 'बी'' (3,5,10) 'है, तो 'ए * बी' काम करता है।'numpy' स्वचालित रूप से आवश्यकतानुसार आयाम जोड़ता है (MATLAB उन्हें अंत में जोड़ता है)। – hpaulj

+0

जैसा ऊपर बताया गया है, प्रसारण जोड़े जोड़े के दाएं-दाएं आयामों से। इसका मतलब है कि '(ए * बीटी) .' गुणा के लिए लंबाई 10s से मेल खाता है और एक सामान्य समाधान होगा, लेकिन मुझे लगता है कि डीएसएम द्वारा सुझाए गए' इन्सुम 'दृष्टिकोण तर्कसंगत रूप से अच्छे हैं। –

उत्तर

4

आप B मैच के लिए A विस्तार करने के लिए None (या np.newaxis) इस्तेमाल कर सकते हैं:

>>> A = np.arange(10) 
>>> B = np.random.random((10,3,5)) 
>>> C0 = np.array([A[i]*B[i,:,:] for i in range(len(A))]) 
>>> C1 = A[:,None,None] * B 
>>> np.allclose(C0, C1) 
True 

लेकिन यह केवल 2 मामले के लिए काम करेंगे। @ajcr से उधार, पर्याप्त transposes साथ हम सामान्य स्थिति के लिए काम करने के लिए अंतर्निहित प्रसारण प्राप्त कर सकते हैं:

>>> C3 = (A * B.T).T 
>>> np.allclose(C0, C3) 
True 

वैकल्पिक रूप से, आप einsum इस्तेमाल कर सकते हैं व्यापकता प्रदान करने के लिए। पूर्व-निरीक्षण में यह संभवतः ट्रांसपोज़र रूट की तुलना में अधिक हो गया है, लेकिन यह आसान है जब गुणा अधिक जटिल होते हैं।

>>> C2 = np.einsum('i,i...->i...', A, B) 
>>> np.allclose(C0, C2) 
True 

और

>>> B = np.random.random((10,4)) 
>>> D0 = np.array([A[i]*B[i,:] for i in range(len(A))]) 
>>> D2 = np.einsum('i,i...->i...', A, B) 
>>> np.allclose(D0, D2) 
True 
+0

वाह, कुछ परिष्कृत सामान, IMHO! वास्तव में, अपने पहले एक एक संपादन के साथ अच्छी तरह से काम करता है: >>> np.array ([एक [i] * बी [i] के लिए मैं सीमा में (लेन (ए))]) के साथ किसी भी समस्या देखते हैं? धन्यवाद! –

+1

@ bob.sacamento: नहीं, यह काम करना चाहिए - मैं बस अपने ब्रूट-बल उदाहरण की प्रतिलिपि बना रहा था। लेकिन चूंकि यह धीमी सूची से सरणी बनाता है, यह बड़े आकार के लिए धीमा हो जाएगा, और केवल परीक्षण उद्देश्यों के लिए उपयोग किया जाना चाहिए। – DSM

+1

यह उबाऊ और असजीला है, लेकिन 'एक [(टुकड़ा (कोई नहीं),) + (कोई नहीं,) * (b.ndim - 1)] * b' भी बकवास हो जाता ... – Jaime

1

हालांकि मैं einsum अंकन की तरह, मैं मिश्रण करने के लिए एक छोटे से विविधता जोड़ देंगे ....

आप ताकि a करने के लिए पर्याप्त अतिरिक्त आयाम जोड़ सकते हैं यह broadcastb पर होगा।

>>> a.shape 
(3,) 
>>> b.shape 
(3,2) 

ba

extra_dims = b.ndim - a.ndim 

a

new_shape = a.shape + (1,)*extra_dims # (3,1) 
new_a = a.reshape(new_shape) 

को गुणा

new_a * b 
अतिरिक्त आयाम (रों) जोड़े की तुलना में अधिक आयाम

एक समारोह के रूप में:

def f(a, b): 
    '''Product across the first dimension of b. 

    Assumes a is 1-dimensional. 
    Raises AssertionError if a.ndim > b.ndim or 
    - the first dimensions are different 
    ''' 
    assert a.shape[0] == b.shape[0], 'First dimension is different' 
    assert b.ndim >= a.ndim, 'a has more dimensions than b' 

    # add extra dimensions so that a will broadcast 
    extra_dims = b.ndim - a.ndim 
    newshape = a.shape + (1,)*extra_dims 
    new_a = a.reshape(newshape) 

    return new_a * b 
संबंधित मुद्दे