Numpy 응용

김선재·2021년 10월 5일
0

Python 라이브러리

목록 보기
2/3
post-thumbnail

axis 이해하기

axis : 축.

  • 축이란, 데이터가 추가되는 방향
    예를 들어 3차원 배열(3, 4, 5) 배열이 있다면
  • 1차원 배열에 추가되는 것은 0차원 스칼라
  • 2차원 배열에 추가되는 것은 1차원 배열
  • 3차원 배열에 추가되는 것은 2차원 배열
ex_1 = np.arange(1, 61).reshape(3, 4, 5)
      # 3차원 배열에 추가되는 2차원 배열 3개
      # 2차원 배열에 추가되는 1차원 배열 4개
      # 1차원 배열에 추가되는 0차원 스칼라 5개

ex_1 ~~> array([[[ 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, 32, 33, 34, 35],
        [36, 37, 38, 39, 40]],

       [[41, 42, 43, 44, 45],
        [46, 47, 48, 49, 50],
        [51, 52, 53, 54, 55],
        [56, 57, 58, 59, 60]]])
        
arr = np.arange(1, 37).reshape(3, 4, 3)
      # 3차원 배열에 추가되는 2차원 배열 3개,
      # 2차원 배열에 추가되는 1차원 배열 4개,
      # 1차원 배열에 추가되는 0차원 스칼라 3개
arr ~~> array([[[ 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, 32, 33],
        [34, 35, 36]]])

axis : 축의 인덱스
위의 예에서는 3차원 배열기기 때문에 축이 3가지

  • 2차원 배열이 추가되는 axis=0
  • 1차원 배열이 추가되는 axis=1
  • 0차원 스칼라가 추가되는 axis:2

각 축별 최댓값(max) 뽑아내기

np.max(arr, axis = 0)
~~> array([[25, 26, 27],
       [28, 29, 30],
       [31, 32, 33],
       [34, 35, 36]])
np.max(arr, axis = 1)
~~> array([[10, 11, 12],
       [22, 23, 24],
       [34, 35, 36]])
       
np.max(arr, axis = 2)
~~> array([[ 3,  6,  9, 12],
       [15, 18, 21, 24],
       [27, 30, 33, 36]])

인덱스와 슬라이싱

인덱싱(Indexing) : 무엇인가를 가르킨다라는 의미
슬라이싱(Slicing) : 무엇인가를 잘라낸다라는 의미

  • 인덱스로 요소에 접할할때는 하나씩만 접근이 되지만 슬라이싱은 인덱스를 사용하여 범위를 정한 후 시퀀스 객체의 요소에 접근
  • 시퀀스객체[ 시작 인덱스 : 끝 인덱스 ]
arr = np.arange(1, 11).reshape(2, 5)
arr
~~> array([[ 1,  2,  3,  4,  5],
       [ 6,  7,  8,  9, 10]])
       
arr[0] # arr 배열의 0번째 행 선택
~~> array([1, 2, 3, 4, 5])

arr[0][2] # arr 배열의 0번째 행, 2번째 열
~~> 3

arr[0, 2]
~~> 3

특정 차원의 배열을 전체 선택하기 위해 쓰는 연산자 => :

arr[:, 2] # 2차원 배열 전체 중 각 열의 2번째 것
~~> array([3, 8])

arr = np.arange(1, 37).reshape(3, 4, 3)
arr
~~> array([[[ 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, 32, 33],
        [34, 35, 36]]])
 
arr[1, 1:3] # 3차원 배열 중 1번째, 1행부터 3행 전까지
~~> array([[16, 17, 18],
       [19, 20, 21]])
       
arr = np.arange(36).reshape(2, 3, 3, 2)
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],
         [32, 33],
         [34, 35]]]])
         
 arr[0, :, :, 0]
 ~~> array([[ 0,  2,  4],
       [ 6,  8, 10],
       [12, 14, 16]])

✔ 3차원, 0차원 제외하고 1, 2 차원 데이터 전체를 가지고 오고 싶다.

  • 스프레드 연산자( ... )
