Universal functions (ufunc) — NumPy v1.15 Manual

Universal functions (ufunc) A universal function (or ufunc for short) is a function that operates on ndarrays in an element-by-element fashion, supporting array broadcasting, type casting, and several other standard features. That is, a ufunc is a “vecto

numpy.org

Numpy에는 Universal function 기능을 제공한다. Numpy의 특별한 구조인 ndarray의 각 요소별로 연산하는 함수로 Braodcasting, type casting 등의 몇 가지 기능들을 제공하며 연산을 빠르게 수행하는 것을 주목적으로 한다.

# 루프와 유니버설 함수의 속도 비교
arr_1 = np.random.randint(1, 10, size = 10 ** 8)
arr_2 = np.random.randint(1, 10, size = 10 ** 8)

import time
### 리스트를 사용하여 벡터의 덧셈 구현
t1 = time.time()
output = []
for val1, val2 in zip(arr_1, arr_2):
    output.append(val1 + val2)
t2 = time.time()
print("반복문을 사용한 경우:", round(t2 - t1, 4))

### 유니버설 함수를 사용하여 벡터의 덧셈 구현
t1 = time.time()
output = arr_1 + arr_2
t2 = time.time()
print("유니버설 함수를 사용한 경우:", round(t2 - t1, 4))

ndarray로 구성된 각각의 요소들을 모두 하나씩 더했을 때보다 ndarray의 유니버설 함수 기능을 사용했을 때 훨씬 빠르게 계산할 수 있음을 알 수 있다. 따라서 지금보다 더 많은 수의 데이터를 처리할 때는 리스트보다 ndarray를 사용하는 것이 더 효율적일 것이다.

 

Broadcasting, 브로드캐스팅

유니버설 함수를 이용한 ndarray 배열 계산이 특별한 이유 중 하나는 바로 이 브로드캐스팅 기능 때문이다. 브로드캐스팅이란, 서로 다른 크기의 배열에 유니버설 함수를 적용하는 규칙 집합으로, 큰 차원의 배열에 맞게 작은 배열이 확장되는 방식이다.

1. (3, )의 크기를 가지는 배열과 연산하기 위해 (1, )의 크기를 가지는 배열이 (3, )으로 확장되었다.
2. (3, 3)의 크기를 가지는 배열과 연산하기 위해 (3, 1)의 크기를 가지는 배열이 (3, 3)으로 확장되었다.
3. (1, 3)의 크기를 가지는 배열과 (3, 1)의 크기를 가지는 배열을 연산하기 위해 (1, 3)에서는 행의 크기가 3으로, (3, 1)에서는 열의 크기가 3으로 확장되었다.

다만 일반적으로 1, 2번의 방법으로 Broadcasting을 자주 사용한다. 즉 하나의 차원만 크기가 1인 경우에 주로 사용된다. 2차원 ndarray에서 더하고자 하는 배열의 행과 열의 크기가 모두 2를 넘기게 되면 broadcasting 규칙이 복잡해지기 때문이다. (numpy 공식 문서의 예제에서도 차원의 크기가 1인 배열로 줄일 것을 권장하고 있다.)

# 브로드캐스팅
print("np.arange(3) + 5:",np.arange(3) + 5, '\n')
print("np.ones((3, 3)) + np.arange(3)\n",np.ones((3, 3)) + np.arange(3),'\n')
print("np.arange(3).reshape(3, 1) + np.arange(3)\n",np.arange(3).reshape(3, 1) + np.arange(3))

# 브로드캐스팅 사용 예시 : 표준화
X = np.random.random((10, 3))
Xmean = X.mean(axis=0) # 열 별 평균 : (1, 3)
Xstd = X.std(axis=0) # 열 별 표준편차 : (1, 3)

# ((10, 3) - (1, 3)) / (1, 3)
Z = (X - Xmean) / Xstd

print("X:\n", X, "\n")
print("X mean:\n", X, "\n")
print("X std:\n", X, "\n")
print("Z:\n", X, "\n")

 

비교 연산자

numpy에서는 리스트와는 달리 독특한 연산이 하나 더 있는데, 바로 비교 연산자를 이용해 부울 리스트를 생성하는 것이다. 리스트의 경우 리스트와 상수의 비교는 type이 다르기 때문에 불가능하지만, ndarray와 상수를 비교하면 ndarray와 같은 크기의 bool type의 ndarray를 생성한다.

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

이렇게 bool type의 ndarray를 만들면 indexing을 할 때 이용할 수 있다. 따라서 비교 연산자의 결과를 바탕으로 조건에 맞는 요소를 탐색할 수 있다.

L = np.array([1, 2, 3, 4, 5])
condition = L >= 3 # condition은 비교 연산자를 통해 만들어진 bool type의 ndarray
print(L[condition]) # 마스킹 검색

728x90
반응형
  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 라이프코리아트위터 공유하기
  • shared
  • 카카오스토리 공유하기