NumPy
‘Numerical Python’의 줄임말로, 복잡한 수학 계산 작업에 유용한 파이썬 라이브러리이다.

pip install numpy     # 터미널에서 NumPy 설치
import numpy as np    # 관례적으로 `np`라는 이름으로 임포트


💡 Ndarray = 균일n차원 배열 객체

  • 균일하다: 배열의 모든 데이터가 같은 데이터 유형
  • n차원: 모든 차원
    • 1차원: 하나의 열(Vector)
    • 2차원: 행렬(Matrix)
    • n차원: 서로 겹쳐진 행렬(Tensor), 3차원 이상은 n차원이 된다.

n-Dimensional Arrays

array_1d = np.array([1, 2, 3, 4])     # 1차원 배열 생성

print(my_array.ndim)                  # 배열의 차원 확인
print(my_array.shape)                 # 배열의 모양 확인
print(my_array[2])                    # 3번째 요소에 접근

1
(4,)
3


array_2d = np.array([[1, 2, 3, 4],    # 2차원 배열 생성
                     [5, 6, 7, 8]])

print(array_2d.ndim)                  # 배열의 차원 확인
print(array_2d.shape)                 # 배열의 모양 확인                     
print(f'It has {array_2d.shape[0]} rows and {array_2d.shape[1]} columns.')
print(array_2d[1, 2])                 # 2행 3열 요소에 접근
print(array_2d[0, :])                 # 1행의 모든 요소에 접근

2
(2, 4)
It has 2 rows and 4 columns.
7
[1 2 3 4]


array_3d = np.array([[[0, 6, 12, 18],       # 3차원 배열 생성
                      [1, 7, 13, 19]],

                     [[2, 8, 14, 20],
                      [3, 9, 15, 21]],

                     [[4, 10, 16, 22],
                      [5, 11, 17, 23]]])

print(array_3d.ndim)                        # 배열의 차원 확인
print(array_3d.shape)                       # 배열의 모양 확인
print(array_3d[2, 1, 3])                    # 마지막 요소(23)에 접근 
print(array_3d[:, :, 0])                    # 3번째 축의 모든 1번째 요소에 접근

3
(3, 2, 4)
[[0 1]
 [2 3]
 [4 5]]


Create Ndarray

.arange()

a = np.arange(10,30)     # 10부터 29(30 미포함)까지 1(step 파라미터의 기본값)의 간격으로 벡터 생성
print(a)

[10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29]


.flip()

a = np.arange(10,30)
print(np.flip(a))     # a[::-1] 도 같은 결과 출력

[29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10]


.rot90()

m = np.array([['○','●'],
              ['◻︎','◼︎']])

print(np.rot90(m))
print(np.rot90(m, 2))

[['●' '◼︎']
 ['○' '◻︎']]

[['◼︎' '◻︎']
 ['●' '○']]


.nonzero()

b = np.array([5,0,7,0,0,3,0,0,0,6])   
nz_indices = np.nonzero(b)            # 배열에서 0이 아닌 요소의 인덱스를 전부 반환(튜플 형태)
print(nz_indices)

(array([0, 2, 5, 9]),)


.random()

from numpy.random import random   # numpy의 np.random에 있는 random 함수 임포트
z = random((3,3,3))               # 임의의 숫자로 3x3x3 배열을 생성하거나            
                                  # z = np.random.random((3,3,3))로 임포트 없이 경로 호출
print(z)

array([[[0.83663521, 0.59510175, 0.48839477],
        [0.48640451, 0.0606524 , 0.54321352],
        [0.8881745 , 0.99562153, 0.4881865 ]],

       [[0.06356174, 0.78809159, 0.05041292],
        [0.29510927, 0.24837348, 0.5094229 ],
        [0.75293232, 0.9470167 , 0.42133181]],

       [[0.98619747, 0.54987823, 0.00345891],
        [0.65826506, 0.67313928, 0.68320409],
        [0.50627954, 0.18895137, 0.95257915]]])


.linspace()