arr[0, ..., 0] # 3차원과 0차원 사이에 있는 모든 데이터를 선택
~~> array([[ 0,  2,  4],
       [ 6,  8, 10],
       [12, 14, 16]])

배열의 차원과 형상

  • 형상(shape)
  • 차원수(ndim)
arr = np.arange(12).reshape(3, 4)
arr
~~> array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])

arr.shape 
~~> (3, 4)

arr.ndim
~~> 2

차원수 확장하기

  • 보통 기초적인 딥러닝에서 이미지 분석을 위한 CNN을 활용할 때 데이터를 전처리하기 위해 사용한다.
  • tensorflow는 tf.newaxis, numpy는 np.newaxis를 활용해서 추가 차원을 만들어 낼 수 있다.
  • tesnsorflow에서 CNN을 위한 이미지 데이터 형태는 항상 ( N, H, W, C )를 유지한다.
    • N : BATCH_SIZE
    • H : 이미지 세로 픽셀( 세로 크기 )
    • W : 이미지 가로 픽셀( 가로 크기 )
    • C : 이미지의 채널 수( 컬러이미지 RGB:3, 흑백이미지 Grayscale: 1 )

만약 이미지를 크롤링해서 가져오면 가로, 세로 크기 밖에 없다. ( H, W )로 이루어진 2차원 배열이다. 이걸 4차원 배열 형태로 바꿔줘야만 한다.

arr = np.arange(784).reshape(28, 28)
arr.shape
~~> (28, 28)

(28, 28)은 2차원 배열 -> (H, W)만 존재하는 경우이다. 이를 4차원 형태로 강제로 만들어줘야 CNN레이어에 입력이 가능하다. (1, 28, 28, 1)

temp_arr = arrpnp.newaxis, :, :, np.newaxis]
temp_arr.shape
~~> (1, 28, 28, 1)

또는

temp_app2 = arr[np.newaxis, ..., np.newaxis]
temp_arr2.shape
~~> (1, 28, 28, 1)

차원 쥐어 짜기

  • np.squeeze
  • 개수가 1인 차원의 내용을 없애는 기법
temp_squeeze = np.squeeze(temp_arr)
temp_squeeze.shape
~~> (28, 28)

배열의 형상(shape) 바꾸기

  • np.newaxis 를 활용하면 축을 하나 추가하게 된다. ( ▶ 차원 수를 늘린다 )
  • np.squeeze 를 활용하면 개수가 1인 차원의 데이터를 삭제 ( ▶ 차원 수를 줄인다 )
    평탄화
  • revel : 원본 배열을 평탄화 시킨 참조 배열 을 만들어 낸다. (이를 View 또는 Reference 라고 한다 )
  • flatten : 원본 배열을 평탄화 시킨 복사된 배열 을 만들어 낸다.

ravel

x = np.arange(15).reshape(3, 5)
x.shape
~~> (3, 5)

x
~~> array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14]])

temp = np.ravel(x)
temp.shape
~~> (15, )

temp
~~> array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14])

x
~~> array([[100,   1,   2,   3,   4],
       [  5,   6,   7,   8,   9],
       [ 10,  11,  12,  13,  14]])

temp를 변경했는데도 x도 변경 되어있다. ravel은 c의 포인터 개념

flatten

  • flattn은 ravel과 다르게 실제 1차원 배열을 새롭게 만들어 낸다.
x = np.arange(15).reshape(3, 5)
x
~~> array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14]])

temp_flatten = x.flatten()
temp_flatten
~~> array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14])

temp_flatten[0] = 100
temp_flatten
~~> array([ 100,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14])

x
~~> array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14]])

temp_flatten이 변경되어도 x는 변경되지 않는다.
데이터를 조금 더 안전하게 관리해야 하기 때문에 ravel보다는 flatten을 더 많이 쓴다.

reshape

