본문 바로가기
AI 공부/파이썬

파이썬 (Numpy)

by AI Sonny 2022. 8. 24.
728x90

Numpy

  • 수치계산을 하기 위한 파이썬 라이브러리
  • 딥러닝에서 사용되는 텐서와 매우 유사
  • 백테와 행렬 단위의 대용량 수치 연산을 빠르게 진행
    • 병렬 연산한다.

백터(vector)

  • 1차원 데이터(1차원 배열)
  • 스칼라가 연속적으로 여러개 모여있는 것
    • 스칼라(scalar): 단순하게 측정한 하나의 값

행렬(Matrix)

  • 2차원 데이터(2차원 배열)
  • 1차원 데이터가 여러개 모여 있는 것

 


벡터

import numpy as np
lst = [1,2,3,4,5,6]
arr = np.array(lst)
arr

=> array([1, 2, 3, 4, 5, 6])

 

행렬

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

=> array([[1, 2, 3],
         [4, 5, 6]])

 

  • 3차원 배열

 

lst = [
    [
     [1,2,3],
     [4,5,6]
    ],
    [
     [7,8,9],
     [10,11,12]
    ]
]
arr = np.array(lst)
arr

=> array([[[ 1,  2,  3],
         [ 4,  5,  6]],

         [[ 7,  8,  9],
         [10, 11, 12]]])

 


인덱싱과 슬라이싱

  • 기본적으로 파이썬에서 사용되는 인덱싱과 슬라이싱을 그대로 따라간다.

 

자주쓰는 numpy 데이터 타입

 

- 데이터의 바이트 크기를 설정

 

np.array([1,2,3],dtype = np.int32) # 4 byte 크기의 정수
np.array([1,2,3],dtype=np.int64) # 8 byte 크기의 정수 (Default 값이라 출력이 안됨!)
np.array([1,2,3],dtype=np.uint8) # 1 byte 크기의 부호없는 정수(0~255) (이미지 처리할때 자주 쓰임)

=> array([1, 2, 3], dtype=int32)
=> array([1, 2, 3], dtype=int64)
=> array([1, 2, 3], dtype=uint8)

-----------------------------------------------------------------------------------------------

np.array([1,2,3],dtype=np.float32) # 4 byte 크기의 실수 (딥러닝 때 많이 사용)
np.array([1,2,3],dtype=np.float64) # 4 byte 크기의 실수 (Default 값이라 출력이 안됨!)
np.array([1,0,1],dtype=np.bool_) # numpy bool 타입! 

=> array([1., 2., 3.], dtype=float32)
=> array([1., 2., 3.])
=> array([ True, False,  True])

 

- 행과 열개수 파악

 

arr = np.array([
    [1,2,3],
    [4,5,6],
    [7,8,9],
    [10,11,12]
])
arr

arr.shape[0] # 행개수
arr.shape[1] # 열개수
=> 4
=> 3

 

 

- 다차원 슬라이싱

 

arr[:,1]

=> array([ 2,  5,  8, 11])

 

첫 번째 행을 전부 다 가져오고, 두번째 열은 1번 인덱스를 가져온다.

 

arr[:,::2]

=> array([[ 1,  3],
         [ 4,  6],
         [ 7,  9],
         [10, 12]])

 

첫번째 행은 다 가져오고, 두번째 열에서 2를 step하여 인덱스값을 가져온다.

 


마스킹 (masking)

  • bool 배열을 마스크로 사용하여 데이터의 특정 부분을 선택할 수 있다.

 

예시

 

array([[ 1,  2,  3],
       [ 4,  5,  6],
       [ 7,  8,  9],
       [10, 11, 12]])
       
mask_list = [True,False,True,False] # 행 선택
arr[mask_list]

=> array([[1, 2, 3],
         [7, 8, 9]])

 

bool형식으로 list로 변수를 담아내고 출력하면 True행만 반환되는 것을 알 수 있다.

 

mask_list = [True,False,True] # 열 선택
arr[:,mask_list]

