Tip/Python

[Python] numpy 라이브러리의 기본적인 유용한 함수들

SuHawn 2020. 8. 26. 18:52
1-08. Numpy 기초

Numpy Basic

In [1]:
import numpy as np

data type

array의 dtype을 본다.

In [2]:
arr = np.array([[1., 2, 3], [1, 2, 3]])

numpy의 data 타입은 하나라도 실수가 포함되어 있으면 실수로 인식한다

In [3]:
arr.dtype
Out[3]:
dtype('float64')

.astype()을 사용해서 datatype을 강제 형변환 가능

In [81]:
arr = arr.astype(np.int32)
arr
Out[81]:
array([3, 5, 6, 6, 3, 3, 1])

array를 생성할 때, dtype= 을 지정해주어서 만들 수도 있다.

In [84]:
arr = np.array([[1., 2, 3], [1, 2, 3]], dtype=np.uint8)
arr.dtype
Out[84]:
dtype('uint8')

len(arr.shape) 를 통해서 차원의 갯수를 확인 할 수 있지만, 아래와 같이 shape과 ndim을 통해 차원 수를 확인할 수 있다.

In [85]:
len(arr.shape)
Out[85]:
2
In [87]:
arr.ndim
Out[87]:
2
In [88]:
arr.shape
Out[88]:
(2, 3)

size 확인 : 사이즈는 array에 존재하는 원소의 개수이다.

In [90]:
arr.size
Out[90]:
6

dtype 확인

In [91]:
arr.dtype
Out[91]:
dtype('uint8')

Reshape

In [92]:
arr.shape
Out[92]:
(2, 3)

Reshape을 통하여 행렬의 형태를 변형할 수 있다.(resize와는 다른 것이다.)

In [93]:
arr = arr.reshape([1, 6])
arr.shape
Out[93]:
(1, 6)
In [12]:
arr = np.array([[1, 2, 3], [1, 2, 3]])
In [94]:
arr.reshape([6]).shape  # 1차원, 벡터로 변환
Out[94]:
(6,)

Reshape, -1 활용, 차원과 사이즈가 클 때, shape를 어떻게 나누어야 할 지 모를 때 -1을 통해서 남는 형태를 변형시킬 수 있다

In [95]:
arr = arr.reshape(-1)
arr.shape
Out[95]:
(6,)
In [96]:
arr = arr.reshape(-1, 3)
arr.shape
Out[96]:
(2, 3)

random array 생성

In [97]:
arr = np.random.randn(8, 8)
arr.shape
Out[97]:
(8, 8)
In [98]:
arr
Out[98]:
array([[-0.59787165,  0.00563604, -0.40750323,  0.12714666,  0.87757431,
        -0.4384266 , -1.05394217, -0.72774784],
       [ 0.91252146, -1.11448461,  0.92986107,  0.91305263, -1.38489503,
         1.12269809,  0.91534079, -0.50648282],
       [-1.37485396,  3.27265939, -1.15092571, -3.08770244,  0.24757335,
        -1.12388415, -0.50694539, -1.68258112],
       [-0.74315937, -0.39082984, -1.21882626,  0.57609084,  1.79176181,
        -0.01061781, -0.49845297,  0.38086041],
       [ 1.78601718,  0.95922182,  1.14148221,  1.67743483,  0.19021581,
        -0.57994507, -2.36904594,  0.63723503],
       [-0.42132594, -1.59561919, -0.34031373,  0.34692717, -0.1929012 ,
        -2.83219539, -1.15250968, -1.75516896],
       [ 1.0607205 ,  1.38619965,  1.05609966,  1.18729133, -0.49292747,
        -1.68128462,  1.30169469, -1.08541589],
       [ 0.36452215, -0.77045596,  0.75356096,  0.6331242 , -0.65665513,
         1.07289204,  1.40196521,  0.28030646]])
In [99]:
arr = arr.reshape([32, 2])
arr.shape
Out[99]:
(32, 2)

3차원 이상으로 늘리기. 원소의 개수가 reshape의 형태와 맞는다면 차원의 개수가 크게 늘어나도 가능하다.

In [101]:
arr = arr.reshape(-1, 2, 1, 1, 1, 1)
arr.shape
Out[101]:
(32, 2, 1, 1, 1, 1)

Ravel

ravel은 일자로 array를 펴준다고 생각하면 되는 함수이다. 즉 원소들을 벡터로 나열한다

In [104]:
arr.shape
Out[104]:
(64,)
In [105]:
arr = arr.ravel()
arr.shape
Out[105]:
(64,)

arr의 차원을 1로 바꿔줌
나중에 배울 layer를 flatten 할 때 같은 기능이라 생각하면 됨

arr.reshape(-1) 와 같음

In [106]:
arr.ravel() == arr.reshape(-1)
Out[106]:
array([ True,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True,  True,  True,  True,  True,  True,  True,
        True])

np.expand_dims()

