넘파이의 ndarray 객체는 리스트와 달리 브로드캐스트(broadcast)라 불리는 특성이 있는데 이는 리스트(list)객체와 확연히 구별이 되는 기능이다. 예를 들어서 다음과 같이 숫자로만 이루어진 중첩 리스트 la 를 고려해 보자.


-----------------------------------------------------------------------

>>> la = [ [1,2], [3,4] ]

-----------------------------------------------------------------------


이 리스트는 요소가 모두 숫자이지만 la+2, la/4 와 같은 연산은 지원하지 않는다. 모든 요소에 2를 더하려면 for 반복문을 사용해야만 한다. 그리고 la*2는 파이썬 문법상 전혀 다른 동작을 수행한다. 즉, 리스트 사이의 사칙연산은 수학 연산과는 전혀 관계가 없는 것이다.


  이에 반해서 ndarray는 요소간 연산이 기본적으로 가능하며 같은 크기의 객체간 산술연산은 요소끼리 행해져서 그 결과가 산출된다. 예를 들어서 다음과 같은 두 개의 ndarray 를 고려하자.


-----------------------------------------------------------------------

>>> a = np.array( la )

>>> b = np.array([[1j,2j],[3j,4j]])

-----------------------------------------------------------------------


이렇게 생성된 a와 b에 대해서는 a+1, a*3, a-b 와 같은 사칙 연산이 정의되며 각각의 요소에 대해서 연산이 수행된다. 배열간 곱셈의 경우는 행렬곱셈과는 상관이 없는 연산이므로 이것과 헷갈리면 안된다. 여기서의 곱셈은 요소간 곱셈이다. 이러한 ndarray 의 기능을 broadcast라고 한다.


  그럼 크기가 다른 객체간 연산은 어떨까? 먼저 한 쪽이 배열이고 다른 쪽이 스칼라라면 그 스칼라는 다른 배열의 크기로 확장된 후 각각의 요소에 더해진다.


-----------------------------------------------------------------------

>>> np.arange(5) + 2 # [0, 1, 2, 3, 4] + [2, 2, 2, 2, 2] 와 같다

array([2, 3, 4, 5, 6])

-----------------------------------------------------------------------


이 예를 보면 1x5 크기의 배열과 2라는 스칼라의 합이다. 2라는 스칼라는 모든 요소가 2인 1x5의 배열로 확장된 후 각 요소간 더해진다. 행렬의 경우도 마찬가지이다.


-----------------------------------------------------------------------

>>> a=np.arange(1,10).reshape(3,3) # [0,1,2, ... ,9] 배열은 3x3로 재배열한다.

>>> a**2

array([[ 1, 4, 9],

[16, 25, 36],

[49, 64, 81]])

-----------------------------------------------------------------------


크기가 다른 행렬 간에는 산술연산이 일반적으로 불가하다. 즉, 다음과 같은 행렬 a, b 간의 산술연산은 불가능하다.


-----------------------------------------------------------------------

>>> a=np.arange(1,10).reshape(3,3)

>>> b=np.array([[1,2],[3,4]])

>>> a+b # 에러 발생

-----------------------------------------------------------------------


하지만 가능한 경우가 있으니 다음의 세 가지 경우이다.


  • mxn 행렬과 mx1 벡터 간의 연산
  • m x n 행렬과 1xn 벡터 간의 연산
  • 또한 mx1 벡터와 1xn 벡터간의 연산.


이 세가지 경우는 한 쪽의 크기가 다른 쪽의 크기로 확장된 후 요소간 연산을 수행하게 된다. (다음 그림 참조)


[#00083]

Posted by 살레시오

댓글을 달아 주세요

  1. 자나깨나 2017.09.20 00:49  댓글주소  수정/삭제  댓글쓰기

    감사합니다 ㅠㅠ C++로 행렬클래스 구현하는데 도움이 많이 됐어요!