=> array([[ 1,  3],
         [ 4,  6],
         [ 7,  9],
         [10, 12]])

 

다차원 슬라이싱을 이용하여 열만 출력할수도 있다.

 

- 여러개의 인덱스 값들을 이용해서 가져오기

 

index_list = [0,2] # 바깥 행에 0번째 행과 2번째열만 가져온다.
arr[index_list]

=>array([[1, 2, 3],
        [7, 8, 9]])

 

바깥 행에 0번째 행과 2번열을 갖고 온다.

 

numpy 함수 알아보기

 

- 배열의 각 요소별로 연산(+,-,*/ 가능)

arr1 = np.array([1,5,1])
arr2 = np.array([3,2,7])

np.add(arr1,arr2) # arr1 + arr2

=> array([4, 7, 8])

 

- 브로드캐스팅 (Broadcasting)

  • 배열의 모양이 다르더라도 어떠한 조건이 만족했을때 작은 배열을 자동으로 큰 배열 크기에 맞춘다.
np.array([
    [1,2,3],
    [4,5,6],
    [7,8,9],
    [10,11,12]
])

arr * np.array([1,2,3]) # 열의 크기를 맞춰주면 행이 늘어난다.

=> array([[ 1,  4,  9],
         [ 4, 10, 18],
         [ 7, 16, 27],
         [10, 22, 36]])

 

다음과 같이 브로드 캐스팅을 이용하면 열의 크기(3)만 맞추면 행이 저절로 늘어나 곱해주는 것을 볼 수 있다.

 


- Norm

  • 벡터의 크기를 측정하는 함수
  •  다 더하고 절대값 씌운 것 = L1
  • 제곱한 후 다 더하고 루트 씌운것 = L2
np.linalg.norm([-1,2,3],1) # L1 norm
np.linalg.norm([-1,2,3],2) # L2 norm (2는 디폴트라 입력안해도 된다!)

=> 6.0
=> 3.7416573867739413

 

- 내적(dot product)

  • 두 벡터의 각 요소끼리 곱의 합
  • 결과값은 스칼라가 나온다.
a = np.array([1,2,3])
b = np.array([4,5,6])
np.dot(a,b)

a @ b # 이렇게도 쓰인다!

=>32

 

- 행렬곱

  • 2차원 공간에서 내적한다.
  • 앞에 행렬의 열개수와 뒤에 행렬의 행개수가 동일해야한다.
  • 연산결과는 shape는 앞에 행렬의 행개수와 뒤에 행렬의 열개수가 나온다.
x = np.array([
    [80,90,70], # 한행은 한 학생의 과거 모의고사 점수
    [81,93,72],
    [71,73,62],
    [61,70,72]
])

 

과거의 모의고사를 가지고, 가중치를 알면 미래 성적을 구할 수 있다.

 

w = np.array([ # 앞에 행렬의 열개수와 뒤에 행렬의 행개수가 동일
    [0.4], # 가중치 를 구하면 예측이 가능!
    [0.2],
    [0.3]
])
x @ w # 다중회귀를 이용하여 미래를 예측할 수 있다.

 

다중회귀를 사용하여  미래 성적을 예측한다.

 

y = np.array([
    [77], # 실제 시험에서의 점수
    [80],
    [71],
    [65]
])

 


배열 만들기

- np.arrange

  • range 함수와 비슷하지만 객체가 아닌 ndarray가 반환된다.

 

예시

 

np.arange(2,10,2)

=> array([2, 4, 6, 8])

 

- np.zeros

  • 0으로 채워진 배열 만들기
np.zeros(10)

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

---------------------------------------------------

np.zeros((2,3,4))

=> array([[[0., 0., 0., 0.],
         [0., 0., 0., 0.],
         [0., 0., 0., 0.]],

        [[0., 0., 0., 0.],
        [0., 0., 0., 0.],
        [0., 0., 0., 0.]]])

 

 

- np.ones

  • 1로 채워진 배열 만들기
np.ones((2,3,1))

=> array([[[1.],
        [1.],
        [1.]],

        [[1.],
        [1.],
        [1.]]])

 