안의 값은 유지하되 차원 수를 늘리고 싶을 때가 있을 수 있다. 이럴 때 사용하는 것이 expand_dims이다. 즉, 뒤(또는 앞)에다가 1을 추가한다고 생각하면 된다.

In [107]:
arr.shape
Out[107]:
(64,)
In [108]:
arr = np.expand_dims(arr, -1)
arr.shape
Out[108]:
(64, 1)
In [109]:
arr = arr.ravel()
In [110]:
arr.shape
Out[110]:
(64,)

앞에다가 추가할 것이면 0, 뒤에다가 추가할 것이면 -1,(indexing과 동일한 구조)

In [111]:
arr = np.expand_dims(np.expand_dims(arr, -1), 0)
In [112]:
arr.shape
Out[112]:
(1, 64, 1)

zeros & ones

0으로 채워진 numpy array를 만들 수 있음 1로 채워진 numpy array 또한 가능

In [116]:
zeros = np.zeros([3, 3])
zeros
Out[116]:
array([[0., 0., 0.],
       [0., 0., 0.],
       [0., 0., 0.]])
In [117]:
zeros = np.zeros(1)
zeros
Out[117]:
array([0.])
In [118]:
ones = np.ones([10, 5])
ones
Out[118]:
array([[1., 1., 1., 1., 1.],
       [1., 1., 1., 1., 1.],
       [1., 1., 1., 1., 1.],
       [1., 1., 1., 1., 1.],
       [1., 1., 1., 1., 1.],
       [1., 1., 1., 1., 1.],
       [1., 1., 1., 1., 1.],
       [1., 1., 1., 1., 1.],
       [1., 1., 1., 1., 1.],
       [1., 1., 1., 1., 1.]])

ones 이상의 수로 이루어진 array를 만들기 위해서는 scalar 곱셈을 해주면 가능하다

In [120]:
ones * 5
Out[120]:
array([[5., 5., 5., 5., 5.],
       [5., 5., 5., 5., 5.],
       [5., 5., 5., 5., 5.],
       [5., 5., 5., 5., 5.],
       [5., 5., 5., 5., 5.],
       [5., 5., 5., 5., 5.],
       [5., 5., 5., 5., 5.],
       [5., 5., 5., 5., 5.],
       [5., 5., 5., 5., 5.],
       [5., 5., 5., 5., 5.]])

arange

arange함수를 통해서 연속적인 수로 이루어진 array를 만들 수 있다.

In [122]:
arr = np.arange(5)
arr
Out[122]:
array([0, 1, 2, 3, 4])

slicing을 이용하여 원하는 범위로 이루어진 array또한 만들 수 있다.

In [34]:
arr = np.arange(4, 9)
arr
Out[34]:
array([4, 5, 6, 7, 8])
In [123]:
arr = np.arange(10, 20)
arr
Out[123]:
array([10, 11, 12, 13, 14, 15, 16, 17, 18, 19])
In [124]:
arr = np.arange(9).reshape(3, 3)
arr
Out[124]:
array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])

Index

list의 인덱싱과 동일, 하지만 행과 열차원에서 모두 가능 [행 index, 열 index]

In [125]:
nums = [1, 2, 3, 4, 5]
In [126]:
nums[2:]
Out[126]:
[3, 4, 5]
In [127]:
nums = [1, 2, 3, 4, [1, 2, 3]]
nums
Out[127]:
[1, 2, 3, 4, [1, 2, 3]]
In [128]:
nums[4]
Out[128]:
[1, 2, 3]
In [129]:
arr[1][2]
Out[129]:
5
In [130]:
arr[1, 2]
Out[130]:
5
In [132]:
arr[1] # 2행
Out[132]:
array([3, 4, 5])

Slicing

slicing 또한 index와 마찬가지

In [136]:
arr
Out[136]:
array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])
In [137]:
arr[1:]
Out[137]:
array([[3, 4, 5],
       [6, 7, 8]])
In [138]:
arr[1:, 1:]
Out[138]:
array([[4, 5],
       [7, 8]])
In [139]:
arr
Out[139]:
array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])

Boolean Indexing

boolean indexing이란 논리적으로 True 값만 뽑아내는 것이다.

In [47]:
data = np.random.randn(3, 3)
data
Out[47]:
array([[-0.45270524, -0.44128914, -0.55259918],
       [ 1.10990721, -1.46146004,  1.58338455],
       [-0.22833894, -0.2481332 ,  1.43147694]])
In [48]:
data <= 0
Out[48]:
array([[ True,  True,  True],
       [False,  True, False],
       [ True,  True, False]])

이를 활용하여서 특정 데이터만 가공을 할 수 있다.

In [49]:
data[data <= 0] = 1
In [50]:
data
Out[50]:
array([[1.        , 1.        , 1.        ],
       [1.10990721, 1.        , 1.58338455],
       [1.        , 1.        , 1.43147694]])

Broadcast

tensorflow나 pytorch로 계산하면 broadcast의 개념도 잘 이해해야 한다.

