न्यूमरी मैट्रिक्स बनाम एरे कक्षाओं के लिए गुणन कैसे भिन्न होता है?


130

मैट्रिक्स के साथ काम करने के लिए मैट्रिक्स के बजाय सरणी का उपयोग करने के लिए सुन्न डॉक्स की सलाह देते हैं। हालाँकि, ऑक्टेव के विपरीत (जो मैं हाल तक उपयोग कर रहा था), * मैट्रिक्स गुणा नहीं करता है, आपको फ़ंक्शन मैट्रिक्समूलिप्टी () का उपयोग करने की आवश्यकता है। मुझे लगता है कि यह कोड को बहुत ही अपठनीय बनाता है।

क्या कोई मेरे विचारों को साझा करता है, और कोई समाधान ढूंढता है?


8
आप राय पूछ रहे हैं, सवाल नहीं। क्या कुछ और विशिष्ट है जो हम आपकी मदद कर सकते हैं या शायद इसे और अधिक पठनीय बनाने में आपका मार्गदर्शन कर सकते हैं?
गेहूं

2
यदि आप रेखीय बीजगणित करते हैं तो डॉक्स मैट्रिक्स का उपयोग करने की सलाह देते हैं और समस्या के कई गुणा () का उपयोग नहीं करना चाहते हैं?
मत्ती पेस्टल

1
मैंने डॉक्स के बारे में विस्तार से नहीं जाना है। बस जिज्ञासु, क्या लाभ मैट्रिक्स वर्ग पर प्रदान करता है? मैंने पाया कि सरणियाँ पंक्तियों और स्तंभों के बीच अंतर नहीं करती हैं। क्या ऐसा इसलिए है क्योंकि एरे को मैट्रिस के बजाय टेंसर्स के रूप में माना जाता है? जैसा कि जो ने बताया, तथ्य यह है कि मैट्रिक्स वर्ग 2-मंद काफी सीमित है। इस तरह के डिजाइन के पीछे क्या सोच है, जैसे कि मैटलब / ऑक्टेव की तरह एक भी मैट्रिक्स क्लास क्यों नहीं है?
इलेक्सहॉबी

मुझे लगता है कि मुख्य मुद्दा यह है कि अजगर के पास .*तत्व वार बनाम मैट्रिक्स गुणन के लिए बनाम '*' वाक्यविन्यास नहीं है । यदि ऐसा होता है, तो यह सब सरल होगा हालांकि मुझे आश्चर्य है कि वे *तत्व-वार का मतलब चुनते हैं और मैट्रिक्स गुणन नहीं।
चार्ली पार्कर

जवाबों:


127

matrixकक्षा का उपयोग करने से बचने का मुख्य कारण यह है कि ए) यह स्वाभाविक रूप से 2-आयामी है, और बी) "सामान्य" सुन्न सरणी की तुलना में अतिरिक्त ओवरहेड है। यदि आप सब कर रहे हैं रैखिक बीजगणित, तो हर तरह से, मैट्रिक्स वर्ग का उपयोग करने के लिए स्वतंत्र महसूस हो रहा है ... व्यक्तिगत रूप से मुझे लगता है कि यह मूल्य की तुलना में अधिक परेशानी है, हालांकि।

सरणियों के लिए (पायथन 3.5 से पहले), के dotबजाय का उपयोग करें matrixmultiply

उदाहरण के लिए

import numpy as np
x = np.arange(9).reshape((3,3))
y = np.arange(3)

print np.dot(x,y)

या सुन्न के नए संस्करणों में, बस का उपयोग करें x.dot(y)

व्यक्तिगत रूप से, मैं इसे *मैट्रिक्स गुणा को लागू करने वाले ऑपरेटर की तुलना में बहुत अधिक पठनीय पाता हूं ...

पायथन 3.5 में सरणियों के लिए, का उपयोग करें x @ y


10
जब आप एक्स ' ए' * ए एक्स के लिए गुणा का ढेर लगाते हैं तो यह अपठनीय होता है ।
ईलेक्सहॉबी

14
@elexhobby - x.T.dot(A.T).dot(A).dot(x)यह अपठनीय नहीं है, यद्यपि प्रत्येक अपने स्वयं के लिए, हालांकि। यदि आप मुख्य रूप से मैट्रिक्स गुणा कर रहे हैं, तो हर तरह से, उपयोग करें numpy.matrix!
जो किंग्सटन