- np.full

  • 지정한 값으로 채워진 배열을 만들 때
np.full([3,5],False)

=> array([[False, False, False, False, False],
         [False, False, False, False, False],
         [False, False, False, False, False]])

 


numpy 집계함수

 

최소값, 중앙값 등 최빈값을 제외한 다양한 집계함수를 사용할 수 있다.

 

scores = np.array([80,90,100,70,40,90]) # 다차원 가능

np.sum(scores), np.std(scores) # score.sum()

=> (470, 19.50783318453271)

 


- exp 함수: y=e^x

  • 자연상수인 오일러의 수를 밑으로 하는 지수함수
  • x 에 0이 들어가면 1, 1이 들어가면 오일러의 수가 나온다.
  • x 값이 조금만 커져도 무한대로 빠진다.
  • 그래서 스케일 조정을 해줘야된다.
np.exp([1,2,3]) # 기하급수적으로 커진다!

=> array([ 2.71828183,  7.3890561 , 20.08553692])

 

자연로그 함수: y=loge_x

  • 오일러 수를 밑으로 하는 로그함수
  • x에 0이하가 들어가면 무한대, 1이 들어가면 0
  • 큰 수를 작게 만들어 정규분포에 가깝게 만듦

x가 0이하의 y의 값이 무한대에 가까워지는 것을 볼 수 있다.

 

즉, 데이터가 큰숫자를 처리할 때  자연로그 함수를 사용한다.

 

np.log(100000000000000)

=> 32.23619130191664

 

- 분위수

  • 데이터를 크기 순서에 따른 위치값
  • 이상치 영향을 덜 받는다.
  • 0.5를 줄 경우 중앙값이 나온다.
arr = np.array([100,3,3,6,7,9,20,10,9])
np.quantile(arr,0.5), np.median(arr), np.mean(arr)

=> (9.0, 9.0, 18.555555555555557)

 

다음과 같이 분위수와 중앙값을 보면 평균에 비해 수가 작게 나오는 것을 알 수 있다.

 

이로써 분위수는 이상치에 영향을 덜 받는다.

 

- 정렬

 

np.sort(arr)
np.sort(arr)[::-1] # 내림차순

=> array([  3,   3,   6,   7,   9,   9,  10,  20, 100])
=> array([100,  20,  10,   9,   9,   7,   6,   3,   3])

 


배열 조건연산

 

배열에서 조건연산은 True, False로 반환된다.

 

예시

 

 

scores = np.array([80,90,100,70,40,90])
scores >= 80 # masking 가능!

=> array([ True,  True,  True, False, False,  True])

 

 

- np.any

  • 조건에 참이 하나라도 있으면 True
np.any(scores >= 100)

=> True

 

- np.all

  • 조건이 모두 참이면 True
np.all(scores >= 70)

=> False

 

 

-np.where

 

np.where(scores >= 80, 1, 0)

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

 

- np.clip

  • 구조 = (array,min,max)
  • 배열에 요소에 min보다 작으면 min으로 변경
  • max보다 크면 max로 변경
  • 이상치 제거하는 데 좋다.
array([[1, 2, 3],
       [0, 0, 3],
       [0, 5, 3]])

 

np.clip(arr,[1,3,1],[3,4,2])

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

 

- 무한대값과 nan값(결측치)

 

np.inf와  np.nan

 

- 전처리 과정에서 nan, inf 값이 동시에 찾기

 

셀 수 있는 정상 수치를 찾는다.

 

np.isfinite(arr)

=> array([False, False,  True,  True,  True,  True])

 

- 무한대와 nan값을 0으로 초기화하기

 

arr[np.isfinite(arr) == False] = 0
arr

=> array([0. , 0. , 4. , 5. , 7. , 8.1])

 


numpy random

- rand 함수

  • 0~1 사이에 랜덤값 반환
np.random.rand()

=> 출력할 때마다 값이 다름

 

배열도 가능하다.

 

np.random.rand(3,3,4)

