एक संख्यात्मक सरणी में गुणा


89

मैं 1d सरणी में संबंधित शर्तों द्वारा 2 डी सरणी में प्रत्येक शब्द को गुणा करने की कोशिश कर रहा हूं। यह बहुत आसान है अगर मैं हर कॉलम को 1D सरणी से गुणा करना चाहता हूं, जैसा कि numpy.multiply फ़ंक्शन में दिखाया गया है । लेकिन मैं इसके विपरीत करना चाहता हूं, पंक्ति में प्रत्येक शब्द को गुणा करें। दूसरे शब्दों में, मैं गुणा करना चाहता हूँ:

[1,2,3]   [0]
[4,5,6] * [1]
[7,8,9]   [2]

और पाओ

[0,0,0]
[4,5,6]
[14,16,18]

लेकिन इसके बजाय मुझे मिलता है

[0,2,6]
[0,5,12]
[0,8,18]

क्या किसी को पता है कि वहाँ एक सुंदर तरीका है कि सुन्न के साथ है? बहुत बहुत धन्यवाद, एलेक्स


3
जैसे ही मैंने प्रश्न प्रस्तुत किया, आह मुझे यह समझ में आ गया। पहले वर्ग मैट्रिक्स को स्थानांतरित करें, गुणा करें, फिर उत्तर को स्थानांतरित करें।
एलेक्स एस

पंक्ति को स्तंभ मैट्रिक्स में स्थानांतरित करने के लिए बेहतर है तो आपको उत्तर को फिर से स्थानांतरित करने की आवश्यकता नहीं है। यदि A * Bआपको ऐसा करना है A * B[...,None]जो Bएक नई अक्ष ( None) जोड़कर स्थानांतरित करता है ।
Askewchan

धन्यवाद, यह सच है। समस्या तब होती है जब आपके पास 1D सरणी कॉलिंग है .transpose () या .T पर यह कॉलम कॉलम में बदल नहीं जाता है, यह इसे एक पंक्ति के रूप में छोड़ देता है, इसलिए जहां तक ​​मुझे पता है कि आपको इसे कॉलम के रूप में परिभाषित करना होगा। सही बल्ले से। जैसे x = [[1],[2],[3]]या कुछ और।
एलेक्स एस

जवाबों:


119

सामान्य गुणन जैसे आपने दिखाया:

>>> import numpy as np
>>> m = np.array([[1,2,3],[4,5,6],[7,8,9]])
>>> c = np.array([0,1,2])
>>> m * c
array([[ 0,  2,  6],
       [ 0,  5, 12],
       [ 0,  8, 18]])

यदि आप एक अक्ष जोड़ते हैं, तो यह आपके इच्छित तरीके को गुणा करेगा:

>>> m * c[:, np.newaxis]
array([[ 0,  0,  0],
       [ 4,  5,  6],
       [14, 16, 18]])

आप दो बार संक्रमण भी कर सकते हैं:

>>> (m.T * c).T
array([[ 0,  0,  0],
       [ 4,  5,  6],
       [14, 16, 18]])

नए अक्ष विधि के साथ दो 1D सरणियों को गुणा करना और 2 डी सरणी उत्पन्न करना संभव है। जैसे [a,b] op [c,d] -> [[a*c, b*c], [a*d, b*d]]
kon psych

50

मैंने गति के विभिन्न विकल्पों की तुलना की है और पाया है कि - मेरे आश्चर्य के लिए - सभी विकल्प (छोड़कर diag) समान रूप से तेज़ हैं। मैं व्यक्तिगत रूप से उपयोग करता हूं

A * b[:, None]

(या (A.T * b).T) क्योंकि यह छोटा है।

यहाँ छवि विवरण दर्ज करें


प्लॉट को फिर से तैयार करने के लिए कोड:

import numpy
import perfplot


def newaxis(data):
    A, b = data
    return A * b[:, numpy.newaxis]


def none(data):
    A, b = data
    return A * b[:, None]


def double_transpose(data):
    A, b = data
    return (A.T * b).T


def double_transpose_contiguous(data):
    A, b = data
    return numpy.ascontiguousarray((A.T * b).T)


def diag_dot(data):
    A, b = data
    return numpy.dot(numpy.diag(b), A)


def einsum(data):
    A, b = data
    return numpy.einsum("ij,i->ij", A, b)


perfplot.save(
    "p.png",
    setup=lambda n: (numpy.random.rand(n, n), numpy.random.rand(n)),
    kernels=[
        newaxis,
        none,
        double_transpose,
        double_transpose_contiguous,
        diag_dot,
        einsum,
    ],
    n_range=[2 ** k for k in range(13)],
    xlabel="len(A), len(b)",
)

2
प्लॉट के लिए कोड प्रदान करने वाला अच्छा स्पर्श। धन्यवाद।
चट्टानेनवीस

17

आप मैट्रिक्स गुणा (उर्फ डॉट उत्पाद) का भी उपयोग कर सकते हैं:

