[Week2] Day6 Numpy / 벡터 / 행렬

이규호·2021년 1월 25일
0

부스트캠프 U Stage

목록 보기
6/30

📒 Numpy


Numpy의 기초 강의였다.
Numpy는 인터넷으로 한 번 간단하게 공부를 했었는데
처음부터 끝까지 교수님이 하나하나 짚어주면서 설명해주셔서
머릿속의 내용들을 정리하기가 너무 수월했다.

📝 numpy


⭐️ 어떻게 행렬과 매트릭스를 코드로 표현할 것인가?

✏️ Why needs?

coefficient_matrix = [[2, 2, 1], [2, -1, 2], [1, -1, 2]]
constant_vector = [9, 6, 5]
  • 다양한 Matrix 계산을 어떻게 만들 것 인가?
  • 굉장히 큰 Matrix에 대한 표현
  • 처리 속도 문제 - python은 interpreter 언어

👉 적절한 패키지의 활용이 필요하다.

✏️ numpy(Numerica Python)

  • 파이썬의 고성능 과학 계산용 패키지
  • Matrix와 Vector와 같은 Array 연산의 표준 (선형대수)
  • 일반 List에 비해 빠르고, 메모리에 효율적이다.
  • 반복문 없이 데이터 배열에 대한 처리를 지원한다.
# 패키지 설치
activate ml
conda install numpy
# 호출
import numpy as np

✏️ ndarray

  • numpy는 np.array 함수를 활용하여 배열을 생성한다.
  • 하나의 데이터 타입만 배열에 넣을 수 있다. (선언 시)
  • Dynamic typing을 지원하지 않는다. (C의 Array 사용)
>>> test_aray = np.array([1, 4, 5, 8], float) # (리스트, 타입)
>>> print(test_array)
array([1. , 4. , 5. , 8.])
>>> type(test_array)
numpy.ndarray
>>> type(test_array[3])
numpy.float64

✏️ Array creation

  • shape : numpy array의 dimension 구성을 반환함
  • dtype : numpy array의 데이터 type을 반환함
>>> test_array = np.array([1, 4, 5, "8"]) # String Type의 데이터를 입력해도
>>> print(test_array)
array([1., 4., 5., 8.])
>>> print(type(test_array[3])) # Float Type으로 자동 형변환
numpy.float64
>>> print(test_array.dtype) # Array 전체의 데이터 Type을 반환
dtype('float64')
>>> print(test_array.shape) # Array의 shape를 반환 (Dimension)
(4,)

✏️ Array shape

array의 RANK에 따라 불리는 이름이 있다.

RankNameExample
0scalar7
1vector[10, 10]
2matrix[[10, 10,], [15, 15]]
33-tensor[[[1, 5, 9], [2, 6, 10]], [[3, 7, 11], [4, 8, 12]]]
nn-tensor

✏️ Array dtype

C의 data type과 호환된다.

📝 numpy2


✏️ reshape

Array의 shape의 크기를 변경한다. element의 갯수는 동일하다.

>>> test_matrix = [[1, 2, 3, 4], [1, 2, 5, 8]]
>>> np.array(test_matrix).shape
(2, 4)
>>> np.array(test_matrix).reshape(8,)
array[1, 2, 3, 4, 1, 2, 5, 8]
  • 한개의 -1을 넣으면 size를 기반으로 알아서 reshape해준다.
  • flatten -> 다차원 array를 1차원 array로 반환

✏️ Indexing

  • List와 달리 이차원 배열에서 [0, 0] 표기법을 제공한다.
  • matrix일 경우 앞은 row, 뒤는 column을 의미한다.
>>>  a = np.array([[1, 2, 3], [4, 5, 6]], int)
>>> print(a[1, 2])
6
>>> a[0, 0] = 0
>>> print(a)
array([[0, 2, 3], [4, 5, 6]])

✏️ Slicing

  • List와 달리 행과 열 부분을 나눠서 slicing이 가능하다.
  • matrix의 부분 집합을 추출할 때 유용하다.
>>> a = np.array([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]], int)
>>> a[:, 2:] # 전체 Row의 2열 이상
array([[3, 4, 5], [8, 9, 10]])
>>> a[1, 1:3] # 1 Row의 1열 ~ 2열
array([7, 8])
>>> a[1:3] # 1Row ~ 2Row의 전체
array([6, 7, 8, 9, 10])

✏️ Creation function

  • arange : array의 범위를 지정하여 값의 list를 생성