x = np.arange(20)
x
~~> array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16,
       17, 18, 19])
  • reshape 함수내의 모든 숫자를 곱했을 때 스칼라 원소의 개수와 같기만 하면 형상 변환이 가능하다.
x.reshape(2, 5, 2)
~~> array([[[ 0,  1],
        [ 2,  3],
        [ 4,  5],
        [ 6,  7],
        [ 8,  9]],

       [[10, 11],
        [12, 13],
        [14, 15],
        [16, 17],
        [18, 19]]])

x.size # 스칼라 원소의 개수 구하기
~~> 20

-1을 reshape에 넣으면 남는 숫자를 자동을 계산해 준다.

  • -1은 하나만 지정을 해줄 수 있다.
x.reshape(2, -1, 2) # -1이 자동으로 5로 지정된다.
~~> array([[[ 0,  1],
        [ 2,  3],
        [ 4,  5],
        [ 6,  7],
        [ 8,  9]],

       [[10, 11],
        [12, 13],
        [14, 15],
        [16, 17],
        [18, 19]]])

x.reshape(2, 2, -1).shape
(2, 2, 5)

브로드 캐스팅

  • 차원 수가 다른 배열끼리의 연산
  • 차원이 달라도 0차원 스칼라의 개수가 똑같으면 연산이 가능
  • 저차원의 배열을 고차원으로 확장
  • 수학적으로는 고차원 배열의 shape과 똑같은 일벡터를 만들어서 저차원과 곱한 배열을 만들어 계산
x = np.arange(20).reshape(4, 5)
y = np.arange(20, 40).reshape(4, 5)

x.shape, y.shape
~~> (4, 5), (4, 5))

x + y
~~> array([[20, 22, 24, 26, 28],
       [30, 32, 34, 36, 38],
       [40, 42, 44, 46, 48],
       [50, 52, 54, 56, 58]])

x * 2 # 일벡터에 전부 2를 곱해줘 2로 채운 후 x와 곱
~~> array([[ 0,  2,  4,  6,  8],
       [10, 12, 14, 16, 18],
       [20, 22, 24, 26, 28],
       [30, 32, 34, 36, 38]])

shape이 다를 때의 연산

a = np.arange(12).reshape(4, 3)
b = np.arange(100, 103)
c = np.arange(1000, 1004)
d = b.reshape(1, 3)

a.shape, b.shape, c.shape, d.shape
~~> ((4, 3), (3, ), (4, ), (1, 3))

a
~~> array([[ 0,  1,  2],
       [ 3,  4,  5],
       [ 6,  7,  8],
       [ 9, 10, 11]])

b 
~~> array([100, 101, 102])

a의 행, 열과 b의 행, 열 중 a의 열, b의 행이 같기 때문에 더할 수 있다.

a + b 
~~> array([[100, 102, 104],
       [103, 105, 107],
       [106, 108, 110],
       [109, 111, 113]])

c
~~> array([1000, 1001, 1002, 1003])

a + c는 a와 c가 같은 수의 행이나 열이 없기 때문에 더해질 수 없다.

a의 행, 열과 d의 행, 열 중 a의 열, d의 열이 같기 때문에 더할 수 있다.

d
~~> array([[100, 101, 102]])

a + d
~~> array([[100, 102, 104],
       [103, 105, 107],
       [106, 108, 110],
       [109, 111, 113]])

전치행렬 만들기

  • 행렬 A의 행과 열의 인덱스를 바꾼 것을 전치행렬 이라고 한다.
  • A(i,j)A_{(i, j)}의 위치를 A(j,i)A_{(j, i)}로 바꾼 것
  • 보통 Transpose 했다고 이야기 한다.
A = np.arange(6).reshape(2, 3)
A
~~> array([[0, 1, 2],
       [3, 4, 5]])
  • ndarray에서 T만 호출해 주면 전치행렬이 완성된다.
A.T
~~> array([[0, 3],
       [1, 4],
       [2, 5]])

역전파를 사용할 때 사용이 된다.

profile
data science!!, data analyst!! ///// hello world

0개의 댓글