본문 바로가기
IT/Data Analysis

선형대수

by Cyber_ 2024. 8. 12.

선형대수는 벡터 공간을 다루는 수학의 한 분야이다. 선형대수는 다양한 데이터 과학 기술과 개념을 뒷받침해 주는 분야이다.

1. 벡터(vector)

벡터는 벡터끼리 더하거나 상수(scalar)와 곱해지면 새로운 벡터를 생성하는 개념적인 도구, 여기에서는 내적을 통해 두 벡터의 거리를 구할 것이다.
벡터를 float 객체를 갖고 있는 리스트인 Vector라는 타입으로 명시해볼 것이다.

from typing import List

Vector = List[float]

height_weight_age = [70, 170, 40]

grades = [95, 80, 75, 62]

벡터 덧셈은 zip을 사용해서 두 벡터를 묶은 뒤 각 성분끼리 더하는 리스트 컴프리헨션을 적용시키면 된다. 뺄샘도 마찬가지이다.

def add(v: Vector, w: Vector) -> Vector:
    assert len(v) == len(w), "vectors must be the same length"

    return [v_i + w_i for v_i, w_i in zip(v, w)]

assert add([1,2,3], [4,5,6]) == [5,7,9]

벡터로 구성된 리스트에서 모든 벡터의 각 성분을 더하고 싶은 경우,

def vector_sum(vectors: List[Vector]) -> Vector:
    assert vectors, "novectors provides!"

    num_elements = len(vectors[0])
    assert all(len(v) == num_elements for v in vectors), "diffrent siezes!"

    return [sum(vector[i] for vector in vectors) for i in range(num_elements)]

assert vector_sum([[1,2],[3,4],[5,6],[7,8]]) == [16,20]

위와 같은 방식들로 스칼라와 벡터를 연산할 수 있고 같은 길이의 벡터끼리의 평균, 내적 등을 구할 수 있다. 아래는 내적을 구하는 것이다.

def dot(v: Vector, w: Vector) -> float:
    assert len(v) == len(w), "vectors must be same length"

    return sum(v_i * w_i for v_i, w_i in zip(v,w))

만약 벡터 w의 크기가 1이라면 내적은 벡터 v가 벡터 w 방향으로 얼마나 멀리 뻗어 나가는지를 나타낸다.

위의 설명이 어렵다면 내적에 대해서 알 필요가 있다.
https://wikidocs.net/22384
간단히 말하면 내적은 두 백터의 방향이 얼마나 일치하는 지이다.

내적의 개념을 사용하면 각 성분의 제곱 값의 합을 쉽게 구할 수 있다.

def sum_of_squares(v: Vector) -> float:
    return dot(v,v)

제곱 값의 합을 이용하면 벡터의 크기를 계산할 수 있다.

def magnitude(v: Vector) -> float:
    return math.sqrt(sum_of_squares(v))

두 벡터간의 거리는 다음과 같이 계산할 수 있다.

def subtract(v: Vector, w:Vector) -> Vector:
    assert len(v) == len(w), "vectors must be the same length" 
    return  [v_i - w_i for v_i, w_i in zip(v,w)]

def squared_distance(v: Vector, w: Vector) -> float:
    return sum_of_squares(subtract(v,w))

def distance(v: Vector, w: Vector) -> float:
    return math.sqrt(squared_distance(v,w))

2. 행렬

행렬(matrix)은 2차원으로 구성된 숫자의 집합이며, 리스트의 리스트로 표현할 수 있다.

Matrix = List[List[float]]

A = [[1,2,3], # 2개의 행과 3개의 열로 구성되어 있다.
    [4,5,6]]

B = [[1,2], # 3개의 행과 2개의 열로  구성되어 있다.
    [3,4],
    [5,6]]

수학에서는 첫 번째 행을 '행1', 첫 번째 열을 '열 1'로 표기한다. 하지만 파이썬의 리스트는 0부터 시작하기 때문에 여기서도 첫 번째 행을 '행 0', 첫 번째 열을 '열 0'으로 표기했다.

행렬을 리스트의 리스트로 나타내는 경우, 행렬 A는 len(A) 개의 행과 len(A[0])개의 열로 구성되어 있다.

from typing import Tuple

def shape(A: Matrix) -> Tuple[int, int]:
    num_rows = len(A)
    rum_cols = len(A[0]) if A else 0
    return numw_rows, num_cols

만약 형태(shape)가 주어졌을 때, 형태에 맞는 행렬을 생성하고 각 원소를 채워 넣는 함수를 만들어 보자. 중첩된 리스트 컴프리헨션을 사용해서 만들면 된다.

from typing import Callable

def make_matrix(num_rows: int,
                num_cols: int,
                entry_fn: Callable[[int,int], float]) -> Matrix:

    return [[entry_fn(i,j) # i가 주어졌을 때, 리스트를 생성한다.
            for j in range(num_cols)] # [entry_Fn(i,0), ....]
            for i in range(num_rows)] # 각 i에 대해 하나의 리스트를 생성한다.

위 함수를 사용해서 다음과 같이 5 * 5 단위 행렬(identity matrix, 대각선의 원소는 1이고 나머지 원소는 0인 경우)을 생성할 수 있습니다.

def identity matrix(n: int) -> Mamtix:
    return make_matrix(n,n, lambda i,j: 1 if i == j else 0)
  • 각 행렬을 나타냄으로써 여러 벡터로 구성된 데이터셋을 행렬로 표현할 수 있습니다.
  • k차원의 벡터를 n차원 벡터로 변환해주는 선형 함수를 n * k 행렬로 표현할 수 있습니다.
  • 행렬로 이진 관계(binary relationship)를 나타낼 수 있습니다.

마치며

겉핥기를 해보았다. 더 공부해보고 싶다면, 선형대수 교과서를 읽어보는 것도 나쁘지 않다.

  • 세인트 마이클스 칼리지에서 제공하는 선형대수 교과서
  • UC Davis 대학교에서 제공하는 선형대수 교과서
  • 만약 조금 더 고급 내용을 탐색해 보고싶다면 Linear Algebra Done Wrong

'IT > Data Analysis' 카테고리의 다른 글

확률론과 통계학  (0) 2024.08.15
데이터 시각화  (0) 2024.08.11
파이썬 속성 강좌: 심화  (0) 2024.08.11
파이썬 속성강좌_기초  (0) 2024.08.11
데이터 과학  (0) 2024.08.11