अंटी डॉट () और पायथन 3.5+ मैट्रिक्स गुणन @ के बीच अंतर


119

मैं हाल ही में पायथन 3.5 में गया और नए मैट्रिक्स गुणन ऑपरेटर (@) पर ध्यान दिया, कभी-कभी सुन्न डॉट ऑपरेटर से अलग व्यवहार करता है । उदाहरण के लिए, 3 डी सरणियों के लिए:

import numpy as np

a = np.random.rand(8,13,13)
b = np.random.rand(8,13,13)
c = a @ b  # Python 3.5+
d = np.dot(a, b)

@ऑपरेटर आकार की एक सरणी देता है:

c.shape
(8, 13, 13)

जबकि np.dot()समारोह रिटर्न:

d.shape
(8, 13, 8, 13)

मैं खतना डॉट के साथ एक ही परिणाम कैसे पुन: पेश कर सकता हूं? क्या कोई अन्य महत्वपूर्ण अंतर हैं?


5
आप उस परिणाम को डॉट से बाहर नहीं निकाल सकते। मुझे लगता है कि आमतौर पर लोग इस बात से सहमत थे कि हाई-डाइमेंशन इनपुट का डॉट का हैंडल गलत डिजाइन का फैसला था।
user2357112

उन्होंने matmulसालों पहले समारोह क्यों नहीं लागू किया ? @एक infix ऑपरेटर के रूप में नया है, लेकिन फ़ंक्शन इसके बिना भी काम करता है।
हंपुलज

जवाबों:


140

@ऑपरेटर सरणी के कॉल __matmul__विधि, नहीं dot। यह विधि कार्य के रूप में एपीआई में भी मौजूद है np.matmul

>>> a = np.random.rand(8,13,13)
>>> b = np.random.rand(8,13,13)
>>> np.matmul(a, b).shape
(8, 13, 13)

प्रलेखन से:

matmuldotदो महत्वपूर्ण तरीकों से अलग है।

  • स्केलर द्वारा गुणा करने की अनुमति नहीं है।
  • मैट्रिस के ढेरों को एक साथ प्रसारित किया जाता है जैसे कि मैट्रिस तत्व थे।

अंतिम बात यह है कि स्पष्ट करता है dotऔर matmulजब 3 डी (या उच्च आयामी) सरणियों पारित कर दिया तरीकों अलग ढंग से व्यवहार। प्रलेखन से कुछ और उद्धरण:

के लिए matmul:

यदि या तो तर्क एनडी, एन> 2 है, तो इसे पिछले दो अनुक्रमों में रहने वाले मेट्रिक्स के ढेर के रूप में माना जाता है और तदनुसार प्रसारित किया जाता है।

के लिए np.dot:

2-डी सरणियों के लिए यह मैट्रिक्स गुणन के बराबर है, और 1-डी सरणियों के लिए वैक्टर के आंतरिक उत्पाद (जटिल संयुग्मन के बिना) के लिए है। एन आयामों के लिए यह बी के अंतिम अक्ष और बी के दूसरे-से-अंतिम पर एक योग उत्पाद है


13
यहाँ भ्रम संभवतः रिलीज़ नोटों के कारण है, जो सीधे उदाहरण कोड में "@" प्रतीक को डॉट () के बराबर कार्य करते हैं।
एलेक्स के

12

@Ajcr द्वारा दिए गए उत्तर में बताया गया है कि कैसे ( dotऔर प्रतीक matmulद्वारा आह्वान @) अलग-अलग हैं। एक सरल उदाहरण को देखकर, एक स्पष्ट रूप से देखता है कि दोनों 'मैट्रिक या ढेर' के ढेर पर काम करते समय कैसे अलग व्यवहार करते हैं।

अंतर स्पष्ट करने के लिए 4x4 सरणी लें और 3x4x2 'मैट्रिक या स्टैक्टर के ढेर' के साथ dotउत्पाद और matmulउत्पाद लौटाएं।

import numpy as np
fourbyfour = np.array([
                       [1,2,3,4],
                       [3,2,1,4],
                       [5,4,6,7],
                       [11,12,13,14]
                      ])


threebyfourbytwo = np.array([
                             [[2,3],[11,9],[32,21],[28,17]],
                             [[2,3],[1,9],[3,21],[28,7]],
                             [[2,3],[1,9],[3,21],[28,7]],
                            ])

print('4x4*3x4x2 dot:\n {}\n'.format(np.dot(fourbyfour,twobyfourbythree)))
print('4x4*3x4x2 matmul:\n {}\n'.format(np.matmul(fourbyfour,twobyfourbythree)))

प्रत्येक ऑपरेशन के उत्पाद नीचे दिखाई देते हैं। ध्यान दें कि डॉट उत्पाद कैसा है,

... बी के अंतिम अक्ष पर एक योग उत्पाद और बी के दूसरे-से-अंतिम

और मैट्रिक्स को एक साथ प्रसारित करके मैट्रिक्स उत्पाद कैसे बनता है।

4x4*3x4x2 dot:
 [[[232 152]
  [125 112]
  [125 112]]

 [[172 116]
  [123  76]
  [123  76]]

 [[442 296]
  [228 226]
  [228 226]]

 [[962 652]
  [465 512]
  [465 512]]]

4x4*3x4x2 matmul:
 [[[232 152]
  [172 116]
  [442 296]
  [962 652]]

 [[125 112]
  [123  76]
  [228 226]
  [465 512]]

 [[125 112]
  [123  76]
  [228 226]
  [465 512]]]