a = [[1,2,3],[4,5,6],[7,8,9]]
b = [0,1,2]
c = numpy.diag(b)

numpy.dot(c,a)

जो अधिक सुरुचिपूर्ण है वह शायद स्वाद का मामला है।


2
अच्छा, +1, इस बारे में नहीं सोचा
jterrace

10
dotवास्तव में यहाँ overkill है। आप केवल 0 से अनावश्यक गुणा कर रहे हैं और
द्वि

2
यदि आप nxd मैट्रिक्स में nx1 वेक्टर को गुणा करना चाहते हैं, जहां d n से बड़ा है, तो यह स्मृति समस्याओं को भी ट्रिगर कर सकता है।
जोनासन

डाउनवोटिंग के रूप में यह धीमा है और घने diagमैट्रिक्स बनाते समय बहुत अधिक मेमोरी का उपयोग करता है ।
निको श्लोमर

16

फिर भी एक और चाल (v1.6 के रूप में)

A=np.arange(1,10).reshape(3,3)
b=np.arange(3)

np.einsum('ij,i->ij',A,b)

मैं सुन्न प्रसारण ( newaxis) के साथ कुशल हूं , लेकिन मैं अभी भी इस नए einsumटूल के आसपास अपना रास्ता ढूंढ रहा हूं । इसलिए मैंने इस समाधान को खोजने के लिए थोड़ा सा खेल किया था।

समय (Ipython timeit का उपयोग करके):

einsum: 4.9 micro
transpose: 8.1 micro
newaxis: 8.35 micro
dot-diag: 10.5 micro

संयोग से, एक iको बदलने के लिए j, np.einsum('ij,j->ij',A,b)मैट्रिक्स का उत्पादन करता है जो एलेक्स नहीं चाहता है। और np.einsum('ji,j->ji',A,b)करता है, वास्तव में, डबल संक्रमण।


1
यदि आप कंप्यूटर पर इसे बड़े पैमाने पर सरणियों के साथ समय देंगे, तो यह कम से कम कुछ मिलीसेकंड लेगा और आपके प्रासंगिक सिस्टम जानकारी के साथ परिणाम यहां पोस्ट करेगा यह बहुत सराहना की जाएगी।
डैनियल

1
एक बड़ी सरणी (100x100) के साथ सापेक्ष संख्याएँ लगभग समान हैं। einsumm(25 माइक्रो) दूसरों की तुलना में दोगुना है (डॉट-डायग अधिक धीमा हो जाता है)। यह np 1.7 है, जो 'libatlas3gf-sse2' और 'libatlas-base-dev' (Ubuntu 10.4, सिंगल प्रोसेसर) के साथ नए सिरे से संकलित है। timeit10000 लूप का सर्वश्रेष्ठ देता है।
hpaulj

1
यह एक महान जवाब है और मुझे लगता है कि यह वही है जिसे स्वीकार किया जाना चाहिए था। हालांकि, ऊपर लिखा कोड वास्तव में, मैट्रिक्स देता है एलेक्स (मेरी मशीन पर) से बचने की कोशिश कर रहा था। एक हंपुलज ने कहा कि गलत वास्तव में सही है।
यार डॉन

यहां समय गुमराह कर रहा है। डॉट-डायग वास्तव में अन्य तीन विकल्पों की तुलना में कहीं अधिक खराब है, और जिन्सम दूसरों की तुलना में तेज नहीं है।
निको श्लोमर

@ NicoSchlömer, मेरा उत्तर लगभग 5 वर्ष पुराना है, और कई numpyसंस्करण वापस आ गए हैं।
हंपुलज

1

Google पर उन खोई हुई आत्माओं के लिए, numpy.expand_dimsतब numpy.repeatकाम करेगा, और उच्च आयामी मामलों में भी काम करेगा (यानी एक (10, 12) द्वारा एक आकृति (10, 12, 3 को गुणा करना)।

>>> import numpy
>>> a = numpy.array([[1,2,3],[4,5,6],[7,8,9]])
>>> b = numpy.array([0,1,2])
>>> b0 = numpy.expand_dims(b, axis = 0)
>>> b0 = numpy.repeat(b0, a.shape[0], axis = 0)
>>> b1 = numpy.expand_dims(b, axis = 1)
>>> b1 = numpy.repeat(b1, a.shape[1], axis = 1)
>>> a*b0
array([[ 0,  2,  6],
   [ 0,  5, 12],
   [ 0,  8, 18]])
>>> a*b1
array([[ 0,  0,  0],
   [ 4,  5,  6],
   [14, 16, 18]])

-4

तुम बस क्यों नहीं करते

>>> m = np.array([[1,2,3],[4,5,6],[7,8,9]])
>>> c = np.array([0,1,2])
>>> (m.T * c).T

??


6
उस सटीक दृष्टिकोण को पहले से ही स्वीकृत उत्तर में दिखाया गया है, मैं नहीं देखता कि यह कैसे कुछ भी जोड़ता है।
बौम Augen mit
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.