x = np.linspace(0, 100, num=9)            # 0에서 100(포함)까지 일정 간격으로 9 크기의 벡터 x 생성
y = np.linspace(start=-3, stop=3, num=9)  # -3에서 3(포함)까지 일정 간격으로 9 크기의 벡터 y 생성 
print(x)
print(y)

[  0.   12.5  25.   37.5  50.   62.5  75.   87.5 100. ]
[-3.   -2.25 -1.5  -0.75  0.    0.75  1.5   2.25  3.  ]
  • .arange()과 유사한 함수
  • 일반적으로 차트에 표시할 점을 생성하기 위해 사용

.where()

a = np.arange(10)
x = np.where(a < 5, a, 10*a)                 # 조건(a < 5)이 참이면 a를, 거짓이면 b를 반환
y = np.where(a % 2 == 0, "Even", "Odd")      # 조건(a % 2 == 0)이 참이면 "Even"을, 거짓이면 "Odd"를 반환
print(x)
print(y)

[ 0  1  2  3  4 50 60 70 80 90]
['Even' 'Odd' 'Even' 'Odd' 'Even' 'Odd' 'Even' 'Odd' 'Even' 'Odd']


Calculations

Vectors

v1 = np.array([1, 3, 5, 7])     # 벡터 1
v2 = np.array([2, 4, 6, 8])     # 벡터 2

print(v1 + v2)                  # 벡터합(파이썬 리스트로는 [1, 3, 5, 7, 2, 4, 6, 8] 출력)
print(v1 * v2)                  # 벡터곱(파이썬 리스트로는 에러 발생)

[ 3  7 11 15]
[ 2 12 30 56]

Scalar & Broadcasting

  • 스칼라: 배열과의 연산에 사용되는 단일 숫자
  • 브로드캐스팅: 작은 배열(스칼라)의 모양을 큰 배열의 모양과 호환되도록 확장하는 것
array_2d = np.array([[1, 2, 3, 4],      # 행렬
                     [5, 6, 7, 8]])

print(array_2d + 10)                    # 행렬의 각 요소에 스칼라를 합하기
print(array_2d * 5)                     # 스칼라 곱

[[11 12 13 14]
 [15 16 17 18]]

[[ 5 10 15 20]
 [25 30 35 40]]

Matrices

두 행렬을 곱하는 원리: 위키피디아 Matrix multiplication

# 4 x 2 행렬
a = np.array([[1, 5],         # a11, a12
              [2, 6],         # a21, a22
              [3, 7],         # a31, a32
              [4, 8]])        # a41, a42
 
# 2 x 3 행렬
b = np.array([[1, 3, 5],      # b11, b12, b13
              [2, 4, 6]])     # b21, b22, b23

# a * b 를 계산하는 2가지 방법  
print(np.matmul(a, b))        # 방법1(matmul 함수)

print(a @ b)                  # 방법2(@ 연산자)

[[11 23 35]
 [14 30 46]
 [17 37 57]
 [20 44 68]]


with Matplotlib

import matplotlib.pyplot as plt


.linspace() + pyplot.plot()

plt.plot(x, y)    # linspace 함수로 만든 x, y 벡터로 꺾은선형 차트 생성
plt.show()



.random() + pyplot.imshow()

noise = np.random.random((128,128,3))   # 128x128x3 형태의 무작위 배열 생성(꼭 3차원이어야 한다!)
plt.imshow(noise)                       # 배열을 이미지화(배열의 각 차원이 픽셀의 RGB색 정보를 저장)


with SciPy

과학적 계산을 위한 라이브러리로, NumPy를 기반으로 고급 수학 기능을 수행

import scipy.stats as stats       # 통계와 확률에 필요한 도구 제공
from scipy.datasets import face   # 라이브러리에서 제공하는 예제 이미지 임포트


scipy.stats

.ttest_ind()

group_a = [80, 85, 88, 90, 92]                         # 그룹 A 점수
group_b = [78, 82, 84, 86, 89]                         # 그룹 B 점수

