NumPy 유니버설 함수 (Universal Functions, ufunc) 알아보기
안녕하세요! 오늘은 "소프트웨어 공장"에서 NumPy의 강력한 기능 중 하나인 유니버설 함수(Universal Functions, 줄여서 ufunc)에 대해 알아보겠습니다. ufunc는 고성능의 벡터화 연산을 제공하며, NumPy 배열에서 매우 빠르고 효율적인 계산을 가능하게 해줍니다. 본 포스팅에서는 ufunc의 개념, 주요 특징, 활용 사례 및 몇 가지 자주 사용하는 ufunc에 대해 예제와 함께 알아보겠습니다.
유니버설 함수란 무엇인가?
유니버설 함수는 NumPy에서 제공하는 함수로, 배열의 각 요소에 대해 반복적인 계산을 수행합니다. 일반적인 Python 루프를 사용하는 것보다 훨씬 빠르게 계산을 수행할 수 있습니다. 이는 NumPy가 내부적으로 C로 구현되어 있으며, 최적화된 벡터 연산을 지원하기 때문입니다.
ufunc는 다음과 같은 특징을 가집니다:
- 벡터화 지원: 반복문 없이도 배열 연산을 수행할 수 있습니다.
- 방대한 함수 제공: 산술 연산, 삼각 함수, 지수 및 로그 함수 등 다양한 함수가 포함되어 있습니다.
- 브로드캐스팅 지원: 크기가 다른 배열 간의 연산을 지원합니다.
- 유연한 입력 및 출력: 다중 입력 및 출력 배열을 지원합니다.
유니버설 함수 사용법
ufunc는 기본적으로 NumPy에서 제공하는 함수로, 배열에 대해 연산을 수행합니다. 아래는 ufunc의 기본적인 사용법입니다:
import numpy as np
# 배열 생성
arr = np.array([1, 2, 3, 4])
# ufunc 사용 예시
result = np.sqrt(arr) # 각 요소에 대해 제곱근 계산
print(result) # [1. 1.41421356 1.73205081 2.]
자주 사용하는 유니버설 함수
1. 산술 연산 함수
NumPy는 기본적인 산술 연산에 대한 ufunc를 제공합니다. 예를 들어, 덧셈, 뺄셈, 곱셈, 나눗셈 등을 수행할 수 있습니다.
# 덧셈
arr1 = np.array([1, 2, 3])
arr2 = np.array([4, 5, 6])
result = np.add(arr1, arr2)
print(result) # [5 7 9]
# 곱셈
result = np.multiply(arr1, arr2)
print(result) # [4 10 18]
2. 삼각 함수
삼각 함수는 과학 계산이나 데이터 분석에서 자주 사용됩니다.
angles = np.array([0, np.pi/2, np.pi])
sin_values = np.sin(angles)
print(sin_values) # [0. 1. 1.2246468e-16]
3. 지수 및 로그 함수
지수와 로그 함수도 NumPy에서 ufunc로 지원됩니다.
values = np.array([1, 2, 3])
# 자연로그
log_values = np.log(values)
print(log_values) # [0. 0.69314718 1.09861229]
# 지수 함수
exp_values = np.exp(values)
print(exp_values) # [ 2.71828183 7.3890561 20.08553692]
4. 비교 함수
배열의 요소를 비교하여 논리 연산을 수행할 수도 있습니다.
arr = np.array([1, 2, 3, 4])
# 비교 연산
result = np.greater(arr, 2)
print(result) # [False False True True]
브로드캐스팅 활용
NumPy ufunc는 브로드캐스팅을 통해 크기가 다른 배열 간의 연산도 지원합니다. 이를 통해 더 유연하게 배열을 다룰 수 있습니다.
# 크기가 다른 배열 연산
arr1 = np.array([1, 2, 3])
arr2 = np.array([[1], [2], [3]])
result = np.add(arr1, arr2)
print(result)
# [[2 3 4]
# [3 4 5]
# [4 5 6]]
커스텀 ufunc 생성
NumPy에서는 np.frompyfunc
를 사용하여 사용자 정의 ufunc를 생성할 수 있습니다. 이를 통해 사용자가 원하는 연산을 손쉽게 벡터화할 수 있습니다.
# 사용자 정의 함수
import numpy as np
def my_func(x, y):
return x ** y
# ufunc 생성
custom_ufunc = np.frompyfunc(my_func, 2, 1)
# 배열 연산
arr1 = np.array([1, 2, 3])
arr2 = np.array([4, 5, 6])
result = custom_ufunc(arr1, arr2)
print(result) # [1 32 729]
유니버설 함수의 성능 비교
ufunc는 일반적인 Python 루프를 사용하는 것보다 훨씬 빠릅니다. 아래는 성능 비교 예제입니다:
import numpy as np
import time
# 큰 배열 생성
arr = np.random.rand(1000000)
# ufunc 사용
start = time.time()
result = np.sqrt(arr)
end = time.time()
print("ufunc 시간:", end - start)
# Python 루프 사용
start = time.time()
result = [x**0.5 for x in arr]
end = time.time()
print("루프 시간:", end - start)
마무리
NumPy의 유니버설 함수는 데이터 분석과 과학 계산에서 매우 중요한 도구입니다. 다양한 함수와 브로드캐스팅 지원 덕분에 복잡한 계산을 간단하게 구현할 수 있습니다. 오늘 소개한 내용을 바탕으로 여러분의 프로젝트에서 NumPy ufunc를 적극적으로 활용해 보세요!
'Python > NumPy' 카테고리의 다른 글
NumPy 배열의 형태 변경: reshape, ravel, flatten (0) | 2025.10.03 |
---|---|
NumPy 배열 브로드캐스팅 (Broadcasting) (0) | 2025.10.01 |
NumPy Array 기본 산술 연산 (0) | 2025.09.30 |
NumPy 슬라이싱 및 배열의 복사와 뷰 (0) | 2025.09.29 |
NumPy 배열의 인덱싱 이해하기 (0) | 2025.09.28 |