행렬 Matrix
여러 백터들을 원소로 가지는 2차원 배열
여러 점들
x=np.array([[1,2,3], [4,5,6]])
2개의 행 벡터가 하나의 배열안에 담겨있다.
numpy에서는 행이 기본 단위, 기준이 된다. 그래서
행열이
[[1,2,3],
[4,5,6],
[7,8,9]]
처럼 표현하게 된다.
- 행 row
- 열 column
n X m 행렬이라고 하면 n 개의 행과 m개의 열의 크기를 가진 행렬임을 알 수 있다.
[[1,2,3]
[4,5,6]]
이면 2 X 3 행렬이다.
$ X $ = ($x_{ij}$)로 표기하기도 한다
- 원소 $ x_{ij} $
$ i $는 행의 index, $ j $는 열의 index = $ i $번째 행, $ j $번째 열에 있는 원소이다.
보통 행렬의 한 원소는 소문자로 표시하고 아래에 위치하는 행과 열을 표시한다. - 행 벡터 $ \textbf{x}_n$ ( or 열 벡터)
예를 들어 첫 번째 행 벡터는
$ \textbf{x}_1 = [ x_{11}, x_{12} \cdots, x_{1n} ]$ 와 같다.
그래서 하나의 행렬은 n개의 행 벡터로 이루어져 있다. - 행렬 $\textbf{X}$
행렬은 대문자 볼드체를 사용해서 표현한다.
전치행렬 transpose matrix : $ X^T $
원래 행렬 $\textbf{X} = x_{ij}$행과 열의 인덱스가 바뀐 행렬
$ \textbf{X}^T $ = ($x_{ji}$)
T기호를 우측 위에 붙히면 전치행렬을 취한다는 의미이다.
원래 n X m행렬이었다면 m X n행렬이 된다.
행벡터에 전치를 하면 열벡터로 바뀌게 된다.
행렬의 계산
같은 형태(모양)을 가지면 덧셈, 뺄셈을 할 수 있다
- 덧셈, 뺄셈
행렬의 구성성분들의 덧셈과 뺄셈
$ X \pm Y$ = ($x_{ij} \pm y_{ij}$)
import numpy as np x=np.array([[1,2,3], [4,5,6]]) y=np.array([[6,5,4], [3,2,1]]) # [[1+6,2+5,3+4], [4+3,5+2,6+1]] print(x+y) >>>[[7 7 7] [7 7 7]]
- 성분곱
같은 위치의 원소들끼리의 곱
$ X \odot Y$ = ($x_{ij} \cdot y_{ij}$)
import numpy as np x=np.array([[1,2,3], [4,5,6]]) y=np.array([[6,5,4], [3,2,1]]) # [[1*6,2*5,3*4], [4*3,5*2,6*1]] print(x*y) >>>[[ 6 10 12] [12 10 6]]
- 스칼라곱
스칼라값을 모든 행렬의 값에 곱한다
$\alpha{X}$ = ($\alpha{x_{ij}}$)
import numpy as np x=np.array([[1,2,3], [4,5,6]]) # [[1*8,2*8,3*8], [4*8,5*8,6*8]] print(x*8) >>>[[ 8 16 24] [32 40 48]]
- 행렬 곱셈 matrix multiplication
$\textbf{XY}$를 구한다면
$\textbf{X}$의 i 번째 행벡터와 $\textbf{Y}$의 j 번째 열벡터 사이의 내적을 성분으로 가지게 되는 곱셈이다
$ \textbf{XY}=\sum_{k} x_{ik}y_{kj} $
일반적인 곱셈과 달리 곱하는 순서가 달라지면 결과가 달라진다
$\textbf{X}$행렬의 열과 $\textbf{Y}$행렬의 행의 갯수가 같아야 한다
3*3 행렬과 3*2행렬은 그래서 계산이 가능하다※ np.inner이 작동은 하지만 여기서 말하는 내적과 의미가 다르다.import numpy as np x=np.array([[1,2,3], [4,5,6], [7,8,9]]) y=np.array([[1,2],[3,4], [5,6]]) # x[0][0]=1*1 +2*3 +3*5 print(x@y) >>>[[ 22 28] [ 49 64] [ 76 100]]
그래서 np.inner을 사용해서 내적을 하려면
y를 전치시켜야 한다.import numpy as np x=np.array([[1,2,3], [4,5,6], [7,8,9]]) y=np.array([[1,2],[3,4], [5,6]]) # x[0][0]=1*1 +2*3 +3*5 print(np.inner(x,y.T))
행렬을 이해하는 방법
다른 데이터들을 연결시키는 역할을 한다. 특히 곱하기에서 한 벡터를 행렬을 통해서 다른 벡터랑 이어줄 수 있다.
행렬곱 $ Ax=z $를 하는 것의 의미는
z와 x라는 벡터를 A라는 행렬을 통해서 이어준다.
이렇게 행렬곱을 통해 벡터를 다른 차원의 공간으로 보낼 수 있다
행렬곱을 통해 패턴을 추출할 수도 있고, 데이터를 압축할 수도 있다.
모든 선형변환(linear transform)은 행렬곱으로 계산할 수 있다. 그래서 행렬곱을 이해해야지 기계학습을 이해할 수있다.
딥러닝은 선형변환과 비선형 함수들의 합성으로 이루어져 있기에 또 중요하다
역행렬 inverse matrix $A^{-1}$
연산을 거꾸로 되돌리는 행렬
위의 사진에서 x를 z로 보냈는데, 역행렬을 곱하게 되면 다시 z가 x로 보내지게 된다.
조건
- 행렬식(determinant)가 0이 아니어야 함
- 행과 열의 크기가 같은 정방행렬이어야 함
$$ AA^{-1} = A^{-1}A = I $$
역행렬은 곱해지는 순서에 상관없다.
$I$는 항등행렬인데 어느 행렬에나 $I$를 곱하면 다시 그 행렬이 결과로 나오게 되는 행렬이다.
import numpy as np
x=np.array([[1,2,3], [4,5,6], [7,8,9]])
inv=np.linalg.inv(x)
x@inv=(항등행렬)
유사역행렬 pseudo-inverse matrix = 무어-펜로즈 역행렬 Moore-Penrose 역행렬 $ A^+ $
행과 열의 수가 달라도 역행렬을 구하는 방법
역행렬과 유사한 기능을 한다.
- 행의 갯수가 열의 갯수보다 큰 경우 n>=m
$A^+ = (A^{T}A)^{-1}A^T$
※주의 : 유사역행렬을 원래 행렬보다 먼저 곱해주어야만 한다 : $A^+A$ - 행의 갯수가 열의 갯수보다 작은 경우 n<=m
$A^+ = A^T(AA^{T})^{-1}$
※주의 : 유사역행렬을 원래 행렬 후에 곱해주어야만 한다 : $AA^+$
import numpy as np
x=np.array([[1,2,3], [4,5,6]])
inv=np.linalg.pinv(x)
inv@x
>>>array([[ 0.83333333, 0.33333333, -0.16666667],
[ 0.33333333, 0.33333333, 0.33333333],
[-0.16666667, 0.33333333, 0.83333333]])
응용
- 연립방정식 풀기
계수(변수) $a$(m)의 갯수가 식의 갯수 n보다 많은 경우(n<=m)에는 보통 부정이다(가능한 계수의 경우가 너무 많다)
계수를 모아서 $A$ 행렬, 해(x)를 모아서 $x$ 벡터, b를 열벡터 $\textbf{b}$로 표현한다.
그래서 이 연립방정식을 행렬식 $ Ax=\textbf{b}$ 으로 표현할 수 있게 된다
우리가 연립방정식을 푼다는 것은 x를 구한다는 뜻이다.(목적)
n(변수의 갯수)<=m(식의 갯수)의 경우에는 유사역행렬을 이용해서 하나의 x벡터를 구할 수 있다
$$ Ax=\textbf{b} $$
$$ AxA^+=\textbf{b}A^+ $$
그래서 만족시키는 x중 하나를 구할 수 있다. - 선형회귀 분석
선형회귀는 데이터가 변수보다는 많을 것이기 때문에 행(식)이 더 많다. (n>=m)
유사역행렬로 선형모델의 답을 구할 수 있다.
이 경우 x를 찾는 것이 아닌 계수 벡터 $\beta$를 구하는 것이 목적이 된다.
실제 상황에 대입해보자면 x는 나이, 몸무게 같은 실제 데이터 값들이 될 것이다.
여러 점들을 행렬 $X$로 나타내고 계수벡터 $\beta$를 곱해주면 선형식 그래프로 나타나게 된다 .
$$X\beta=y$$
행이
$X\beta=y$를 완전히 만족할 수 없다. 왜냐하면 모든 데이터가 일정하게 선 모양으로 완벽하게 그려지지 않는 이상 차이가 생길수 밖에 없기 때문이다.
그래서 우리가 찾은 선형 모델의 값 $\hat{y}$ 과 원래의 정답 $y$ 의 차이가 최소가 되게 하는 $\beta$를 찾는 것으로 문제를 정리할 수 있다.
그 둘의 차이를 L2 norm으로 구하면 된다.
무어펜로즈 역행렬을 이용하여 근사하는 y'를 찾을 수 있다
$$ \beta = X^+y $$
여기에다가 y절편(intercept)항 까지 추가하면 scikit learn의 linear regression 결과와 같은 값을 받을 수 있게 된다.