t_stat, p_value = stats.ttest_ind(group_a, group_b)    # t-통계량과 p-value 계산

print(f"T-Statistic: {t_stat}")    # 두 그룹의 평균의 차이
print(f"P-Value: {p_value}")       # t-통계량이 통계적으로 유의미한지 확인('p-value < 0.05'면 유의미하다고 판단)

T-Statistic: 1.1428571428571437
P-Value: 0.2861445588099162


scipy.datasets

💡 이미지 = 픽셀의 모음
💡 픽셀 = 해당 색에 대한 값
💡 색 = R(빨강), G(녹색), B(파랑)의 조합

.face()

img = face()          # 이미지 불러오기

print(type(img))      # 이미지 타입은 NumPy의 ndarray
print(img.shape)      # 768 행과 1024 열로 이루어짐(해상도를 의미)
print(img.ndim)       # 3개의 행렬 존재(각각 빨강, 녹색, 파랑 값)

plt.imshow(img)       # Matplotlib의 imshow 함수로 이미지 출력

<class 'numpy.ndarray'>
(768, 1024, 3)
3


image → grayscale

이미지를 흑백으로 변환(그레이스케일 공식 사용)

공식

  • Y_linear은 결과로 출력될 흑백 이미지
  • 3가지 색이 모두 01 사이일 경우에만 공식 작동
  • 모든 값을 255로 나누어서 sRGB로 변환해야 한다.
sRGB_array = img / 255                              # 1. 스칼라로 나누기(NumPy의 브로드캐스팅)
grey_vals = np.array([0.2126, 0.7152, 0.0722])      # 2. 공식에서 주어진 값을 배열로 저장
img_gray = sRGB_array @ grey_vals                   # 3. 두 배열을 곱하기
plt.imshow(img_gray, cmap='gray')                   # 4. 맷플롯립으로 이미지 표시(cmap 매개변수 필수)




image → solarize

  • 컬러 이미지의 색 반전(e.g. 0255가 되어 검은색이 흰색이 됨)
  • 스칼라 값 255(RGB 픽셀의 최대값)에서 img를 빼서 반대값을 얻어야 한다.
solar_img = 255 - img
plt.imshow(solar_img)



image → upside down

  • NumPy의 .flip() 함수로 Ndarray 행렬의 순서를 반대로 지정
  • 이미지를 위아래로 뒤집는 데 활용할 수 있다.
plt.imshow(np.flip(img_gray), cmap='gray')



image → rotation

  • NumPy의 .rot90() 함수로 Ndarray 행렬을 옆으로 90도 회전
  • 이미지 회전에 활용할 수 있다.
plt.imshow(np.rot90(img))



with Pillow

  • 이미지 처리를 위한 라이브러리로, 이미지 파일을 열어서 수정 후 저장할 수 있는 기능 제공
  • 원래 PIL(Python Imaging Library)이 쓰였으나, Python3에서는 PIL을 기반으로 확장한 Pillow를 공식적으로 사용하게 되었다.
pip install Pillow        # 터미널에서 Pillow 설치
from PIL import Image     # 임포트


원하는 이미지 사용하기

  • 프로젝트의 디렉토리 안에 이미지 파일이 있어야 한다.
  • .png와 같은 파일은 RGB값이 아닌 4개의 채널을 사용하기 때문에 추가적인 처리가 필요
file_name = 'yummy_macarons.jpg'    # 이미지 파일 경로

my_img = Image.open(file_name)      # 이미지 파일 열기
img_array = np.array(my_img)        # 이미지 파일로 Ndarray 생성

plt.imshow(img_array)               # 맷플롯립으로 출력




References
  1. Angela Yu, [Python 부트캠프 : 100개의 프로젝트로 Python 개발 완전 정복], Udemy, https://www.udemy.com/course/best-100-days-python/?couponCode=ST3MT72524
  2. [NumPy reference], https://numpy.org/doc/stable/reference/index.html
  3. [SciPy API], https://scipy.github.io/devdocs/reference/index.html

Leave a comment