=> array([[[0.20334628, 0.97235771, 0.3365398 , 0.57339741],
         [0.98327426, 0.67012025, 0.2040247 , 0.59778891],
         [0.30227852, 0.28058461, 0.95835101, 0.06884652]],
 
        [[0.46307451, 0.25222799, 0.15999601, 0.28020491],
         [0.06943581, 0.13306157, 0.57014365, 0.31451093],
         [0.57866082, 0.61023913, 0.58615388, 0.53240497]],

        [[0.41231987, 0.97134875, 0.46866302, 0.88366356],
         [0.85220647, 0.61853079, 0.45999031, 0.69883963],
         [0.7875093 , 0.32514806, 0.80099353, 0.26738617]]])

 

- randn

  • 평균이 0이고, 분산이 1인 정규분포 형태의 랜덤값을 반환
np.random.seed(42)
arr = np.random.randn(10000)
arr

=> array([ 0.49671415, -0.1382643 ,  0.64768854, ..., -0.70531672,
        0.49576557,  0.64438845])

 

 

- randint

  • 랜덤한 정수 반환
  • start ~ end-1
  • 세번째 인자는 크기
np.random.randint(50,100,(4,3))

=> array([[78, 64, 92],
       [57, 70, 88],
       [68, 72, 60],
       [60, 73, 85]])

 

- shuffle

  • 반환값이 없고, 배열 자체를 섞는다.
  • 원본 데이터가 섞여서 위험성이 높다.
  • arr = arr.copy (깊은 복사를 사용해야한다.)
np.random.seed(42)
arr = np.arange(1,7)
np.random.shuffle(arr)
arr
=> array([1, 2, 6, 3, 5, 4])

 

- choice

  • 지정한 개수만큼 랜덤하게 선택해서 추출
np.random.choice(5,3) # 0~4사이의 값을 3개 뽑음

=> array([3, 1, 3])

 


axis 이해하기

np.random.seed(42)
arr = np.random.randint(50,91,[4,3])
arr

=> array([[88, 78, 64],
       [57, 70, 88],
       [68, 72, 60],
       [60, 73, 85]])

 

axis를 이용하여 1차원으로 표현

 

arr.sum(axis = 0) # 1차원

=> array([273, 293, 297])

 

즉, axis가 0인 경우 각 행에 첫번째 열을 더하고, 두번째을 더하고, 세번째 열을 더한 것을 나타낸 결과이다. 

 

axis를 이용하여 2차원으로 표현

 

arr.sum(axis = 1) # 2차원

=> array([230, 215, 200, 218])

 

이번에는 각 열의 같은행을 더한 것이다.

 

axis를 이용하여 3차원으로 표현

 

3차원 배열 생성

 

np.random.seed(42)
arr = np.random.randint(50,91,[4,3,2])
arr

=> array([[[88, 78],
        [64, 57],
        [70, 88]],

       [[68, 72],
        [60, 60],
        [73, 85]],

       [[89, 73],
        [52, 71],
        [51, 73]],

       [[79, 87],
        [51, 70],
        [82, 61]]])

 

결과

 

arr.sum(axis = 0) # 3행 2열

=> array([[324, 310],
       [227, 258],
       [276, 307]])

 

3행 2열인 2차원 구조가 4개가 있는 구조에서 2차원 구조에서 각 같은 행에 같은 열을 더하여 나타낸 것이다.

 


넘파이의 구조를 이해하는데 오래걸렸다.

 

내가 머리로는 이해해도 막상 코드를 실행해보면 원하지않게 나올 때가 많았다.

 

내일 다시 복습하자!

728x90

'AI 공부 > 파이썬' 카테고리의 다른 글

파이썬 (Pandas를 이용한 EDA)  (0) 2022.08.30
파이썬 (Pandas 기초)  (0) 2022.08.30
파이썬 (SQLAIchemy)  (0) 2022.08.23
파이썬 (Pymysql)  (0) 2022.08.23
파이썬 (pip와 가상 환경) 마지막!  (0) 2022.08.10

댓글