np.arange(5) # List의 range와 같은 효과, integer로 0부터 4까지 배열 추출
# array([0, 1, 2, 3, 4])
np.arange(0, 3, 0.5) # (시작, 끝, step)으로, floating point도 표시 가능
# array([0., 0.5, 1., 1.5, 2, 2.5])
np.arange(4).reshape(2, 2)
# array([[0, 1], [2, 3]])
  • zeros : 0으로 가득찬 ndarray를 생성
  • ones : 1로 가득찬 ndarray 생성
  • empty : shape만 주어지고 비어있는 ndarray 생성
  • something_like(ndarray) : 기존 ndarray의 shape 크기 만큼 1, 0 또는 empty array를 반환
np.zeros(shape=(5,), dtype=np.int8)
# array([0, 0, 0, 0, 0], dtype = int8)
np.ones((2, 2))
# array([[1, 1], [1, 1]])
  • identity : 단위 행렬(i 행렬)을 생성함
>>> np.identity(3)
array([1., 0., 0.],
      [0., 1., 0.],
      [0., 0., 1.]])
  • eye : 대각선이 1인 행렬에서 K값의 시작 index 변경 가능
np.eye(3, 5, k = 2)
array([0., 0., 1., 0., 0.],
      [0., 0., 0., 1., 0.],
      [0., 0., 0., 0., 1.]])
  • diag : 대각 행렬의 값을 추출 (K 값으로 시작 index 설정 가능)
    k값이 양수일때는 오른쪽으로, 음수일 때는 아래로
matrix = np.arange(9).reshape(3, 3)
np.diag(matrix)
# array([0, 4, 8])
  • random.unitform(시작 값, 끝 값, size) : 균등 분포
  • random.normal(시작 값, 끝 값, size) : 정규 분포

✏️ axis

  • 모든 operation function을 실행할 때 기준이 되는 dimension 축
a = a[np.newaxis, :] # 값은 그대로면서, 축을 하나 늘려준다.
a.T # T를 붙여주면 행과 열을 바꿔준다.

🧤 np.something을 호출하여 다양한 수학 연산자를 확인할 수 있다.

✏️ concatenate

  • numpy array를 합치는(붙이는) 함수

✏️ array operation

numpy는 array간의 기본적인 사칙 연산을 지원한다. (shape가 같아야 된다)

>>> a = np.array([[1, 2, 3], [4, 5, 6]])
>>> a + a
array([[2, 4, 6], [8, 10, 12]])
>>> a - a
array([[0, 0, 0], [0, 0, 0]])
>>> a * a
array([[1, 4, 9], [16, 25, 36]])
  • Matrix의 기본 연산인 Dot product도 지원한다.
>>> a = np.arange(1, 7).reshape(2, 3)
>>> b = np.arange(7, 13).reshape(3, 2)
>>> a.dot(b)
array([[58, 64], [139, 154]])
  • Matrix-Scalar, Vector - Matrix 간의 연산도 지원한다.

📝 numpy3


✏️ Comparisons

배열의 크기가 동일할 때 element간 비교의 결과를 Boolean type으로 반환

>>> a = np.array([1, 3, 0])
>>> b = np.array([5, 2, 1])
>>> a > b
array([False, True, False], dtype=bool)
>>> (a > b).any()
True
np.where(a > 0, 3, 2) # where(condition, True, False)
np.where(a > 0) # True 값의 index들을 반환
a = np.array([1, np.Nan, np.Inf], float)
np.isnan(a) # Not a Number
np.isfinite(a) # is finite number

np.argmax(a), np.argmin(a) # 최대값, 최소값의 index를 반환함
np.argmax(a, axis = 1), np.argmin(a, axis = 0) # axis 기반의 반환
a.argsort() # 작은 값부터 index를 반환
a[a.argsort()[::-1]] # 내침차순

✏️ Boolean & fancy index

  • Boolean index는 특정 조건에 따른 값을 배열 형태로 추출한다.
  • Comparison operation 함수들도 모두 사용 가능하다.
>>> a = np.array([1, 4, 0, 2, 3, 5], float)
>>> a[a > 3] # 조건이 True인 index의 element만 추출
array([4.0, 5.0])
  • numpy는 array를 index value로 사용해서 값 추출이 가능하다.
  • Matrix 형태의 데이터도 가능하다.
>>> a = np.array([2, 4, 6, 8], float)
>>> b = np.array([0, 0, 1, 3, 2, 1], int) # 반드시 integer로 선언
>>> a[b] # bracket index, b 배열의 값을 index로 하여 a의 값들을 추출함.
# a.take(b) -> take 함수 : 윗 줄 문법과 같은 효과
array([2., 2., 4., 8., 6., 4.])

