Programing

NumPy Matrix와 Array 클래스의 곱셈은 어떻게 다릅니 까?

lottogame 2020. 7. 2. 07:48
반응형

NumPy Matrix와 Array 클래스의 곱셈은 어떻게 다릅니 까?


numpy 문서는 행렬 작업을 위해 행렬 대신 배열을 사용하는 것이 좋습니다. 그러나 최근까지 사용했던 옥타브와 달리 *는 행렬 곱셈을 수행하지 않으므로 matrixmultipy () 함수를 사용해야합니다. 이것이 코드를 읽을 수 없게 만든다고 생각합니다.

아무도 내 의견을 공유하고 해결책을 찾았습니까?


matrix클래스 사용을 피하는 주된 이유 는 a) 본질적으로 2 차원이며 b) "정상적인"numpy 배열에 비해 추가 오버 헤드가 있기 때문입니다. 당신이하고있는 모든 일이 선형 대수학이라면, 반드시 매트릭스 클래스를 자유롭게 사용하십시오 ... 개인적으로 나는 그것이 가치보다 더 많은 문제를 발견합니다.

배열의 경우 (Python 3.5 이전) dot대신을 사용하십시오 matrixmultiply.

예 :

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

print np.dot(x,y)

또는 최신 버전의 numpy에서는 간단히 x.dot(y)

개인적으로 나는 *행렬 곱셈을 암시 하는 연산자 보다 훨씬 더 읽기 쉽습니다 ...

Python 3.5의 배열에는을 사용하십시오 x @ y.


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]])

그러나이 두 NumPy 행렬이 배열로 변환되면이 작업이 실패합니다.

>>> 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.dot의 올바른 구문을 알고 있다면)?

규칙 (배열)이 주어진 선형 대수 연산과 호환되는 모양 (mxn)을 가지고 있다면 괜찮습니다. 그렇지 않으면 NumPy가 발생합니다.

내가 겪은 유일한 예외 (다른 것들이있을 수 있음)는 행렬 inverse를 계산 하는 것 입니다.

아래는 내가 순수 선형 대수 연산 (실제로 Numpy의 Linear Algebra 모듈에서)을 호출하고 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

고유 벡터 / 고유 값 쌍 :

>>> 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

qr 인수 분해 :

>>> 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'

그러나 Moore-Penrose pseudoinverse 는 잘 작동하는 것 같습니다.

>>> 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.5에서 파이썬은 마침내 행렬 곱셈 연산자를 얻었습니다 . 구문은 a @ b입니다.


도트 연산자가 배열을 다룰 때 행렬을 다룰 때와는 다른 대답을하는 상황이 있습니다. 예를 들어, 다음을 가정하십시오.

>>> 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.]]

http://docs.scipy.org/doc/scipy/reference/tutorial/linalg.html 에서 참조

..., the use of the numpy.matrix class is discouraged, since it adds nothing that cannot be accomplished with 2D numpy.ndarray objects, and may lead to a confusion of which class is being used. For example,

>>> 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 operations can be applied equally to numpy.matrix or to 2D numpy.ndarray objects.


This trick could be what you are looking for. It is a kind of simple operator overload.

You can then use something like the suggested Infix class like this:

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

A pertinent quote from PEP 465 - A dedicated infix operator for matrix multiplication , as mentioned by @petr-viktorin, clarifies the problem the OP was getting at:

[...] numpy provides two different types with different __mul__ methods. For numpy.ndarray objects, * performs elementwise multiplication, and matrix multiplication must use a function call (numpy.dot). For numpy.matrix objects, * performs matrix multiplication, and elementwise multiplication requires function syntax. Writing code using numpy.ndarray works fine. Writing code using numpy.matrix also works fine. But trouble begins as soon as we try to integrate these two pieces of code together. Code that expects an ndarray and gets a matrix, or vice-versa, may crash or return incorrect results

The introduction of the @ infix operator should help to unify and simplify python matrix code.


Function matmul (since numpy 1.10.1) works fine for both types and return result as a numpy matrix class:

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))

Output:

(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'>)

Since python 3.5 as mentioned early you also can use a new matrix multiplication operator @ like

C = A @ B

and get the same result as above.

참고URL : https://stackoverflow.com/questions/3890621/how-does-multiplication-differ-for-numpy-matrix-vs-array-classes

반응형