[3주차 - Day1] Python으로 데이터 다루기 - numpy

2023. 3. 27. 23:39BOOTCAMP/프로그래머스 인공지능 데브코스

Numpy로 연산하기

Vector와 Scalar 사이의 연산

벡터의 각 원소에 대해서 연산을 진행

import numpy as np

 

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

print("더하기 : {}".format(x + c))
print("빼기 : {}".format(x - c))
print("곱하기 : {}".format(x * c))
print("나누기 : {}".format(x / c))

 

더하기 : [6 7 8]
빼기 : [-4 -3 -2]
곱하기 : [ 5 10 15]
나누기 : [0.2 0.4 0.6]

 

Vector와 Vector 사이의 연산

벡터의 같은 인덱스끼리 연산이 진행

y = np.array([1, 3, 5])
z = np.array([2, 9, 20])

print("더하기 : {}".format(y + z))
print("빼기 : {}".format(y - z))
print("곱하기 : {}".format(y * z))
print("나누기 : {}".format(y / z))

더하기 : [ 3 12 25]
빼기 : [ -1  -6 -15]
곱하기 : [  2  27 100]
나누기 : [0.5        0.33333333 0.25      ]

 

Arraydml Indexing

Array에서 특정 위치의 원하는 원소를 가져와야 할 때

Python의 List와 유사하게 진행

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

print(W[0, 0])

print(W[2, 3])

 

1
12

W[1, 2]

7

 

Array Slicing

Python의 리스트와 유사하게 진행

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

W[0:2, 1:3]

array([[2, 3],
       [6, 7]])

W[0:2, 0:4]

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

W[0:2]

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

W[0:2,:]

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

W[0:3, 2:4]

array([[ 3,  4],
       [ 7,  8],
       [11, 12]])

W[:, 2:4]

array([[ 3,  4],
       [ 7,  8],
       [11, 12]])

Array의 Broadcasting

기본적으로 같은 Type의 data에 대해서만 연산이 적용 가능 그러나 만약에 피연산자가 연산 가능하도록 변환이 가능하다면 연산이 가능. (Broadcasting)

 

1. M by N, M by 1

a = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
x = np.array([0, 1, 0])

x = x[:, None]

print(a+x)

[[1 2 3]
 [5 6 7]
 [7 8 9]]

 

2. M by N, 1 by N

y = np.array([0, 1, -1])

print(a * y)

[[ 0  2 -3]
 [ 0  5 -6]
 [ 0  8 -9]]

 

3. M by 1, 1 by N

t = np.array([1, 2, 3]) # 열벡터로 바꿔줘야 함
t = t[:, None]  # Transpose

u = np.array([2, 0, -2])

print(t + u)

[[ 3  1 -1]
 [ 4  2  0]
 [ 5  3  1]]

Numpy의 선형대수

영벡터(영행렬)

  • 원소가 모두 0인 벡터(행렬)
  • np.zeros(dim)을 통해 생성
np.zeros(3)

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

np.zeros((3, 3, 3))

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.],
        [0., 0., 0.]]])

 

일벡 터(일행렬)

  • 원소가 모두 1인 벡터(행렬)
  • np.ones(dim)을 통해 생성, dim은 값, 튜플(,)
np.ones(2)

array([1., 1.])

np.ones((3, 3))

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

 

대각행렬(diagonal matrix)

  • Main diagonal을 제외한 성분이 0인 행렬
  • np.diag((main_diagonals))을 통해 생성할 수 있음.
np.diag((2, 4))

array([[2, 0],
       [0, 4]])

np.diag((1, 3, 5))

array([[1, 0, 0],
       [0, 3, 0],
       [0, 0, 5]])

 

항등행렬(identity matrix)

  • Main diagonal이 1인 대각행렬
  • np.eye(n, (dtype=int, unit, float, complex,...))를 사용
np.eye(2, dtype=int)

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

np.eye(3)

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

 

행렬곱(dot product)

  • 행렬 간의 정의되는 곱 연산(dot product)
  • np.dot() or @사용
mat_1 = np.array([[1, 4], [2, 3]])
mat_2 = np.array([[7, 9], [0, 6]])

mat_1.dot(mat_2)

array([[ 7, 33],
       [14, 36]])

mat_1 @ mat_2

array([[ 7, 33],
       [14, 36]])

 

트레이스(trace)

  • Main diagonal의 합
  • np.trace()를 사용
arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])

arr

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

arr.trace()

15

np.eye(2, dtype=int).trace()

2

 

행렬식(determinant)

  • 행렬을 대표하는 값들 중 하나
  • np.linalg.det()으로 계산
arr_2 = np.array([[2, 3], [1, 6]])
arr_2

array([[2, 3],
       [1, 6]])

np.linalg.det(arr_2)

9.000000000000002

arr_3 = np.array([[1, 4, 7], [2, 5, 8], [3, 6, 9]])
arr_3

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

np.linalg.det(arr_3)

0.0

 

역행렬

  • 행렬 A에 대해서 AB = BA = 1을 만족하는 행렬 B
  • np.linalg.inv()으로 계산
mat = np.array(([1, 4], [2, 3]))

mat

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

mat_inv = np.linalg.inv(mat)

mat_inv

array([[-0.6,  0.8],
       [ 0.4, -0.2]])

mat @ mat_inv

array([[ 1.00000000e+00,  0.00000000e+00],
       [-1.11022302 e-16,  1.00000000e+00]])

 

고육값과 고유벡터(eigenvalue and eigenvector)

  • 정방행렬 A에 대해 Ax=(\lambda) x를 만족하는 상수 (\lambda)와 이에 대응하는 벡터
  • np.linalg.eig()으로 계산
mat = np.array([[2, 0 ,-2], [1, 1, -2], [0, 0, 1]])

mat

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

np.linalg.eig(mat)

(array([1., 2., 1.]), array([[0.        , 0.70710678, 0.89442719],
        [1.        , 0.70710678, 0.        ],
        [0.        , 0.        , 0.4472136 ]]))

 

Validation

eig_val, eig_vec = np.linalg.eig(mat)

eig_val

array([1., 2., 1.])

eig_vec

array([[0.        , 0.70710678, 0.89442719],
       [1.        , 0.70710678, 0.        ],
       [0.        , 0.        , 0.4472136 ]])

mat @ eig_vec[:, 0] # Ax

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

eig_val[0] * eig_vec[:, 0]  # (lambda)x

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