✏️ Numpy data I/O

Text type의 데이터를 읽고 저장하는 기능

a = np.loadtxt("파일명")
a_int = a.astype(int) # int type 변환
np.savetgxt("파일명", a_int, fmt="%.2e", delimiter=",") # csv로 저장

📒 벡터가 뭐에요?


강사님이 UNIST의 임성빈 교수님으로 바뀌었다.
벡터에 대한 수학적 내용 + python으로 구현에 대한 강의였다.
기하와 벡터나 선형대수를 배운지가 꽤 오래 되어서 새로운 개념처럼 느껴졌다.
이제 수학 공부도 열심히 해야겠다..

📝 vector


  • 숫자를 원소로 가지는 list또는 배열이다.
  • 공간에서 한 점을 나타낸다.
  • 원점으로부터 상대적 위치를 표현한다.
# 1차원 벡터 예시
x = np.array([1, 7, 2]) # 행 벡터
x.T # 열 벡터
  • 숫자를 곱해주면 길이만 변한다. (스칼라곱)
  • 벡터끼리 같은 모양을 가지면 사칙연산을 할 수 있다.

📝 벡터의 노름


  • 벡터의 노름(norm)은 원점에서부터의 거리를 말한다.
  • 임의의 차원 d에 대해 성립한다.
  • L1 노름은 각 성분의 변화량의 절대값을 모두 더한다.
  • L2 노름은 피타고라스 정리를 이용해 유클리드 거리를 계산한다.
def L1_norm(x):
    x_norm = np.abs(x)
    x_norm = np.sum(x_norm)
    return x_norm

# np.linalg.norm을 이용해도 구현할 수 있다.
def L2_norm(x):
    x_norm = x * x
    x_norm = np.sum(x_norm)
    x_norm = np.sqrt(x_norm)
    return x_norm
  • 노름의 종류에 따라 기하학적 성질이 달라진다.
  • L1, L2 노름을 이용해 두 벡터 사이의 거리를 계산할 수 있다.
  • 두 벡터 사이의 거리를 계산할 때는 벡터의 뺄셈을 이용한다.
  • 제 2 코사인 법칙에 의해 두 벡터 사이의 각도를 계산할 수 있다.
def angle(x, y):
    v = np.inner(x, y) / (L2_norm(x) * L2_norm(y))
    theta = np.arccos(v)
    return theta

📒 [퀴즈] 벡터- 1~5


5/5 Solve

📝 Q1


Q) 다음 벡터의 L1-노름을 구하시오 (정수값으로 입력)

x = [-1, 2, -3]

A) 1 + 2 + 3 = 6

📝 Q2


Q) 다음 벡터의 L2-노름을 구하시오 (정수값으로 입력)

x = [-6, -8]

A) sqrt(36 + 64) = sqrt(100) = 10

📝 Q3


Q) L2-노름을 이용하여 다음 두 벡터 사이의 거리를 구하시오 (정수값으로 입력)

x = [-3, 0]
y = [0, 4]

A) L2(x - y) = L2([-3, -4]) = sqrt(9 + 16) = sqrt(25) = 5

📝 Q4


Q) 다음 두 벡터 사이의 각도를 구하시오 (라디안 단위: 0 이상, 7 미만의 정수값으로 입력)

x = [0, 1]
y = [0, 2]

A) θ = 내적(x, y) / (L2(x) * L2(y)) = 2 / (1 * 2) = 1.
-> arccos(θ) = arccos(1) = 0

📝 Q5


Q) 내적이 다음과 같이 정의될 때, 다음 두 벡터 (x , y)의 내적을 구하시오 (정수값으로 입력)

<x, y> = ||x||₂||y||₂cos(θ)

x = [1, -1, 1, -1]
y = [4, -4, 4, -4]

A) L2(x) * L2(y) * cos(θ) = 2 * 8 * 1 = 16

📒 행렬이 뭐에요?


이론은 전부 이해했지만, 마지막 응용 부분을 들어도 이해가 잘 되지 않았다.
행렬 연산은 딥러닝의 핵심이라고 한다.
직접 모델을 구현하려면 정말 중요한 부분인 것 같다.
이론에서 응용까지 스스로 적용시키기 위해 많은 공부가 필요할 것 같다.