7
वैसे, मैट्रिक्स गुणन को "डॉट" क्यों कहा जाता है? किस मायने में यह एक डॉट उत्पाद है?
amcnabb

8
@amcnabb - मैट्रिक्स गुणन को कभी-कभी पाठ्यपुस्तकों में "डॉट उत्पाद" के रूप में संदर्भित किया जाता है (उन पुस्तकों में, जिस डॉट उत्पाद के बारे में आप सोच रहे हैं उसे "स्केलर उत्पाद" या "स्केलर डॉट उत्पाद" कहा जाता है)। स्केलर डॉट उत्पाद केवल दो वैक्टर का मैट्रिक्स गुणन है, सब के बाद, इसलिए सामान्य रूप से मैट्रिक्स गुणा का "डॉट" का उपयोग करना अधिक खिंचाव नहीं है। गणित की तुलना में इंजीनियरिंग और विज्ञान के ग्रंथों में यह विशेष रूप से संकेतन (?) अधिक सामान्य लगता है, कम से कम मेरे अनुभव में। सुन्न में इसका प्रचलन ज्यादातर इसलिए numpy.matrixmultiplyहै क्योंकि टाइप करना कठिन है।
जो किंगटन

7
@amcnabb बिंदु यह है कि बिंदु अस्पष्टता के बिना मनमानी आयामीता का सामान्यीकरण करता है। यह वह है जो numpy.dotमैट्रिक्स गुणा के बराबर बनाता है। यदि आप वास्तव में संकेतन को नापसंद करते हैं, तो matrixकक्षा का उपयोग करें ।
हेनरी गोमर्सल

80

NumPy सरणियों पर कार्रवाई के लिए जानने के लिए महत्वपूर्ण चीजें बनाम NumPy मैट्रिसेस पर संचालन निम्न हैं:

  • NumPy मैट्रिक्स NumPy सरणी का एक उपवर्ग है

  • NumPy सरणी संचालन तत्व-वार हैं (एक बार प्रसारण के लिए जिम्मेदार है)

  • NumPy मैट्रिक्स ऑपरेशन रैखिक बीजगणित के सामान्य नियमों का पालन करते हैं

वर्णन करने के लिए कुछ कोड स्निपेट:

>>> from numpy import linalg as LA
>>> import numpy as NP

>>> a1 = NP.matrix("4 3 5; 6 7 8; 1 3 13; 7 21 9")
>>> a1
matrix([[ 4,  3,  5],
        [ 6,  7,  8],
        [ 1,  3, 13],
        [ 7, 21,  9]])

>>> a2 = NP.matrix("7 8 15; 5 3 11; 7 4 9; 6 15 4")
>>> a2
matrix([[ 7,  8, 15],
        [ 5,  3, 11],
        [ 7,  4,  9],
        [ 6, 15,  4]])

>>> a1.shape
(4, 3)

>>> a2.shape
(4, 3)

>>> a2t = a2.T
>>> a2t.shape
(3, 4)

>>> a1 * a2t         # same as NP.dot(a1, a2t) 
matrix([[127,  84,  85,  89],
        [218, 139, 142, 173],
        [226, 157, 136, 103],
        [352, 197, 214, 393]])

लेकिन यह ऑपरेशन विफल हो जाता है अगर इन दो न्यूमपी मैट्रिस को सरणियों में बदल दिया जाता है:

>>> a1 = NP.array(a1)
>>> a2t = NP.array(a2t)

>>> a1 * a2t
Traceback (most recent call last):
   File "<pyshell#277>", line 1, in <module>
   a1 * a2t
   ValueError: operands could not be broadcast together with shapes (4,3) (3,4) 

हालांकि NP.dot सिंटैक्स का उपयोग सरणियों के साथ काम करता है ; यह कार्य मैट्रिक्स गुणा की तरह काम करता है:

>> NP.dot(a1, a2t)
array([[127,  84,  85,  89],
       [218, 139, 142, 173],
       [226, 157, 136, 103],
       [352, 197, 214, 393]])

तो क्या आपको कभी NumPy मैट्रिक्स की आवश्यकता है? यानी, रैखिक बीजगणित संगणना के लिए एक NumPy सरणी पर्याप्त होगी (बशर्ते आपको सही सिंटैक्स पता हो, यानी, NP.dB)?

