numpy에는 배열(ndarray)과 행렬(matrix) 객체가 있는데 이들 중 어느 것을 사용해야 하는지 처음 공부할 때 혼동하기 쉽다. 언뜻 보기에는 사용법에 별 차이가 없어 보이고 행렬 연산에는 무조건 matrix를 사용해야 하는 것 아닌가 짐작했었는데 다음 사이트에 잘 정리가 되어 있어서 여기에 옮겨보도록 하겠다.
1. 결론 요약
일단 결론부터 말하자면 ndarray 를 사용하는 것이 더 효율적이라고 명시되어 있다. 개인적으로 matrix 객체는 MATLAB 사용자의 편의를 위해서 (억지로) 만들어진 것 같은 느낌이 든다. (pylab 과 같은 모듈도 비슷한 이유로 만들어졌으나 파이썬 커뮤니티 안에서는 사용이 역시 권장되지 않는다.)
ndarray를 사용해야 하는 이유는 다음과 같이 요약할 수 있다.
- ndarray는 numpy에서 지원하는 표준형인 벡터/행렬/텐서 를 저장한다.
- 많은 numpy 함수가 matrix가 아니라 ndarray를 반환한다.
- 요소 간 연산과 선형대수 연산에 대해선 명확히 구분되어 있다.
- 표준 벡터나 열벡터/행벡터를 표현할 수 있다.
ndarray를 사용할 경우의 한 가지 단점은 행렬의 곱셈을 수행할 때 ,dot() method를 사용해야한다는 점이다. 즉, ndarray 객체 A와 B를 행렬곱하려면 A.dot(B) 와 같이 수행해야 하며 A*B는 요소간 곱셈이 된다. 반면 matrix객체 A와 B는 단순히 A*B로 행렬곱이 수행된다.
2. 좀 더 자세한 설명
numpy는 ndarray 와 matrix 둘 다 포함한다. ndarray는 다양한 종류의 수치 연산을 위해서 고안된 범용 n차 배열이다. 반면 matrix는 선형 대수 연산을 위해서 특별히 고안된 객체이다. 실용적인 관점에서 둘 사이의 차이점은 몇 가지 안된다.
- 연산자 *, dot() 그리고 multiply()
- ndarray 는 '*'는 요소간 곱셈이다. 행렬곱을 할때는 obj.dot() 메쏘드를 사용해야 한다.
- 반면 matrix는 '*'이 행렬곱이다. 그리고 numpy.multiply() 함수가 요소간 곱이다.
- 벡터와 1차 배열
- ndarray 는 벡터 1xN, Nx1, 그리고 N크기의 1차원 배열이 모두 각각 다르다. obj[:,1] 는 크기가 n인 1차 배열을 반환한다. 그리고 1차원 배열의 전치는 작동하지 않는다. (역자 주 : ndarray로 벡터를 표현할 때는 반드시 2차 배열을 이용해야 한다.)
- 반면 matrix 객체에서 1차 배열은 모두 1xn, 혹은 nx1 행렬(2차원 배열)로 상향 변환된다. ( matrix 객체는 내부적으로 항상 2차원 배열이다. )
- ndarray는 고차원 배열이 가능하지만 matrix는 항상 2차원 배열 이다.
- 편리한 attribute
- ndarray 는 전치를 해주는 a.T attribute 가 있다.
- matrix 도 m.H, m.I, m.A attribute들이 있으며 각각 복소전치, 역행렬, ndarray로의 변환이다.
- 편리한 생성자
- ndarray는 중첩된 리스트로 다차원 배열을 생성한다. 예) array( [ [1,2,3].[4,5,6] ] )
- matrix는 MATLAB 의 문법을 지원한다. 예) matrix('[1 2 3; 4 5 6]')
좀 더 부가 설명을 하자면 ndarray를 이용하여 벡터(vector)를 표현할 때는 2차 배열로 정의해야 한다. 즉, 다음 세 가지는 모두 다르며 이 중 벡터는 두 번째와 세 번째 같이 생성해야 한다. (혼동하기 참 쉽다.)
a1 = np.array( [1, 2, 3] ) #크기 (3,)인 1차원 배열a2 = np.array( [ [1, 2, 3] ] ) #크기 (1,3)인 2차원 배열 (행벡터)a3 = np.array( [ [1], [2], [3] ] ) #크기 (3,1)인 2차원 배열 (열벡터) |
여기서 a1.T 는 동작하지 않는다. 반면 a2.T 와 a3.T는 동작한다. 1차 배열은 행벡터나 열벡터 두 가지 모두로 취급되기도 한다.
ndarray 객체를 사용하는데 있어서 장점과 단점은 다음과 같다.
- 장점
- 1차 배열은 행벡터나 열벡터 둘 다로 취급할 수 있다. dot(A,v) 에서 v는 열벡터로 다루어지고 dot(v,A)에서는 행벡터로 취급된다. 따라서 전치를 복잡하게 수행할 필요가 없다.
- 요소 간 곱셈이 쉽다 (예: A*B) 사실 모든 산술 연산 (+ - * / ** 등등)이 요소 간 연산이다.
- ndarray 는 numpy 의 가장 기본 객체이므로 연산의 속도, 효율성 그리고 numpy를 이용하는 외부 라이브러리의 반환형이 이것일 가능성이 높다.
- 다차원 배열을 쉽게 구현한다.
- tensor algebra 에 대한 장점이 있다.(?)
- 단점
- 행렬간 곱에 obj.dot() 멤버함수를 사용해야 하므로 번잡할 수 있다. 세 행렬 A, B, C의 행렬곱은 dot( dot(A,B),C) 이다
matrix 객체를 사용하는 데 있어서 장점과 단점은 다음과 같다.
- 장점
- MATLAB 행렬과 비슷하게 동작한다.
- 행렬곱이 A*B 와 같이 '*' 연산자이므로 선형대수 연산이 좀 더 편하다.
- 단점
- matrix 의 차수는 항상 2이다. 벡터도 2차 배열로 저장된다. 3차 행렬을 구현하려면 ndarray를 이용하던가 matrix객체를 요소로 갖는 리스트(list)로 구현해야 한다.
- ndarray 가 numpy의 표준 객체이기 때문에 어떤 함수는 인수로 matrix를 주어도 반환 객체는 ndarray 이기도 하다. numpy 에 포함된 함수는 절대 그렇지 않지만 제3자 라이브러리는 그럴 수 있다.
- 요소간 곱은 multiply(A,B)함수를 이용해야 한다.
- *은 행렬곱인데 반해 /는 요소간 연산이다. 즉, 연산자 오버로딩에 일관성이 결여되어 있다.
개인적으로는 numpy를 사용하기로 결정되었다면 matlab에서의 개념은 모두 버리고 numpy에서 제공하는 객체에 빨리 익숙해져야한다는 의견이다. 그래서 matrix객체나 pylab 모듈을 사용하는 것이 권장되지 않는 것이다.
댓글 없음:
댓글 쓰기