Numpy(넘파이) 정리

seulzzang·2022년 10월 5일
0


1. 앞서 약간 기쁜소식
스마일게이트에서 코딩테스트를 보라고 연락이 왔다!
내 생각엔 아마 이 코딩테스트랑 서류를 같이보는.. 서류전형인듯 하다.
그래도 내 서류를 보고 연락을 준걸까..? 저의 지원서 어떤가요..?
어쨌든 좋은 기회가 왔으니 동기부여가 된다😁
2. 이러닝 주간이라 강의 얼른 듣고 지원서 쓰느라고 벨로그 관리도 소홀했고 코딩도 열심히 안했더니.. 감을 약간 잃어버린듯 하다.. 개발자들이 왜 꾸준히 공부하는 지 알겠음


머신러닝 교육과정을 앞두고 판다스랑 넘파이에 대해서 정리하고자 한다.
사실 이 두 라이브러리 모두 다뤄봤지만..
심지어 인공지능 수업때 열심히 다뤘던 것들이다. 근데 이런것들은 정리 안해두면 금방 까먹음!!
판다스랑 넘파이는 같이 쓰는 경우가 많으니! 넘파이 먼저 정리하고자 한다

Numpy란?

  • 행렬 연산이나 다차원 배열을 편리하게 계산하고 처리하는 파이썬 라이브러리
  • 배열(array)단위로 벡터, 행렬 연산 등을 파이썬의 기본 리스트에 비해 빠르고 적은 양의 메모리로 연산
  • 브로드캐스트 지원: 형태가 다른 행렬끼리의 계산
import numpy as np

필요성

1. 행렬 합

matrix_1 = [[1, 2],[3, 4]]
matrix_2 = [[5, 6],[7, 8]]

이런 형태의 2차원 배열.. 즉 행렬이 있을 때, 넘파이 사용 없이 행렬의 합을 구하고자 한다면 이중포문을 사용해야 한다.

matrix_result = []
for i in range(len(matrix_1)):
    tmp = []
    for j in range(len(matrix_2)):
        tmp.append(matrix_1[i][j]+matrix_2[i][j])
    matrix_result.append(tmp)

이렇게!
하지만 Numpy를 이용해 행렬합을 구하고자 한다면 np.array를 사용하여 쉽게 해결할 수 있다.

matrix_result = np.array(matrix_1) + np.array(matrix_2)


참 쉽죠?

2. 숫자와의 연산

한 행렬의 모든 원소에 1을 더하고자 한다.
Numpy를 이용하지 않는다면 마찬가지로 이중포문을 사용하여 각각의 배열의 인덱스에 접근하여 더해줘야 한다.

matrix_1 = [[1, 2],[3, 4]]

for i in range(len(matrix_1)):
    for j in range(len(matrix_2)):
        matrix_1[i][j] = matrix_1[i][j] + 1

근데 이 역시 넘파이를 이용한다면

matrix_1 = [[1, 2],[3, 4]]
np.array(matrix_1) + 1

너무나도 간단하게 해결할 수 있다!

3. 연산 속도 비교

import time

size = 10000000

#list
x = list(range(size))
y = list(range(size))

start_time = time.time()
z = [x[i]+x[i] for i in range(size)]
print("리스트 걸린시간", time.time()-start_time)

#adlist (넘파이)
x = np.arange(size)
y = np.arange(size)
start_time = time.time()
z = x + y
print("넘파이 걸린시간", time.time()-start_time)
리스트 걸린시간 1.5493590831756592
넘파이 걸린시간 0.07301616668701172

Numpy를 안 쓸 이유가 없다.

ndarray

  • Numpy의 다차원 행렬자료구조 클래스
  • np.array(data, dtype = np.float32)와 같이 데이터 타입지정도 같이 해줄 수 있다.

다차원 ndarray

  • 행렬구조: ndarray.shape
  • 차원 확인: ndarray.dim
  • 개수: ndarray.size
  1. 0차원