नियम से प्रतीत होता है कि यदि तर्कों (सरणियों) में आकार (mxn) एक दिए गए रैखिक बीजगणित ऑपरेशन के साथ संगत है, तो आप ठीक हैं, अन्यथा, NumPy फेंकता है।

एकमात्र अपवाद जो मुझे आया है (वहाँ दूसरों की संभावना है) मैट्रिक्स व्युत्क्रम की गणना कर रहा है

नीचे स्निपेट हैं जिसमें मैंने एक शुद्ध रैखिक बीजगणित ऑपरेशन कहा है (वास्तव में, Numpy के रैखिक बीजगणित मॉड्यूल से) और एक NumPy सरणी में पारित किया गया

एक सरणी के निर्धारक :

>>> m = NP.random.randint(0, 10, 16).reshape(4, 4)
>>> m
array([[6, 2, 5, 2],
       [8, 5, 1, 6],
       [5, 9, 7, 5],
       [0, 5, 6, 7]])

>>> type(m)
<type 'numpy.ndarray'>

>>> md = LA.det(m)
>>> md
1772.9999999999995

eigenvectors / eigenvalue जोड़े:

>>> LA.eig(m)
(array([ 19.703+0.j   ,   0.097+4.198j,   0.097-4.198j,   5.103+0.j   ]), 
array([[-0.374+0.j   , -0.091+0.278j, -0.091-0.278j, -0.574+0.j   ],
       [-0.446+0.j   ,  0.671+0.j   ,  0.671+0.j   , -0.084+0.j   ],
       [-0.654+0.j   , -0.239-0.476j, -0.239+0.476j, -0.181+0.j   ],
       [-0.484+0.j   , -0.387+0.178j, -0.387-0.178j,  0.794+0.j   ]]))

मैट्रिक्स मानक :

>>>> LA.norm(m)
22.0227

क्यू कारककरण :

>>> LA.qr(a1)
(array([[ 0.5,  0.5,  0.5],
        [ 0.5,  0.5, -0.5],
        [ 0.5, -0.5,  0.5],
        [ 0.5, -0.5, -0.5]]), 
 array([[ 6.,  6.,  6.],
        [ 0.,  0.,  0.],
        [ 0.,  0.,  0.]]))

मैट्रिक्स रैंक :

>>> m = NP.random.rand(40).reshape(8, 5)
>>> m
array([[ 0.545,  0.459,  0.601,  0.34 ,  0.778],
       [ 0.799,  0.047,  0.699,  0.907,  0.381],
       [ 0.004,  0.136,  0.819,  0.647,  0.892],
       [ 0.062,  0.389,  0.183,  0.289,  0.809],
       [ 0.539,  0.213,  0.805,  0.61 ,  0.677],
       [ 0.269,  0.071,  0.377,  0.25 ,  0.692],
       [ 0.274,  0.206,  0.655,  0.062,  0.229],
       [ 0.397,  0.115,  0.083,  0.19 ,  0.701]])
>>> LA.matrix_rank(m)
5

मैट्रिक्स स्थिति :

>>> a1 = NP.random.randint(1, 10, 12).reshape(4, 3)
>>> LA.cond(a1)
5.7093446189400954

उलटा कोहालांकिएक NumPy मैट्रिक्स की आवश्यकता होती है:

>>> a1 = NP.matrix(a1)
>>> type(a1)
<class 'numpy.matrixlib.defmatrix.matrix'>

>>> a1.I
matrix([[ 0.028,  0.028,  0.028,  0.028],
        [ 0.028,  0.028,  0.028,  0.028],
        [ 0.028,  0.028,  0.028,  0.028]])
>>> a1 = NP.array(a1)
>>> a1.I

Traceback (most recent call last):
   File "<pyshell#230>", line 1, in <module>
   a1.I
   AttributeError: 'numpy.ndarray' object has no attribute 'I'

लेकिन मूर-पेनरोज़ स्यूडोइनवेरस ठीक काम करने लगता है

>>> LA.pinv(m)
matrix([[ 0.314,  0.407, -1.008, -0.553,  0.131,  0.373,  0.217,  0.785],
        [ 1.393,  0.084, -0.605,  1.777, -0.054, -1.658,  0.069, -1.203],
        [-0.042, -0.355,  0.494, -0.729,  0.292,  0.252,  1.079, -0.432],
        [-0.18 ,  1.068,  0.396,  0.895, -0.003, -0.896, -1.115, -0.666],
        [-0.224, -0.479,  0.303, -0.079, -0.066,  0.872, -0.175,  0.901]])