📝 행렬


  • 행렬(matrix)은 벡터를 원소로 가지는 2차원 배열이다.
  • numpy에서는 행벡터를 원소로 가지는 2차원 배열이라고 생각하면 좋다.
  • 행렬은 행(row)과 열(column)이라는 인덱스(index)를 가진다.
  • 전치 행렬은 행과 열의 인덱스가 바뀐 행렬을 의미한다.
  • 행렬끼리 같은 모양을 가지면 덧셈, 뺄셈, 성분곱, 스칼라곱이 모두 가능하다.

📝 행렬 연산


✏️ 행렬 곱셈

  • 행렬 곱셈은 i번째 행벡터와 j번째 열벡터 사이의 내적을 성분으로 가지는 행렬을 계산한다.
  • 행렬곱을 통해 벡패턴을 추출할 수 있고 데이터를 압축할 수도 있다.
X = np.array([[1, -2, 3],
              [7, 5, 0],
              [-2, -1, 2]])
Y = np.array([[0, 1],
              [1, -1],
              [-2, 1]])
>>> X @ Y # numpy에선 @ 연산을 사용한다.
array([[-8, 6],
       [5, 2],
       [-5, 1]])

✏️ 행렬 내적

  • numpy의 np.inner는 i번째 행벡터와 j번째 행벡터 사이의 내적을 성분으로 가지는 행렬을 계산한다.

✏️ 역행렬

  • 어떤 행렬 A의 연산을 거꾸로 되돌리는 행렬을 역행렬(Inverse matrix)라고 한다.
  • 역행렬은 행과 열 숫자가 같고, 행렬식(determinant)이 0이 아닌 경우에만 계산할 수 있다.
X = np.array([1, -2, 3],
             [7, 5, 0],
             [-2, -1, 2]])
np.linalg.inv(X) # 역행렬 구하기
  • 역행렬을 계산할 수 없다면 유사역행렬(pseudo-inverse) 또는 무어-펜로즈 역행렬을 이용한다.
X = np.array([[0, 1],
              [1, -1],
              [-2, 1]])
np.linalg.pinv(X) # 유사 역행렬 구하기

📝 응용


✏️ 연립방정식 풀기

✏️ 선형회귀분석

📒 [퀴즈] 행렬- 1~5


5/5 Solve

📝 Q1


Q) 다음 보기 중 행렬 X의 올바른 전치행렬을 고르시오.

  X = [[1, 2, 3],
       [4, 5, 6]
       [7, 8, 9]]

  1. [[3, 2, 1],
      [6, 5, 4],
      [9, 8, 7]]  
    
✔️2. [[1, 4, 7],
      [2, 5, 8],
      [3, 6, 9]]
    
  3. [[9, 8, 7],
      [6, 5, 4],
      [3, 2, 1]]
    
  4. [[7, 8, 9],
      [4, 5, 6],
      [1, 2, 3]]
    
  5. [[1, 0, 0],
      [0, 1, 0],
      [0, 0, 1]]

📝 Q2


Q) 두 행렬의 곱셈은 각 행렬의 모양과 상관없이 가능하다.

A) 아니오

📝 Q3


Q) 어떠한 행렬의 역행렬은 항상 계산할 수 있다.

A) 아니오

📝 Q4


Q) 다음 보기 중 행렬 X의 올바른 역행렬을 고르시오.

X = [[1, 0, 1],
     [0, 1, 0]
     [1, 1, 0]]

  1. [[1, 0, 0],
      [0, 1, 0],
      [0, 0, 1]]  
    
  2. [[1, 0, 1],
      [0, 1, 0],
      [1, 1, 0]]
    
  3. [[1, 0, 1],
      [0, 1, 1],
      [1, 0, 0]]
    
✔️4. [[0, -1, 1],
      [0, 1, 0],
      [1, 1, -1]]
    
  5. [[0, -1, 1],
      [-1, 1, 0],
      [1, 0, -1]]

📝 Q5


Q) 다음 보기 중 행렬 X의 올바른 무어-펜로즈 역행렬을 고르시오.

X = [[1, 0, 1],
     [0, 1, 0]]

  1. [[1, 0],
      [0, 1],
      [1, 1]]  
    
  2. [[1, 1],
      [1, 1],
      [0, 0]]
    
✔️3. [[0.5, 0],
      [0, 1],
      [0.5, 0]]
    
  4. [[0.5, 0.5],
      [0, 0.5],
      [0.5, 0]]
    
  5. [[0, 1],
      [1, 0],
      [0, 1]]
profile
Beginner

0개의 댓글