x = np.array(1)
print(x.shape) # ()
print(x.ndim) # 0
print(x.size) # 1
  1. 1차원
x = np.array([1, 2])
print(x.shape) # (2, )
print(x.ndim) # 1
print(x.size) # 2
  1. 2차원 혹은 그 이상
x = np.array([[1, 2, 3], [4, 5, 6]])
print(x.shape) # (2, 3)
print(x.ndim) # 2
print(x.size) # 6

numpy 주요 메서드 및 함수 정리

np.arange()

  • 파이썬의 range와 유사함
  • np.arange(start, end, step)
x = np.arange(10)
print(x)
x = np.arange(10.0)
print(x)
x = np.arange(1, 10, 2)
print(x)
x = np.arange(1, 10, 0.5)
print(x)
x = np.arange(10, 1, -0.5)
print(x)
[0 1 2 3 4 5 6 7 8 9]
[0. 1. 2. 3. 4. 5. 6. 7. 8. 9.]
[1 3 5 7 9]
[1.  1.5 2.  2.5 3.  3.5 4.  4.5 5.  5.5 6.  6.5 7.  7.5 8.  8.5 9.  9.5]
[10.   9.5  9.   8.5  8.   7.5  7.   6.5  6.   5.5  5.   4.5  4.   3.5
  3.   2.5  2.   1.5]

np.linspace()

  • 균일한 간격으로 리스트 크기만큼의 리스트 생성
  • np.linspace(start, end, size)
  • endpoint=False: 끝 값 포함여부 옵션
x = np.linspace(1, 20, 10, endpoint=False)
print(x)
[ 1.   2.9  4.8  6.7  8.6 10.5 12.4 14.3 16.2 18.1]
x = np.linspace(1, 20, 10, endpoint=True)
print(x)
[ 1.          3.11111111  5.22222222  7.33333333  9.44444444 11.55555556
 13.66666667 15.77777778 17.88888889 20.        ]

np.reshape()

  • 데이터를 유지하면서 차원의 형태를 변경
  • ndarray.reshape(dim)
  • -1일 경우 자동으로 맞춰 생성
x = np.arange(9)

다음과 같이 ndarray를 생성했을 때 [0 1 2 3 4 5 6 7 8]인 리스트가 생성된다.

x = np.arange(9).reshape(3, 3)

이렇게 해주면 3*3 행렬로 만들어줌!

[[0 1 2]
 [3 4 5]
 [6 7 8]]
x = np.arange(9).reshape(3, -1)

-1을 넣어주면 자동으로 3*3행렬로 만들어준다.

random

  • 난수가 들어가 있는 다양한 형태의 데이터를 생성해준다.
np.random.rand(5,5)
array([[0.78537271, 0.09390253, 0.7100877 , 0.49239082, 0.76433812],
       [0.3153292 , 0.1477745 , 0.18806045, 0.13771488, 0.39226348],
       [0.26999992, 0.79353612, 0.62133562, 0.9536003 , 0.43887054],
       [0.90003483, 0.03766647, 0.08435369, 0.38078857, 0.47093035],
       [0.8807208 , 0.04898573, 0.35459603, 0.94382534, 0.0284358 ]])
  • 정수형 난수
np.random.randint(1, 10) # 1부터 10 사이의 랜덤한 정수 하나 출력
  • 정수형 난수 크기 지정
np.random.randint(1, 10, size=(5, 5))
array([[1, 2, 4, 3, 9],
       [5, 8, 9, 4, 6],
       [6, 2, 3, 3, 5],
       [2, 3, 1, 6, 7],
       [1, 3, 5, 9, 5]])

특별한 형태의 배열

  • np.ones([5,5]): 모든 값이 1
  • np.zeros([5,5]): 모든 값이 0
  • np.eye(5): 단위행렬 (행렬곱 시 자기 자신이 나오는)
  • ndarray.ravel(order=‘C’): 행렬 펼치기(행 기준, 'F' = 열 기준)
