NumPy Matrix 대 Array 클래스의 곱셈은 어떻게 다릅니까?
numpy 문서에서는 행렬 대신 배열을 사용하여 작업할 것을 권장합니다.그러나 *는 옥타브(최근까지 사용했던)와 달리 행렬 곱셈을 수행하지 않으므로 함수 행렬 곱셈()을 사용해야 합니다.코드를 읽을 수 없게 만드는 것 같습니다.
제 의견을 공유하고 해결책을 찾은 사람이 있습니까?
사용을 피하는 주된 이유는matrix
클래스는 a) 본질적으로 2차원이며, b) "정상적인" 눔피 배열에 비해 추가적인 오버헤드가 있다는 것입니다.지금 하는 일이 선형대수학뿐이라면, 어쨌든, 행렬 클래스를 자유롭게 사용하세요...하지만 개인적으로 저는 그것이 가치있는 것보다 더 큰 문제라고 생각합니다.
어레이(Python 3.5 이전)의 경우 다음 대신 사용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만 알면)
규칙은 인수(배열)가 주어진 선형 대수 연산과 호환되는 모양(m x n)을 가지면 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
고유 벡터/eigen 값 쌍:
>>> 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'
하지만 무어와 펜로즈 사이비 역은 잘 작동하는 것 같습니다
>>> 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 의 참조
..., 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 객체에 동일하게 적용할 수 있습니다.
이 속임수가 당신이 찾고 있는 것일 수도 있습니다.이것은 일종의 단순한 연산자 과부하입니다.
그런 다음 제안된 Infix 클래스와 같은 것을 다음과 같이 사용할 수 있습니다.
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
@petr-viktorin이 언급한 매트릭스 곱셈을 위한 전용 infix 연산자인 PEP 465의 관련 인용문은 OP가 얻고 있던 문제점을 다음과 같이 설명합니다.
[...] numpy는 서로 다른 두 가지 유형을 제공합니다.
__mul__
methods. for.numpy.ndarray
물건들,*
요소별 곱셈을 수행하고 행렬 곱셈은 함수 호출을 사용해야 합니다 (numpy.dot
의 경우.numpy.matrix
물건들,*
행렬 곱셈을 수행하고 요소별 곱셈에는 함수 구문이 필요합니다.를 이용하여 코드를 작성하는 중numpy.ndarray
잘 통합니다.를 이용하여 코드를 작성하는 중numpy.matrix
또한 잘 작동합니다.그러나 문제는 이 두 가지 코드를 통합하려는 순간 시작됩니다.코드는 다음과 같이 예상됩니다.ndarray
그리고 a를 받습니다.matrix
, 또는 그 반대의 versa이 충돌하거나 잘못된 결과를 반환할 수 있습니다.
도입부.@
infix 연산자는 python matrix code를 통일하고 단순화하는 데 도움이 되어야 합니다.
함수 매트물(numpy 1.10.1 이후)은 numpy 행렬 클래스로 두 가지 유형과 반환 결과 모두에 대해 정상적으로 작동합니다.
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'>)
앞서 언급한 python 3.5 이후로 당신은 다음과 같은 새로운 행렬 곱셈 연산자를 사용할 수 있습니다.
C = A @ B
위와 같은 결과를 얻을 수 있습니다.
언급URL : https://stackoverflow.com/questions/3890621/how-does-multiplication-differ-for-numpy-matrix-vs-array-classes
'it-source' 카테고리의 다른 글
MySQL 업데이트 열 +1? (0) | 2023.11.07 |
---|---|
Drietrine QueryBuilder의 식 mysql NOW() (0) | 2023.11.07 |
C에서 ASCII 문자를 int로 변환하는 방법 (0) | 2023.11.07 |
MySQL 오류:UPDATE 및 LIMIT의 잘못된 사용 (0) | 2023.11.07 |
Magento에서 getChildHtml 이해 (0) | 2023.11.07 |