행렬이란?
- 행렬(matrix)는 벡터를 원소로 가지는 2차원 배열
- 벡터의 확장
- 벡터의 원소 → 숫자, 행렬의 원소 → 벡터
- numpy에서는 행(row)이 기본 단위
x = np.array([1, -2, 3],
[7, 5, 0],
[-2, -1, 2])
- 벡터 : 소문자 bold, 행렬 : 대문자 bold
- 행렬은 행(row)과 열(column)이라는 index를 가진다
- $X = (x_{ij})$와 같이 표기하기도 한다
- 행렬의 특정 행(열)을 고정하면 행(열)벡터라고 부른다
- 전치행렬 (transpose matrix)은 행과 열의 인덱스가 바뀐 행렬
- $X^T = (x_{ji})$
행렬의 이해 (1)
- 벡터가 공간에서 한 점을 의미하면, 행렬은 여러 점들을 나타낸다
- 행렬의 행벡터 $x_i$는 i번째 데이터를 의미한다
- 행렬의 $x_{ij}$는 i번째 데이터의 j번째 변수 값을 말한다
행렬의 덧셈, 뺄셈, 성분곱, 스칼라곱
- 행렬은 벡터를 원소로 가지는 2차원 배열
- 행렬끼리 같은 모양을 가지면 덧셈, 뺄셈을 계산할 수 있다
- 각 행렬 구성성분끼리 덧셈, 뺄셈
- 성분곱은 벡터와 똑같다
- 각 인덱스 위치끼리 곱한다 - element-wise 연산
- 스칼라곱도 벡터와 똑같다
- 모든 성분에 똑같이 숫자를 곱해준다
행렬 곱셈
- 행렬 곱셈 (matrix multiplication)은 i번째 행벡터와 j번째 열벡터 사이의 내적을 성분으로 가지는 행렬 계산
- X의 열의 개수와 Y의 행의 개수가 같아야 한다
- XY ≠ YX
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]])
'''
행렬의 내적
- 넘파이의
np.inner
는 i번째 행벡터와 j번째 행벡터 사이의 내적을 성분으로 가지는 행렬 계산- 수학에서 말하는 내적과 다르므로 주의
- 수학에선 보통 $tr(XY^T)$을 내적으로 계산
- 행렬의 곱: i번째 행벡터와 j번째 열백터 사이 내적
X = np.array([[1, -2, 3],
[7, 5, 0],
[-2, -1, 2]])
Y = np.array([[0, 1, -1],
[1, -1, 0]])
np.inner(X, Y)
'''
array(([-5, 3],
[5, 2],
[-3, -1]])
'''
행렬의 이해 (2)
- 행렬은 벡터공간에서 사용되는 연산자(operator)로 이해
- 행렬도 두 벡터 연결
- 행렬곱을 통해 벡터를 다른 차원의 공간으로 보낼 수 있다
- 행렬곱을 통해 패턴을 추출할 수 있고 데이터를 압축할 수 있다
- 모든 선형변환(linear transform)은 행렬곱으로 계산 가능
역행렬
- 어떤 행렬 $A$의 연산을 거꾸로 되돌리는 행렬을 역행렬(inverse matrix)라 부르고 $A^{-1}$이라 표기
- 역행렬은
#행 == #열
이고,행렬식(determinant) != 0
인 경우에만 계산 가능
$AA^{-1} = A^{-1}A = I$ ($I$는 항등행렬, identity matrix)
- 항등행렬 - 곱하면 자기 자신 나오는 행렬, 대각원소 모두 1이고 그 이외 0
numpy.linalg.inv
로 구할 수 있다 (linear algebra → inverse)
X = np.array([[1, -2, 3],
[7, 5, 0],
[-2, -1, 2]])
np.linalg.inv(X)
'''
array([[ 0.21276596, 0.0212766 , -0.31914894],
[-0.29787234, 0.17021277, 0.44680851],
[ 0.06382979, 0.10638298, 0.40425532]])
'''
X @ np.linalg.inv(X)
'''
array([[ 1.00000000e+00, -1.38777878e-17, 0.00000000e+00],
[ 0.00000000e+00, 1.00000000e+00, 0.00000000e+00],
[-2.77555756e-17, 0.00000000e+00, 1.00000000e+00]])
'''
- 만약 역행렬을 계산할 수 없다면, 유사역행렬(pseudo-inverse) 또는 무어-펜로즈(Moore-Penrose) 역행렬 $A^+$를 이용$n \leq m$인 경우 $A^+ = A^T(AA^T)^{-1}$, $n \leq m$이면 $AA^+ = I$만 성립
- 함수:
np.linalg.pinv(Y)
- pseudo inverse
- 함수:
- $n \geq m$인 경우 $A^+ = (A^TA)^{-1}A^T$, $n \geq m$이면 $A^+A = I$가 성립
Y = np.array([[0, 1],
[1, -1],
[-2, 1]])
np.linalg.pinv(Y)
'''
array([[ 5.00000000e-01, 1.11022302e-16, -5.00000000e-01],
[ 8.33333333e-01, -3.33333333e-01, -1.66666667e-01]])
'''
np.linalg.pinv(Y) @ Y
'''
array([[ 1.00000000e+00, -2.22044605e-16],
[ 1.11022302e-16, 1.00000000e+00]])
'''
응용1 : 연립방정식 풀기
np.linalg.pinv
를 이용하면 연립방정식의 해를 구할 수 있다- #식 == #변수 → 해를 구할 수 있다
- 식이 변수 개수보다 작거나 같은 경우 (식의 개수 $\leq$ 변수의 개수), 무어-펜로즈 역행렬을 이용해 해를 하나 구할 수 있다
- 즉, $n \leq m$
응용2: 선형회구분석
np.linalg.pinv
를 이용하면 데이터를 선행모델(linear model)로 해석하는 선형회귀식을 찾을 수 있다- (변수 개수 $\leq$ 식의 개수) 인 경우, $X\beta$는 $y$를 만족하는 $X$를 찾는 것은 불가능하다
- 즉, 연립방정식과 달리 행이 더 크므로 방정식을 푸는 것은 불가능
- $X\beta$로 표현되는 선이 우리의 data를 최대한 잘 표현하도록 → 이런 특성을 가진 선 찾기는 가능
- 즉, $n \geq m$
sklearn
의LinearRegression
과 같은 결과를 가져올 수 있다
from sklearn.linear_model import LinearRegression
model = LinearRegression() # y절편 자동으로 추정
model.fit(X, y)
y_test = model.predict(x_test)
# Moore-Penrose 역행렬
X_ = np.array([np.append(x, [1]) for x in X]) # intercept 항 추가
# y 절편(intercept) 항을 직접 추가해야 한다
beta = np.linalg.pinv(X) @ y
y_test = np.append(x_test) @ beta
'부스트캠프 AI Tech > AI_Math' 카테고리의 다른 글
[06] 확률론 (0) | 2022.01.16 |
---|---|
[05] 딥러닝 학습방법 이해하기 (0) | 2022.01.16 |
[04] 확률적 경사하강법 SGD (0) | 2022.01.15 |
[03] 경사하강법 (0) | 2022.01.15 |
[01] Vector (0) | 2022.01.14 |