2
dot (a, b) [i, j, k, m] = sum (a (i, j ,:] * b [k,:, m]) ------- जैसे प्रलेखन कहता है: यह a है बी के अंतिम अक्ष पर और बी के दूसरे-से-अंतिम अक्ष पर योग उत्पाद:
रौनक अग्रवाल

अच्छी पकड़ हालांकि, एक 3x4x2 है। मैट्रिक्स बनाने का एक और तरीका होगा a = np.arange(24).reshape(3, 4, 2)जो 3x4x2 के आयामों के साथ एक सरणी बनाएगा।
नाथन

8

बस FYI करें, @और इसके बराबर समकक्ष dotऔर matmulसभी लगभग समान रूप से तेज़ हैं। (प्लॉट परफ़ेक्ट , मेरी एक परियोजना के साथ बनाया गया है ।)

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

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

import perfplot
import numpy


def setup(n):
    A = numpy.random.rand(n, n)
    x = numpy.random.rand(n)
    return A, x


def at(data):
    A, x = data
    return A @ x


def numpy_dot(data):
    A, x = data
    return numpy.dot(A, x)


def numpy_matmul(data):
    A, x = data
    return numpy.matmul(A, x)


perfplot.show(
    setup=setup,
    kernels=[at, numpy_dot, numpy_matmul],
    n_range=[2 ** k for k in range(12)],
    logx=True,
    logy=True,
)

7

गणित में, मुझे लगता है कि अंको में डॉट अधिक समझ में आता है

डॉट (ए, बी) _ {आई, जे, के, ए, बी, सी} =सूत्र

चूंकि यह डॉट उत्पाद देता है जब ए और बी वैक्टर होते हैं, या मैट्रिक्स जब ए और बी मैट्रिक्स होते हैं


के रूप में matmul आपरेशन के लिए numpy में, यह डॉट परिणाम के कुछ हिस्सों के होते हैं , और इसे के रूप में परिभाषित किया जा सकता है

> मटमुल (ए, बी) _ {i, j, k, c} =सूत्र

तो, आप देख सकते हैं कि मटमुल (ए, बी) एक सरणी को एक छोटे आकार के साथ लौटाता है, जिसमें मेमोरी की छोटी खपत होती है और अनुप्रयोगों में अधिक समझ आती है। विशेष रूप से, प्रसारण के साथ संयोजन , आप प्राप्त कर सकते हैं

मटमुल (ए, बी) _ {i, j, k, l} =सूत्र

उदाहरण के लिए।


उपरोक्त दो परिभाषाओं से, आप उन दो कार्यों का उपयोग करने के लिए आवश्यकताओं को देख सकते हैं। A.shape = (s1, s2, s3, s4) और b.shape = (t1, t2, t3, t4) मान लें

  • डॉट (ए, बी) का उपयोग करने के लिए आपको चाहिए

    1. t3 = s4 ;
  • मैटमुल (ए, बी) का उपयोग करने के लिए आपको चाहिए

    1. t3 = एस 4
    2. t2 = s2 , या t2 और s2 में से एक 1 है
    3. t1 = s1 , या t1 और s1 में से एक 1 है

अपने आप को समझाने के लिए कोड के निम्नलिखित टुकड़े का उपयोग करें।

कोड नमूना

import numpy as np
for it in xrange(10000):
    a = np.random.rand(5,6,2,4)
    b = np.random.rand(6,4,3)
    c = np.matmul(a,b)
    d = np.dot(a,b)
    #print 'c shape: ', c.shape,'d shape:', d.shape

    for i in range(5):
        for j in range(6):
            for k in range(2):
                for l in range(3):
                    if not c[i,j,k,l] == d[i,j,k,j,l]:
                        print it,i,j,k,l,c[i,j,k,l]==d[i,j,k,j,l] #you will not see them

np.matmulवैक्टर पर डॉट उत्पाद और मैट्रिक्स पर मैट्रिक्स उत्पाद भी देता है।
सुभानिल लाहिड़ी

2

यहाँ यह np.einsumदिखाने के लिए तुलना की गई है कि सूचकांकों का अनुमान कैसे लगाया जाता है

np.allclose(np.einsum('ijk,ijk->ijk', a,b), a*b)        # True 
np.allclose(np.einsum('ijk,ikl->ijl', a,b), a@b)        # True
np.allclose(np.einsum('ijk,lkm->ijlm',a,b), a.dot(b))   # True

0

MATMUL और DOT के साथ मेरा अनुभव

जब मैं MATMUL का उपयोग करने की कोशिश कर रहा था, तो मुझे लगातार "ValueError: शेप ऑफ पास वैल्यूज़ (200, 1), इंडेक्स इम्प्ली (200, 3)" मिल रहा था। मैं एक त्वरित समाधान चाहता था और डीओटी को समान कार्यक्षमता प्रदान करने के लिए मिला। मुझे डॉट का उपयोग करने में कोई त्रुटि नहीं मिली। मुझे सही उत्तर मिला

MATMUL के साथ

X.shape
>>>(200, 3)

type(X)

>>>pandas.core.frame.DataFrame

w

>>>array([0.37454012, 0.95071431, 0.73199394])

YY = np.matmul(X,w)

>>>  ValueError: Shape of passed values is (200, 1), indices imply (200, 3)"

डॉट के साथ

YY = np.dot(X,w)
# no error message
YY
>>>array([ 2.59206877,  1.06842193,  2.18533396,  2.11366346,  0.28505879, 

YY.shape

>>> (200, )
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.