프로그래머스 인공지능 데브코스 3기 수업내용 정리 #10(Numpy 실습)

Clay Ryu's sound lab·2021년 12월 20일
0

Note for 2021

목록 보기
10/33
post-custom-banner

Numpy(Numerical Python)

넘파이(Numpy)는 Python에서 벡터, 행렬 등 수치 연산을 수행하는 선형대수(Linear algebra) 라이브러리이다. 선형대수 관련 수치 연산을 지원하고 내부적으로는 C로 구현되어 있어 연산이 빠른 속도로 수행된다. 또한 Scipy와 함께 사용하면 공학용 소프트웨어인 MATLAB에 버금가는 기능을 지원한다고 알려져 있다.

Ndarray의 특징

선형대수의 데이터의 유형에는 스칼라(scalar), 벡터(vector), 행렬(matrix), 텐서(Tensor)가 있다.
numpy의 array로 벡터와 행렬, 텐서를 표현할 수 있다.

import numpy as np
arr = np.arange(0, 32)
#벡터
arr -> array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31])
#행렬
v= arr.reshape([4,8])
v -> 48열의 행렬
#텐서
v = arr.reshape([4,2,4])
v -> 
array([[[ 0,  1,  2,  3],
        [ 4,  5,  6,  7]],

       [[ 8,  9, 10, 11],
        [12, 13, 14, 15]],

       [[16, 17, 18, 19],
        [20, 21, 22, 23]],

       [[24, 25, 26, 27],
        [28, 29, 30, 31]]])
#이런 텐서를 만나게 되면 괄호를 기준으로 차원을 생각해볼수 있다.
가장 작은 괄호는 텐서 크기의 가장 마지막 값을 가리킨다.(H x W x D에서 D)

파이썬 list를 Numpy 배열로 만들기

arr = [1, 2, 3, 4, 5]
print(arr, type(arr)) -> [1, 2, 3, 4, 5] <class `list`>
np_arr = np.array(arr) 
print(np_arr, type(np_arr)) -> [1 2 3 4 5] <class `numpy.ndarray`>

인덱싱, 슬라이싱

파이썬과 동일 다만 특이사항은 아래 블로그 인덱싱 부분 참고
https://laboputer.github.io/machine-learning/2020/04/25/numpy-quickstart/

인덱스 배열로 인덱싱하기 - Indexing with Arrays of Indices

a = np.arange(12)**2
print(a)
# [  0   1   4   9  16  25  36  49  64  81 100 121]

i = np.array([1, 1, 3, 8, 5])
print(a[i])
#i라는 배열의 값들은 a라는 배열의 인덱스를 가리킨다.
# [ 1  1  9 64 25]

j = np.array([[3, 4], [9, 7]])
print(a[j])
#j라는 배열의 값들은 a라는 배열의 인덱스를 가리킨다.
# [[ 9 16]
#  [81 49]]
palette = np.array([[0, 0, 0],         # black
                    [255, 0, 0],       # red
                    [0, 255, 0],       # green
                    [0, 0, 255],       # blue
                    [255, 255, 255]])  # white

image = np.array([[0, 1, 2, 0],
                  [0, 3, 4, 0]])

palette[image]

# array([[[  0,   0,   0],
#         [255,   0,   0],
#         [  0, 255,   0],
#         [  0,   0,   0]],

#        [[  0,   0,   0],
#         [  0,   0, 255],
#         [255, 255, 255],
#         [  0,   0,   0]]])

2차원 슬라이싱

,를 기준으로 차원을 구별할 수 있다.

arr = np.array([
    [1, 2, 3, 4, 5], 
    [4, 5, 6, 7, 8], 
    [5, 6, 7, 8, 9], 
    [10, 11, 14, 15, 17]
    ])
#arr[1:3][2:4]이렇게 쓰면 안된다. 가운데를 ,로 구분해주면 기가막히게 행, 열, 깊이, 상위차원을 구분해서 잘라준다.
print(arr[1:3, 2:4]) -> 
[[6 7]
 [7 8]]

각 요소끼리의 덧셈, 곱셈, 뺄셈, 나눗셈

arr_A = np.array([1, 2, 3, 4, 5])
arr_B = np.array([6, 7, 8, 9, 10])
result = arr_A + arr_B -> [ 7  9 11 13 15]
result = arr_A * arr_B -> [ 6 14 24 36 50]
result = arr_A - arr_B  -> [ 3  3 -1  1 -1]
result = arr_A / arr_B -> 몫 계산
result = arr_A % arr_B -> 나머지 계산

브로드캐스팅

덧셈

Numpy에서는 같은 모양의 배열이 아니더라도 (1)상수를 배열에 더하거나, (2)모양이 다른 배열끼리 덧셈 연산이 가능합니다(단, 특정 조건을 갖춘 배열이여야 합니다). 이와 같이 Numpy에서 배열의 모양이 다르더라도 자동으로 맞춰 연산하는 것을 브로드캐스팅이라고 합니다. 하지만 브로드캐스팅이 적용되려면 특정 조건을 갖춰야만 합니다.

슬라이싱

arr = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
arr[3:7] = 100
arr -> [  1   2   3 100 100 100 100   8   9  10]
#더 높은 차원도 가능하다.
arr[2:6, 3:8] = 0

dot 메소드

A.dot(B)
np.dot(A, B)
A @ B
두 계산의 결과는 행렬의 곱과 같다.

bool 인덱싱