>>> m = NP.array(m)

>>> LA.pinv(m)
array([[ 0.314,  0.407, -1.008, -0.553,  0.131,  0.373,  0.217,  0.785],
       [ 1.393,  0.084, -0.605,  1.777, -0.054, -1.658,  0.069, -1.203],
       [-0.042, -0.355,  0.494, -0.729,  0.292,  0.252,  1.079, -0.432],
       [-0.18 ,  1.068,  0.396,  0.895, -0.003, -0.896, -1.115, -0.666],
       [-0.224, -0.479,  0.303, -0.079, -0.066,  0.872, -0.175,  0.901]])

3
mInv = NP.linalg.inv (m) एक सरणी के व्युत्क्रम की गणना करता है
db1234

यहाँ एक महत्वपूर्ण बात ध्यान देने योग्य है * तत्व-वार गुणन है, डॉट सही मैट्रिक्स गुणन है। कृपया देखें stackoverflow.com/a/18255635/1780570
मिन्ह ट्राइएट

छोटा सा नोट: सरणियों के पक्ष में सुन्न मेट्रिसेस से बचा जाना चाहिए। दस्तावेज़ीकरण से ध्यान दें -> "रैखिक बीजगणित के लिए भी अब इस वर्ग का उपयोग करने की अनुशंसा नहीं की जाती है। इसके बजाय नियमित सरणियों का उपयोग करें। भविष्य में कक्षा को हटाया जा सकता है।" यह भी देखें stackoverflow.com/a/61156350/6043669
उम्मीद है कि

21

3.5 में, पायथन को आखिरकार एक मैट्रिक्स गुणन ऑपरेटर मिल गया । वाक्य-विन्यास है a @ b


2
धन्यवाद! हां, यह देखकर खुशी हुई कि मैं अकेला नहीं हूं जो महसूस करता है कि वर्तमान अंकन अपठनीय है।
elexhobby

15

एक ऐसी स्थिति है जहां डॉट ऑपरेटर ऑपरेटर को मैट्रिसेस से निपटने के साथ-साथ डील करते समय अलग-अलग उत्तर देगा। उदाहरण के लिए, मान लें कि निम्नलिखित हैं:

>>> a=numpy.array([1, 2, 3])
>>> b=numpy.array([1, 2, 3])

उन्हें मेट्रिसेस में बदलें:

>>> am=numpy.mat(a)
>>> bm=numpy.mat(b)

अब, हम दो मामलों के लिए एक अलग आउटपुट देख सकते हैं:

>>> print numpy.dot(a.T, b)
14
>>> print am.T*bm
[[1.  2.  3.]
 [2.  4.  6.]
 [3.  6.  9.]]

विशिष्ट होने के लिए, * तत्व-वार गुणन है, डॉट सही मैट्रिक्स गुणन है। कृपया देखें stackoverflow.com/a/18255635/1780570
मिन्ह ट्राइएट

ऐसा इसलिए है क्योंकि एक संख्यात्मक सरणी के रूप में, aT == a, पारगमन कुछ भी नहीं करता है।
patapouf_ai

यदि आप = np.array ([[1], [2], [3]]) पर लिखते हैं, तो numpy.dot (at, b) आपको समान देना चाहिए। Matix और array के बीच का अंतर डॉट में नहीं है बल्कि ट्रांसपोज़ में है।
patapouf_ai

या वास्तव में, यदि आप एक = numpy.array ([[1,2,3]]) लिखते हैं तो aT वास्तव में स्थानांतरित हो जाएगा और सब कुछ मैट्रिसेस की तरह ही काम करेगा।
patapouf_ai

8

Http://docs.scipy.org/doc/scipy/reference/tutorial/linalg.html से संदर्भ

..., numpy.matrix वर्ग के उपयोग को हतोत्साहित किया जाता है , क्योंकि यह कुछ भी नहीं जोड़ता है जिसे 2D numpy.ndarray ऑब्जेक्ट्स के साथ पूरा नहीं किया जा सकता है , और यह भ्रम हो सकता है कि किस वर्ग का उपयोग किया जा रहा है। उदाहरण के लिए,

