Post

기본 데이터 타입과 NumPy

기본 데이터 타입과 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): 서로 다른 크기의 배열 간 연산을 지원.
    • 인덱싱 및 슬라이싱: 배열의 특정 요소에 접근하거나 부분 배열을 추출.
  • 예시:
    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().
    • 주파수 분석: 신호의 주파수 성분을 분석.
  • 예시:
    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)

벡터화 연산이 반복문보다 훨씬 빠름!

This post is licensed under CC BY 4.0 by the author.