기본 데이터 타입과 NumPy
계산 전용 자료 구조: NumPy
NumPy는 데이터 분석, 과학 계산, 머신러닝 분야에서 널리 사용됩니다.
주요 활용 분야:
matplotlib,scipy(최적화),scikit-learn,TensorFlow등과 연동됩니다.특징:
데이터 저장: 동질적 데이터를 연속된 메모리 공간에 저장합니다.
벡터화 연산: 배열 기반 계산으로 빠른 처리 속도를 제공합니다.
정적 데이터: 삽입/삭제보다는 계산에 최적화되어 있습니다.
배열(Array) vs 리스트(List)
| 특징 | 배열(Array) | 리스트(List) |
|—————-|———————————|——————————-|
| 메모리 구조 | 연속적 메모리 할당 | 비연속적 메모리 할당 |
| 데이터 타입 | 동일한 타입만 허용 | 다양한 타입 허용 |
| 연산 속도 | 빠름 (벡터화 연산) | 상대적으로 느림 |
| 삽입/삭제 | 비효율적 | 효율적 |
| 사용 사례 | 대규모 데이터 계산 (빅데이터) | 유연한 데이터 관리 |
NumPy의 주요 모듈 상세 설명
NumPy는 과학 계산과 데이터 분석을 위한 강력한 라이브러리로, 다양한 모듈을 제공합니다. 각 모듈은 특정한 기능을 수행하며, 아래에서 주요 모듈에 대해 더 자세히 설명드리겠습니다.
1. 기본 연산: numpy.core
- 역할: NumPy의 핵심 데이터 구조와 기본 연산을 제공합니다.
- 주요 기능:
- 배열(Array) 생성 및 관리:
np.array(),np.zeros(),np.ones()등. - 기본 연산: 덧셈, 뺄셈, 곱셈, 나눗셈 등 배열 간의 산술 연산.
- 브로드캐스팅(Broadcasting): 서로 다른 크기의 배열 간 연산을 지원.
- 인덱싱 및 슬라이싱: 배열의 특정 요소에 접근하거나 부분 배열을 추출.
- 배열(Array) 생성 및 관리:
- 예시:
import numpy as np a = np.array([1, 2, 3]) b = np.array([4, 5, 6]) print(a + b) # [5, 7, 9]
2. 선형대수: numpy.linalg
- 역할: 행렬 연산 및 선형대수 관련 기능을 제공합니다.
- 주요 기능:
- 행렬 곱셈:
np.dot(),@연산자. - 역행렬 계산:
np.linalg.inv(). - 고유값 및 고유벡터 계산:
np.linalg.eig(). - 특이값 분해(SVD):
np.linalg.svd(). - 행렬식 계산:
np.linalg.det().
- 행렬 곱셈:
- 예시:
A = np.array([[1, 2], [3, 4]]) inv_A = np.linalg.inv(A) # 역행렬 계산 print(inv_A)
3. 확률 및 난수: numpy.random
- 역할: 난수 생성 및 확률 분포 관련 기능을 제공합니다.
- 주요 기능:
- 난수 생성:
np.random.rand(),np.random.randint(). - 확률 분포: 정규 분포(
np.random.normal()), 균등 분포(np.random.uniform()). - 시드 설정:
np.random.seed()로 난수 생성기의 초기값 설정.
- 난수 생성:
- 예시:
np.random.seed(42) random_numbers = np.random.normal(0, 1, 10) # 평균 0, 표준편차 1인 정규 분포 print(random_numbers)
4. 신호 처리: numpy.fft
- 역할: 푸리에 변환(Fourier Transform)을 통해 신호 처리 기능을 제공합니다.
- 주요 기능:
- 고속 푸리에 변환(FFT):
np.fft.fft(). - 역 푸리에 변환:
np.fft.ifft(). - 주파수 분석: 신호의 주파수 성분을 분석.
- 고속 푸리에 변환(FFT):
- 예시:
signal = np.array([0, 1, 0, -1]) fft_result = np.fft.fft(signal) # 푸리에 변환 print(fft_result)
5. 다항식 연산: numpy.polynomial
- 역할: 다항식 계산 및 관련 연산을 지원합니다.
- 주요 기능:
- 다항식 생성:
np.poly1d(). - 근 찾기:
np.roots(). - 다항식 적합:
np.polyfit().
- 다항식 생성:
- 예시:
coefficients = [1, -3, 2] # x^2 - 3x + 2 roots = np.roots(coefficients) # 근 계산 print(roots) # [2., 1.]
6. 테스트 및 디버깅: numpy.testing
- 역할: NumPy 코드의 테스트 및 디버깅을 위한 도구를 제공합니다.
- 주요 기능:
- 배열 비교:
np.testing.assert_array_equal(). - 근사값 비교:
np.testing.assert_almost_equal(). - 예외 테스트:
np.testing.assert_raises().
- 배열 비교:
- 예시:
a = np.array([1, 2, 3]) b = np.array([1, 2, 3]) np.testing.assert_array_equal(a, b) # 두 배열이 동일한지 확인
7. 마스킹 처리: numpy.ma
- 역할: 결측값(Missing Value)을 마스킹하여 처리하는 기능을 제공합니다.
- 주요 기능:
- 마스크 배열 생성:
np.ma.masked_array(). - 결측값 처리:
np.ma.masked_where(). - 통계 계산: 마스크된 값을 무시하고 통계 계산.
- 마스크 배열 생성:
- 예시:
data = np.array([1, 2, -999, 4]) # -999는 결측값 masked_data = np.ma.masked_where(data == -999, data) print(masked_data.mean()) # 결측값을 제외한 평균 계산
8. Ufunc (Universal Function)
- 역할: 배열의 각 요소에 대해 빠르게 연산을 수행하는 범용 함수입니다.
- 주요 기능:
- 벡터화 연산:
np.add(),np.subtract(),np.multiply()등. - 사용자 정의 Ufunc:
np.frompyfunc()로 생성 가능.
- 벡터화 연산:
- 특징:
- 브로드�스팅 지원: 서로 다른 크기의 배열 간 연산 가능.
- C로 구현: 빠른 속도로 동작.
- 예시:
a = np.array([1, 2, 3]) b = np.array([4, 5, 6]) result = np.add(a, b) # [5, 7, 9] print(result)
결론
NumPy는 다양한 모듈을 통해 과학 계산, 데이터 분석, 머신러닝 등 다양한 분야에서 활용됩니다. 각 모듈은 특정한 기능을 제공하며, 이를 조합하여 복잡한 문제를 효율적으로 해결할 수 있습니다.
NumPy 데이터 타입
기본 타입
| 타입 | 설명 | 예시 |
|—————-|————————————–|———————–|
| Boolean | 참/거짓 값 | bool |
| 정수형 | 부호 있는 정수 | int8, int32, int |
| Unsigned | 부호 없는 정수 (0 이상) | uint8, uint32 |
| 실수형 | 부동소수점 | float32, float64 |
| 복소수 | 복소수 (실수부 + 허수부) | complex64, complex128 |
| 문자열 | 문자열 또는 유니코드 | str, unicode |
| 객체 | 파이썬 객체 참조 | object |
| 레코드 | 여러 필드를 묶은 구조체 형태 | void |
복사 방식
약식 복사 (Shallow Copy):
원본과 동일한 메모리 주소를 참조합니다.
예:
b = a(NumPy 배열은 기본적으로 약식 복사)깊은 복사 (Deep Copy):
원본 데이터를 완전히 복제하여 새 메모리에 저장합니다.
예:
np.copy()사용
선형대수와 딥러닝
행렬곱 (내적): 차원 축소 또는 확장에 사용됩니다.
딥러닝: 중간층에서 행렬 연산을 반복하여 특징을 추출합니다.
(예: TensorFlow, PyTorch)
참고 사항
CPU vs GPU:
CPU: 범용 계산에 적합합니다.
GPU: 병렬 처리로 고속 연산이 가능합니다 (딥러닝에 필수).
R vs NumPy:
R은 원본 데이터 유지를 중시하지만, NumPy는 메모리 효율을 우선시합니다.
예문
단위 행렬 생성
print(np.eye(5)) # 단위 행렬 (정사각 행렬)
np.identity(5) # identity 함수 사용 가능
다차원 배열 속성 정보
arr = np.array([[1,2,3], [4,5,6]])
print(arr.ndim) # 차원 (2D)
print(arr.shape) # 행렬 차수 (2,3)
print(len(arr)) # 행 개수 (2)
print(arr.size) # 전체 요소 개수 (6)
print(arr.dtype) # 데이터 타입 (int64)
행렬 데이터 저장 방식 (행우선 vs. 열우선)
first = np.ndarray(shape=(2,2), dtype=float, order='F') # Fortran 방식 (열우선)
first.fill(10)
print(first)
배열 생성 및 변형
배열 생성
print(np.arange(10)) # [0,1,2,3,4,5,6,7,8,9]
다차원 배열 변환
array = np.arange(10).reshape(5, 2) # (5,2) 형태로 변경
print(array)
모든 원소가 1인 배열 생성
b = np.ones_like(array, float) # 원래 배열 크기 유지
print(b)
3차원 배열 생성 및 변형
e = np.arange(24).reshape(2,3,4)
print(e)
print(e.flatten()) # 1차원으로 변환
print(e.strides) # 메모리 상 데이터 배치 확인
배열 속성 및 데이터 타입
배열 속성 확인
a = np.arange(10)
print(type(a)) # <class 'numpy.ndarray'>
print(a.dtype) # int64
print(a.shape) # (10,)
print(a.ndim) # 1차원
print(a.dtype.itemsize) # 요소 하나의 크기 (8바이트)
print(a.size) # 요소 개수 (10)
print(a.dtype.itemsize * a.size) # 전체 메모리 공간 (80바이트)
리스트 ↔ ndarray 변환
nda = np.array([[1,2], [3,4]]) # list -> ndarray
print(nda.tolist()) # ndarray -> list
배열 연산
요소 연산 (덧셈, 곱셈 등)
a = np.array([[1,2],[3,4]])
print(a + a) # 요소별 덧셈
print(a * a) # 요소별 곱셈
행렬 곱 연산 (dot product)
b = np.array([[4,3,4],[2,1,5]])
print(a.dot(b)) # 2x2 * 2x3 => 2x3 행렬 결과
브로드캐스팅 (Broadcasting)
a = np.array([[0,0,0],[10,10,10],[20,20,20],[30,30,30]])
b = np.array([1,2,3])
print(a + b) # 자동 확장 후 연산 수행
인덱싱 및 슬라이싱
2D 배열 인덱싱
arr2d = np.arange(1,10).reshape(3,3)
print(arr2d[0,2]) # 첫 번째 행, 세 번째 열 요소
print(arr2d[:2,1:]) # 0,1행 선택, 1열부터 끝까지
3D 배열 인덱싱
arr3d = np.arange(1,13).reshape(2,2,3)
print(arr3d[0,0,0]) # 첫 번째 면, 첫 번째 행, 첫 번째 열 요소
Boolean 인덱싱
names = np.array(['Seoul', 'Daejun', 'Chungju','Seoul', 'Chungju', 'Daejun', 'Daejun'])
data = np.random.randn(7,4)
print(data[names == 'Seoul']) # 'Seoul'에 해당하는 행만 선택
# 문제 : 다음 데이터에 대하여 두개가 다 참이면 0, cond1 참이면 1, cond2 참이면 2 그외 3
cond1 = np.array([1,0,1,1,0,0,1], dtype=bool)
cond2 = np.array([0,1,1,0,0,1,1], dtype=bool)
result = np.where(cond1 & cond2, 0, np.where(cond1, 1, np.where(cond2, 2, 3)))
print("3항 연산자 ", result)
result = 1*(cond1 & ~cond2) + 2*(cond2 & ~cond1) + 3*~(cond1 | cond2)
print("수식을 이용한 ", result)
수학 연산 및 삼각함수
기본 연산
x = np.array([1,2,3])
print(np.exp(x)) # e^x
print(np.exp2(x)) # 2^x
print(np.log(x)) # 자연로그 ln(x)
삼각 함수
theta = np.linspace(0, np.pi, 3)
print(np.sin(theta))
print(np.cos(theta))
print(np.tan(theta))
선형대수 (Linear Algebra)
최소제곱법 (Least Square)
x = np.array([0,1,2,3])
y = np.array([-1,0.2,0.9,2.1])
A = np.vstack([x, np.ones(len(x))]).T
m, c = np.linalg.lstsq(A, y, rcond=None)[0] # 선형 회귀
print(m, c) # 기울기와 절편
시각화 (Matplotlib)
산점도 (Scatter Plot)
import matplotlib.pyplot as plt
X = np.random.rand(10,2)
plt.scatter(X[:,0], X[:,1], s=50)
plt.show()
함수 그래프 그리기
def my_func(x):
return 3*x**3 + 2*x**2 + x + 1
x = np.linspace(-3,3)
y = my_func(x)
plt.plot(x, y, 'bo') # 파란 점 그래프
plt.xlabel('x')
plt.ylabel('y')
plt.grid()
plt.show()
성능 비교 (반복문 vs 벡터 연산)
%%time
# magic command
# 속도차
a = np.arange(1000000)
result = 0
for v in a:
result += v
print("반복문을 이용한 결과 : ", result)
벡터화 연산 (빠름)
%%time
result = np.sum(a) # 벡터화 연산
print("벡터화 연산을 이용한 결과 :", result)
벡터화 연산이 반복문보다 훨씬 빠름!