broadcast는 연산 하려는 서로 다른 두개의 행렬의 shape가 같지 않고, 한쪽의 차원이라도 같거나 또는 값의 갯수가 한 개 일 때
이를 여러 복사를 하여 단순 연산을 진행하는 것이다.

In [140]:
arr = np.arange(9).reshape(3, 3)
arr
Out[140]:
array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])
In [141]:
arr + 3
Out[141]:
array([[ 3,  4,  5],
       [ 6,  7,  8],
       [ 9, 10, 11]])
In [142]:
arr * 3
Out[142]:
array([[ 0,  3,  6],
       [ 9, 12, 15],
       [18, 21, 24]])
In [143]:
arr
Out[143]:
array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])

벡터로 broadcasting을 진행할 수도 있다.

In [56]:
arr + np.array([1, 2, 3])
Out[56]:
array([[ 1,  3,  5],
       [ 4,  6,  8],
       [ 7,  9, 11]])

Math Function

In [144]:
arr + 10
Out[144]:
array([[10, 11, 12],
       [13, 14, 15],
       [16, 17, 18]])
In [145]:
arr * 5
Out[145]:
array([[ 0,  5, 10],
       [15, 20, 25],
       [30, 35, 40]])
In [146]:
arr + arr
Out[146]:
array([[ 0,  2,  4],
       [ 6,  8, 10],
       [12, 14, 16]])
In [147]:
np.add(arr, 1)
Out[147]:
array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]])
In [148]:
arr + 1
Out[148]:
array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]])
In [149]:
np.multiply(arr, 3)
Out[149]:
array([[ 0,  3,  6],
       [ 9, 12, 15],
       [18, 21, 24]])
In [150]:
arr = np.random.randint(2, size=27).reshape(3, 3, 3)
arr_2 = np.random.randint(2, size=9).reshape(3, 3)
In [151]:
arr.shape, arr_2.shape
Out[151]:
((3, 3, 3), (3, 3))
In [152]:
arr + arr_2
Out[152]:
array([[[1, 1, 0],
        [1, 2, 2],
        [0, 1, 1]],

       [[1, 2, 0],
        [2, 1, 2],
        [1, 2, 2]],

       [[2, 2, 1],
        [2, 2, 2],
        [1, 2, 2]]])
In [153]:
arr * arr_2
Out[153]:
array([[[0, 0, 0],
        [0, 1, 1],
        [0, 0, 0]],

       [[0, 1, 0],
        [1, 0, 1],
        [0, 1, 1]],

       [[1, 1, 0],
        [1, 1, 1],
        [0, 1, 1]]])

기초통계 함수

In [161]:
np.sum(arr)  # array의 원소들의 합을 구하기
Out[161]:
17
In [162]:
np.sum(arr + arr_2)
Out[162]:
38
In [163]:
arr + arr_2
Out[163]:
array([[[1, 1, 0],
        [1, 2, 2],
        [0, 1, 1]],

       [[1, 2, 0],
        [2, 1, 2],
        [1, 2, 2]],

       [[2, 2, 1],
        [2, 2, 2],
        [1, 2, 2]]])
In [164]:
np.max(arr + arr_2)   # array에 존재하는 원소 중 가장 큰 값
Out[164]:
2
In [165]:
np.min(arr + arr_2)   # array에 존재하는 원소 중 가장 작은 값
Out[165]:
0
In [159]:
np.max(arr + arr_2, -1)
Out[159]:
array([[1, 2, 1],
       [2, 2, 2],
       [2, 2, 2]])
In [160]:
arr + arr_2
Out[160]:
array([[[1, 1, 0],
        [1, 2, 2],
        [0, 1, 1]],

       [[1, 2, 0],
        [2, 1, 2],
        [1, 2, 2]],

       [[2, 2, 1],
        [2, 2, 2],
        [1, 2, 2]]])
In [74]:
np.sum(arr + arr_2, axis=-1)
Out[74]:
array([[3, 2, 5],
       [2, 2, 4],
       [3, 2, 5]])
In [166]:
np.mean(arr)   # array에 존재하는 원소들의 산술평균
Out[166]:
0.6296296296296297
In [76]:
arr = np.array([1, 6, 3, 7, 3, 2, 9, 0, 2])
arr
Out[76]:
array([1, 6, 3, 7, 3, 2, 9, 0, 2])
In [168]:
np.argmax(arr)   
# 이는 가장 큰 수치를 갖고있는 원소의 index를 나타낸다, 
# prob이 가장 높은 수를 찾기위한 딥러닝의 분류에서 많이 쓰인다
Out[168]:
4
In [169]:
np.argmin(arr)
# 이는 가장 작은 수치를 갖고있는 원소의 index를 나타낸다, 
Out[169]:
0
In [171]:
arr = np.array([3, 5, 6, 6, 3, 3, 1])
In [172]:
np.unique(arr)  # array에 존재하는 원소들을 중복없이 출력한다.
Out[172]:
array([1, 3, 5, 6])
In [ ]: