[AI][Data Analysis and Machine Learning]NumPy

·2025년 2월 14일
post-thumbnail

NumPy

Numerical Python

https://numpy.org/

  • 수치적 연산을 위해 최적화된 모듈
  • 기본 타입: ndarray (n-dimensional array) 다차원 배열 표현
  • numpy 사용하는 이유 (파이썬에 list가 있는데도)
    • 성능적으로 빠르다
    • 훨씬 적은 메모리 사용
    • 제공하는 함수들이 풍부하다
    • 수많은 모듈에서 numpy 함수명과 기능을 그대로 사용한다.
import numpy as np

차원

  • Scalar : 0 차원 array(단일값)
  • Vector : 1 차원 array
  • Matrix : 2 차원 array
  • Tensor: 3차원(이상) array

1차원 array(벡터) 생성

x = np.array([1,2,3])

x
>array([1,2,3])

type(x)
>numpy.ndarray
  • list 는 원소타입이 제각각 가능하나, array는 모든 원소가 한가지 타입이어야 한다

shape,size,ndim,dtype,len()

shape

numpy 에서는 해당 array 의 크기를 알 수 있다. shape 을 확인함으로써 몇 개의 데이터가 있는지, 몇 차원으로 존재하는지 등을 확인할 수 있다.

arr.shape 는 tuple 이다.

arr = np.array([1,2,3,4,5])
arr
>
array([1,2,3,4,5)]

arr.shape
>(5,)

즉 arr은 1차원, 크기는 5이다.

ndim 차원

arr.ndim
>1

.ndim 과 len(arr.shape) 은 같다

size : 데이터 개수

arr.size
>5

len(array)

  • array 는 iterable 하다!
len(arr)
>5

dtype: data type

arr.dtype
>dtype('int64')

정수 64bit(8byte)를 말한다

arr2 = np.array([10,3.14,2,0.12)]
arr2

>
array([10. ,3.14, 2. ,0.12])

arr2.dtype
>dtype('float64')

numpy에서 사용되는 자료형(자료형 뒤에 붙는 숫자는 몇 비트 크기인지를 의미함)

  • 부호가 있는 정수 int
  • 부호가 없는 정수 uint
  • 실수 float
  • 복소수 complex
  • 불리언 bool
  • 문자열 string_
  • 파이썬 오브젝트 object
  • 유니코드 unicode_

2차원 array 생성

x=np.array([1,2,3,4])
y=np.array([[2,3,4],[1,2,4]])

x
>array([1,2,3,4])

x.shape
>(4,)

x.ndim
>1

len(x)
>4

x.size
>4

y
>array([[2,3,4],
				[1,2,4]])
				
y.shape
>(2,3)

y.ndim
>2

len(y)
>2

y.size
>6

3차원 array

# 2x3x4

z = np.array([
        [
            [1,2,3,4],
            [5,6,7,8],
            [9,10,11,12]
        ],
        [
            [101,102,103,104],
            [105,106,107,108],
            [109,110,111,112]
        ],
             ])

z
>array([[[  1,   2,   3,   4],
        [  5,   6,   7,   8],
        [  9,  10,  11,  12]],

       [[101, 102, 103, 104],
        [105, 106, 107, 108],
        [109, 110, 111, 112]]])
        
        
        
 z.shape
 >(2,3,4)
 
 
 z.size
 >24
 
 

같은 값이라도 ‘차원’이 다를 수 있다

‘차원 변환’ 중요함.


#scalar 0차원
np.array(10)
>array(10)

#1차원
np.array([10])
>array([10])

#2차원
np.array([[10]])
>array([10])

#3차원
np.array([[[10]]])
>array([10])

np.arange()

  • range() 와 유사하다
np.arange(10)
>array([0,1,2,3,4,5,6,7,8,9])

np.arange(1,10)
>array([1,2,3,4,5,6,7,8,9])

np.arange(1,10,2)
>array([1,3,5,7,9])

astype(타입)

  • 타입변환한 array 를 리턴한다
  • 원본 변화는 없다!
d = np.arange(3,10)
d
>array([3,4,5,6,7,8,9])

d.astype(np.float32)
>array([3.,4.,5.,6.,7.,8.,9.],dtype=float32)

d
>array([3,4,5,6,7,8,9])

reshape()

  • ndarray 의 형태, 차원을 바꾸기 위해 사용
  • 머신러닝, 데이터 프로세싱에서 매우 자주 사용된다(차원변환)
#(12, )->(2,6)
np.arange(12).reshape(2,6)
>array([[0,1,2,3,4,5],
				[6,7,8,9,10,11]])
  • 
    np.arange(12).reshape(3,2,2)
    
    >
    array([[[ 0,  1],
            [ 2,  3]],
    
           [[ 4,  5],
            [ 6,  7]],
    
           [[ 8,  9],
            [10, 11]]])
  • size 맞지 않으면 error
np.arange(12).reshape(2,4) 

ValueError: cannot reshape array of size 12 into shape (2,4)

np.ones, np.zeros

np.ones(5)
>array([1.,1.,1.,1.,1.])

np.ones(6).reshape(2,3)
>array([[1., 1., 1.],
       [1., 1., 1.]])

np.eye

  • 단위행렬
  • (5,5) 단위행렬
np.eye(5)

>
array([[1., 0., 0., 0., 0.],
       [0., 1., 0., 0., 0.],
       [0., 0., 1., 0., 0.],
       [0., 0., 0., 1., 0.],
       [0., 0., 0., 0., 1.]])

np.random 서브모듈

  • rand: 0부터 1 사이의 균일 분포 [0,1)
  • randn: 가우시안 표준 정규 분포
  • randint: 균일 분포의 정수 난수

#0~1 사이 10개의 랜덤

np.random.rand(10)
>
array([0.7022079 , 0.4568314 , 0.1572509 , 0.9945428 , 0.60413926,
       0.26675034, 0.06674856, 0.6047497 , 0.18090705, 0.39759417])
np.random.rand(2,3)

>array([[0.07368398, 0.03856894, 0.55895503],
       [0.18494501, 0.31118853, 0.63923653]])
np.random.randn(5)

>array([-0.28035118, -0.34143822,  1.05176861, -1.4786252 ,  1.15442739])
#0~4 사이의 정수 난수 
np.random.randint(5)

#1~99 사이 숫자로 (3,5,2) 형태의 배열 
np.random.randint(1,100,(3,5,2))

>array([[[21, 33],
        [44, 85],
        [14, 62],
        [34, 29],
        [57, 53]],

       [[71, 97],
        [33, 58],
        [73, 94],
        [43, 68],
        [82,  4]],

       [[38, 50],
        [43, 24],
        [74, 25],
        [44, 54],
        [90, 33]]])
  • seed() : 난수를 예측가능하도록 만든다. 실행할 때마다 동일한 난수가 발생되도록 한다
np.random.seed(0)
np.random.rand(4)

>array([0.5488135 , 0.71518937, 0.60276338, 0.54488318])

np.unique()

  • 중복되지 않는 수만
np.unique([11,11,2,2,34,34])

> array([2,11,34])

인덱싱 index

  • 파이썬 리스트와 동일한 개념으로 사용한다
  • 인덱싱 할 때마다 차원이 감소된다
x = np.arange(10)
x

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

x[0]
>0

x[-1],x[9]
>(9,9)

x[3] = 100
x
>
array([  0,   1,   2, 100,   4,   5,   6,   7,   8,   9])

x = np.arange(10).reshape(2,5)
x
>array([[0, 1, 2, 3, 4],
       [5, 6, 7, 8, 9]])
       
       
x[0]#1차원
> array([0,1,2,3,4])

x[0][2]#0차원
>2       
  • 콤마(,)로 인덱싱 가능하다
x[0,2]
>2

x[1,4],x[1,-1],x[-1,-1]
>(9,9,9)

Advanced Indexing

  • integer array indexing
x
>array([[0, 1, 2, 3, 4],
       [5, 6, 7, 8, 9]])
       
x[0]
> array([0, 1, 2, 3, 4])

#0번째 원소가 담긴 2차원 배열이 된다
x[[0]]
>array([[0, 1, 2, 3, 4]])

x[[1,0,0]]
>array([[5, 6, 7, 8, 9],
       [0, 1, 2, 3, 4],
       [0, 1, 2, 3, 4]])
       

슬라이싱

  • 리스트, 문자열 slicing 과 동일한 개념으로 사용한다
  • ‘,’를 사용하여 각 차원별로 슬라이싱이 가능하다
  • 슬라이싱은 차원 변화가 없다
x=np.arange(10)
x

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

x[1:7]
>array([1,2,3,4,5,6])

x[1::3]
>array([1,4,7])
  • list 는 차원별 slicing 이 불가하지만, array 는 가능하다!!
    • list y 를 생성해보자
      y = [[0, 1, 2, 3, 4],
           [5, 6, 7, 8, 9],
           [10, 11, 12, 13, 14]]
      y
      >[[0, 1, 2, 3, 4], [5, 6, 7, 8, 9], [10, 11, 12, 13, 14]]
      
      y[:2]
      >[[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]]
      
      #차원별 slicing 즉 여기서는 1~3과 6~8 을 뽑아내고 싶다는 뜻
      y[:2][1:4]
      ->XX 불가함
      
    • array x 를 생성해보자
    • x에서는 slicing 가능하다!
      x = np.arange(15).reshape(3,5)
      x
      >
      array([[ 0,  1,  2,  3,  4],
             [ 5,  6,  7,  8,  9],
             [10, 11, 12, 13, 14]])
             
             
      x[:2,1:4]
      > array([[1, 2, 3],
             [6, 7, 8]])
             

shape(차원) 변경하기