Numpy에선 특별한 관계연산을 사용한 인덱싱이 가능하다. 예시로 보자.

A = np.array([1, 2, 3, 4, 5, 4, 3, 2, 1])
print(A >= 4) -> [False False False  True  True  True False False False]
A = np.array([1, 2, 3, 4, 5, 4, 3, 2, 1])
#bool 배열B를 생성한다. B를 A의 인덱스로 넣어준다.
B = (A >= 4)
print(A[B]) -> [4 5 4]
A = np.array([1, 2, 3, 4, 5, 4, 3, 2, 1])
A[(A > 1) & (A <= 3)] = 0
print(A) -> [1 0 0 4 5 4 0 0 1]

단, Numpy에서 논리 연산자를 사용하여 여러 조건식을 결합할 때, and 및 or가 아닌 & 및 |를 사용한다.

A = np.random.randint(0, 100, size=(3, 3, 3))
#A배열에서 요소의 값이 52거나 1인 자리에 True를 넣음
result = (A == 52) | (A == 1)

Important attributes of an ndarray object

ndarray.shape : 배열의 각 축(axis)의 크기(순서대로 행, 열, 깊이), 객체값으로 리턴 //
ndarray.ndim : 축의 개수(Dimension)
ndarray.dtype : 각 요소(Element)의 타입
ndarray.itemsize : 각 요소(Element)의 타입의 bytes 크기
ndarray.size : 전체 요소(Element)의 개수

a = np.arange(15).reshape(3, 5)
print(a.shape)
# (3, 5)
print(a.ndim)
# 2
print(a.dtype)
# int64
print(a.itemsize)
# 8
print(a.size)
# 15
print(type(a))
# <class 'numpy.ndarray'>

배열생성 Array creation

np.zeros(shape) : 0으로 구성된 N차원 배열 생성 // A = np.zeros(shape=(2,3))
np.ones(shape) : 1로 구성된 N차원 배열 생성 // A = np.ones(shape=(2,3))
np.empty(shape) : 초기화되지 않은 N차원 배열 생성
numpy.arange(start(optional), stop, step(optional), dtype=None, *, like=None)

np.arange(3) array([0, 1, 2])
np.arange(3.0) array([ 0.,  1.,  2.])
np.arange(3,7) array([3, 4, 5, 6])
np.arange(3,7,2) array([3, 5])

np.linspace(): N 등분한 숫자 생성 // np.linspace(0, 99, 100), 0~99까지 100등분

np.random.normal(loc=0.0, scale=1.0, size=None)

정규 분포에 맞게 생성하는 함수로서 모양을 size 인자를 통해 전달하여 배열을 생성합니다. 이때 평균(mean)과 표준편차(std)값을 각각 loc, scale 인자를 통해 지정할 수 있습니다.
Example
rand_arr = np.random.normal(size=(3, 2))
rand_normal_arr = np.random.normal(loc = 3, scale = 0.25, size=(3, 2))
Parameters
loc : float or array_like of floats
scale : float or array_like of floats
size : int or tuple of ints, optional

np.random.randint(low, high=None, size=None, dtype=int)

임의의 정수들로 채워진 배열을 만들어줍니다. 이때 정수 범위는 start 이상 end 미만으로, size에 모양을 인자로 전달합니다.
Example
rand_int_arr = np.random.randint(1, 10, size=(3, 2))
Parameters
low : int or array-like of ints
high : int or array-like of ints, optional
size : int or tuple of ints, optional
dtype : dtype, optional

np.random.randn(d0, d1, ..., dn)

모양을 인자로 주어 배열을 생성합니다. 이때, randn()에 들어간 인자의 순서대로 차원의 크기가 정해집니다. 예를 들어, randn(3, 2)는 3 x 2 모양을 가진 2차원 배열을 생성합니다.

np.random.seed(42)

파이썬의 random패키지와 같이 seed를 고정하여 일정하게 랜덤 값을 유지할 수 있습니다.
Example
np.random.seed(0)
print(np.random.randn(3))
np.random.seed(2)
print(np.random.randn(3))
np.random.seed(0)
print(np.random.randn(3))

연습문제

RGB 값을 흑백이미지로 만들기

높이가 H, 너비가 W인 컬러 이미지에서 RGB 정보를 추출하여 만든 3차원 배열 img는 H x W x 3 모양을 가집니다. 그리고 img의 채널은 R, G, B 순으로 있습니다. 예를 들어, img[1, 1, 0]는 (1, 1) 위치에 있는 픽셀의 R 값에 접근합니다. 또, img[2, 1, 2]는 (2, 1) 위치에 있는 픽셀의 B 값에 접근합니다. img가 numpy.ndarray 타입으로 주어질 때, 위의 방법을 참고하여 img 를 흑백 이미지를 나타내는 H x W 모양의 2차원 배열로 변환하는 함수를 구현하세요.

import numpy as np
def solution(img):
	#배열을 미리 0으로 만들어주고
    answer = np.zeros(shape = (len(img),len(img[0])))
    #각각의 인덱스 값에 알맞는 흑백의 명도 값을 넣어주었다.
    #근데 뭔가 반대로 넣은거 같은데... 일단 보류
    for w_index in range(len(img)):
        for h_index in range(len(img[w_index])):
            R, G, B = img[w_index][h_index]
            N = 0.3*R + 0.5*G + 0.2*B
            answer[w_index][h_index] = N
    return answer
profile
chords & code // harmony with structure
post-custom-banner

0개의 댓글