x = np.random.randint(1, 10, size=(5, 5))
print(x)
print(x.ravel())
print(x.ravel(order='F'))
[[7 9 5 5 4]
 [8 9 2 5 9]
 [4 5 5 9 6]
 [7 1 2 1 3]
 [3 2 3 2 4]]
[7 9 5 5 4 8 9 2 5 9 4 5 5 9 6 7 1 2 1 3 3 2 3 2 4]
[7 8 4 7 3 9 9 5 1 2 5 2 5 2 3 5 5 9 1 2 4 9 6 3 4]

concatenate

  • 배열을 연결
x = np.arange(1, 4)
y = np.arange(4, 7)

np.concatenate([x, y])
array([1, 2, 3, 4, 5, 6])
  • axis=1 열을 기준으로 연결
x = np.arange(10).reshape(2, 5)
y = np.arange(10, 20).reshape(2, 5)
print(x)
print(y)
[[0 1 2 3 4]
 [5 6 7 8 9]]
[[10 11 12 13 14]
 [15 16 17 18 19]]

이렇게 생긴 두 이차원 배열을 concat한다면

np.concatenate([x, y])
array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14],
       [15, 16, 17, 18, 19]])

그냥 concat을 하면 행렬을 밑에 고대로 갖다 붙힘

np.concatenate([x, y], axis=1)
array([[ 0,  1,  2,  3,  4, 10, 11, 12, 13, 14],
       [ 5,  6,  7,  8,  9, 15, 16, 17, 18, 19]])

axis=1로 줄 경우 열을 기준으로.. 그니까 오른쪽으로 쌓아줌.
axis=0axis=1의 경우 현재 판다스에서도 겁나 헷갈리고 있어서 이부분은 따로 정리할 것이다.. 나는 정녕 공대생이 맞는가?

split

  • 배열을 분해
x = np.arange(12)
print(x)
np.split(x, 4)
[ 0  1  2  3  4  5  6  7  8  9 10 11]
[array([0, 1, 2]), array([3, 4, 5]), array([6, 7, 8]), array([ 9, 10, 11])]
  • axis=1 열을 기준으로 분해
x = np.arange(16).reshape(4, 4)
print(x)
np.split(x, 2, axis=1)
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]
 [12 13 14 15]]
[array([[ 0,  1],
        [ 4,  5],
        [ 8,  9],
        [12, 13]]),
 array([[ 2,  3],
        [ 6,  7],
        [10, 11],
        [14, 15]])]

브로드캐스트

  • 형태(차원)가 다른 행렬끼리의 계산
    이게 무슨말이냐면 차원이 다를 경우 자동으로 채워서 계산을 해준다고 생각하면 쉽다.
x = np.arange(1, 10).reshape(3, 3)
y = np.arange(1, 4)
x + y


이런식으로 진행이 되는 것이다.
정말 편리하죠?

연산 및 집계함수

x.dot(y) # 행렬곱
np.transpose(x) # 전치행렬
np.linalg.inv(x) # 역행렬
np.linalg.det(x) # 행렬식
np.mean(x) # 평균
np.median(x) # 중간값
np.std(x) # 표준편차
np.var(x) # 분산
np.sum(x) # 합
np.sum(데이터, axis=1) # 합, 축 변경
np.cumsum(x) # 누적합
np.cumprod(x) # 누적곱
np.min(x) # 최소값
np.argmin(x) #최소값 위치
np.argmax(x) # 최대값 위치
np.any(x > 4) # 하나라도 참이어야 참
np.all(x > 4) # 모든 요소가 참이어야 참
np.where(x > 4) # 조건에 맞는 위치
np.where(x > 4, x, -100) # 조건, True일 경우, False일 경우

... 이런 것들이 있다😉


아진짜 실습 문제까지 다루려고 했는데 지금 11시 30분 졸려죽겠어요 죄송합니다
내일의 슬기가 힘내자..

profile
중요한 것은 꺾이지 않는 마음

0개의 댓글