차원 변환은 데이터분석과 인공지능에서 자주 발생하는 작업이기 때문에 자유자재로 변환 가능해야함. 머리속으로 내가 변환하는 데이터의 구조가 그려지도록 익숙해져야 좋아용

EX. 이미지 데이터 벡터화 - 이미지는 기본적으로 2차원 혹은 3차원이나 트레이닝을 위해 1차원으로 변형하여 사용된다.

ravel(), np.ravel()

  • 다차원배열을 1차원으로 변경(=펼친다)
  • ‘order’ 파라미터
    • ‘C’- row 우선 변경
    • ‘F’ - column 우선 변경
  • ravel() 은 np 안에 일반 함수로도 있고, 혹은 ndarray의 멤버함수로도 존재한다
x

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

#row (행) 방향으로 펼쳐짐 (axis 0부터 펼쳐진다)
np.ravel(x,order='C')
>array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14])

#column 방향으로 펼쳐짐 -1부터 펼쳐짐 
np.ravel(x,order='F')
>array([ 0,  5, 10,  1,  6, 11,  2,  7, 12,  3,  8, 13,  4,  9, 14])

flatten()

  • 다차원 배열을 1차원으로 변경
  • ravel과의 차이점:
    • copy 를 생성하여 변경한다(원본이 아닌 복사본을 반환)
    • ndarray 의 멤버함수로만 제공된다
  • ‘order’ 파라미터
    • ‘C’ -row 우선 변경
    • ‘F’ - column 우선 변경
y = np.arange(15).reshape(3,5)
y
>array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14]]
       
       
y.flatten()
> array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14])     

reshape 함수

  • array의 shape 을 다른 차원으로 변경한다
  • 주의할 점은 reshape한 후의 전체 원소 개수와 이전 개수가 같아야 가능하다
  • EX. 이미지 데이터 벡터화 하는 경우 사용
  • ‘-1’ 값을 줘서 나머지 차원을 유추하게 할 수 있다.
x2 = np.arange(36)
x2
>
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])
       
       
       
 x2.reshape(6,6)
 >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]])
       
  #차원 유추    
  x2.reshape(6,-1)
  >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]])
       
 #(6,?,2) ?는 3!
 
 x2.reshape(6,-1,2)
 >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]]])   
       
       
       

차원 확장/제거

  • 차원 확장/제거 하는 동작도 머신러닝에서 많이 사용된다

  • reshape() 로 차원 변환(확장/제거) 자유롭게 가능

  • 차원 확장: np.expand_dims()

    • axis 로 지정된 차원을 추가한다
  • 차원 자동 제거 :squeeze, np.squeeze()

    • 차원 중 사이즈가 1인 것을 찾아 스칼라값으로 바꿔 해당 차원을 제거한다
x3 = np.arange(6)
x3
>array([0, 1, 2, 3, 4, 5])

x3.shape
>(6,)

#(6,)=>(6,1)로 차원 확장 
x3 = x3.reshape(6,1)
x3
>array([[0],
       [1],
       [2],
       [3],
       [4],
       [5]])
       
x3 = x3.reshape(6,1,1)
x3
>array([[[0]],

       [[1]],

       [[2]],

       [[3]],

       [[4]],

       [[5]]])
       
       
#1차원으로 축소(차원 제거)      
x3 = x3.reshape((6,))
x3
>array([0, 1, 2, 3, 4, 5])

x3 = x3.reshape(1,1,1,6)
x3
>array([[[[0, 1, 2, 3, 4, 5]]]])

#차원 크기가 1인 차원을 제거 (6,)
x3.squeeze()
>array([0, 1, 2, 3, 4, 5])
x4 = np.arange(4).reshape((2,1,2))
x4
>array([[[0, 1]],

       [[2, 3]]])

#(2,1,2)=>(2,2)       
x4.squeeze()      
       
       
x5 = np.arange(3)
x5
>array([0,1,2])
#0번째 차원축에 새로운 차원 추가
y5 = np.expand_dims(x5,axis=0)
y5

>array([[0, 1, 2]])

transpose,T,swapaxes

전치행렬(transpose matrix), 차원 축 바꾸기

a = np.arange(15).reshape(3,5)
a

>array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14]])
       
       
np.transpose(a)
>array([[ 0,  5, 10],
       [ 1,  6, 11],
       [ 2,  7, 12],
       [ 3,  8, 13],
       [ 4,  9, 14]])
       
       
a.T
>array([[ 0,  5, 10],
       [ 1,  6, 11],
       [ 2,  7, 12],
       [ 3,  8, 13],
       [ 4,  9, 14]])
 
#axis 0과 axis 1을 바꾸기 
np.swapaxes(a,0,1)
>array([[ 0,  5, 10],
       [ 1,  6, 11],
       [ 2,  7, 12],
       [ 3,  8, 13],
       [ 4,  9, 14]])      
profile
어리둥절 빙글빙글 돌아가는 코딩세상~

0개의 댓글