>>> import numpy as np
>>> from scipy import linalg
>>> A = np.array([[1,2],[3,4]])
>>> A
    array([[1, 2],
           [3, 4]])
>>> linalg.inv(A)
array([[-2. ,  1. ],
      [ 1.5, -0.5]])
>>> b = np.array([[5,6]]) #2D array
>>> b
array([[5, 6]])
>>> b.T
array([[5],
      [6]])
>>> A*b #not matrix multiplication!
array([[ 5, 12],
      [15, 24]])
>>> A.dot(b.T) #matrix multiplication
array([[17],
      [39]])
>>> b = np.array([5,6]) #1D array
>>> b
array([5, 6])
>>> b.T  #not matrix transpose!
array([5, 6])
>>> A.dot(b)  #does not matter for multiplication
array([17, 39])

scipy.linalg ऑपरेशंस को समान रूप से numpy.matrix या 2D numpy.ndarray ऑब्जेक्ट पर समान रूप से लागू किया जा सकता है ।


7

यह ट्रिक वही हो सकती है जो आप ढूंढ रहे हैं। यह एक तरह का सिंपल ऑपरेटर ओवरलोड है।

फिर आप सुझाए गए इन्फिक्स वर्ग जैसे कुछ का उपयोग कर सकते हैं:

a = np.random.rand(3,4)
b = np.random.rand(4,3)
x = Infix(lambda x,y: np.dot(x,y))
c = a |x| b

5

PEP 465 से एक प्रासंगिक उद्धरण - मैट्रिक्स गुणन के लिए एक समर्पित इन्फिक्स ऑपरेटर , जैसा कि @ पेट-विकटोरिन द्वारा उल्लेख किया गया है, ओपी में हो रही समस्या को स्पष्ट करता है:

[...] अलग-अलग __mul__तरीकों से सुन्न दो अलग-अलग प्रकार प्रदान करता है । के लिए numpy.ndarrayवस्तुओं, *प्रदर्शन elementwise गुणा, और आव्यूह गुणन एक समारोह कॉल का उपयोग करना चाहिए ( numpy.dot)। के लिए numpy.matrixवस्तुओं, *प्रदर्शन गुणा मैट्रिक्स, और elementwise गुणा समारोह वाक्य रचना की आवश्यकता है। राइट्स का उपयोग करके कोड लिखना numpy.ndarrayठीक है। कोड का उपयोग करके लिखना numpy.matrixभी ठीक काम करता है। लेकिन मुसीबत शुरू होती है जैसे ही हम कोड के इन दो टुकड़ों को एक साथ एकीकृत करने का प्रयास करते हैं। कोड जो एक की उम्मीद करता है ndarrayऔर एक matrix, या इसके विपरीत, दुर्घटनाग्रस्त हो सकता है या गलत परिणाम दे सकता है

@इन्फिक्स ऑपरेटर की शुरूआत को अजगर मैट्रिक्स कोड को एकजुट करने और सरल बनाने में मदद करनी चाहिए।


1

फंक्शन मैटमूल (संख्या 1.10.1 के बाद से) दोनों प्रकार के लिए ठीक काम करता है और परिणाम के रूप में एक खस्ता मैट्रिक्स वर्ग:

import numpy as np

A = np.mat('1 2 3; 4 5 6; 7 8 9; 10 11 12')
B = np.array(np.mat('1 1 1 1; 1 1 1 1; 1 1 1 1'))
print (A, type(A))
print (B, type(B))

C = np.matmul(A, B)
print (C, type(C))

आउटपुट:

(matrix([[ 1,  2,  3],
        [ 4,  5,  6],
        [ 7,  8,  9],
        [10, 11, 12]]), <class 'numpy.matrixlib.defmatrix.matrix'>)
(array([[1, 1, 1, 1],
       [1, 1, 1, 1],
       [1, 1, 1, 1]]), <type 'numpy.ndarray'>)
(matrix([[ 6,  6,  6,  6],
        [15, 15, 15, 15],
        [24, 24, 24, 24],
        [33, 33, 33, 33]]), <class 'numpy.matrixlib.defmatrix.matrix'>)

अजगर 3.5 के रूप में जल्दी उल्लेख किया है आप भी @जैसे एक नया मैट्रिक्स गुणन ऑपरेटर का उपयोग कर सकते हैं

C = A @ B

और ऊपर के रूप में एक ही परिणाम मिलता है।

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