선형대수학 부분은 실습 코드 위주에 부가설명을 추가하여 업로드할 예정!
<Linear System, Inverse Matrix, Linear Combination>
1. Install Packages
2. Matrix Operations
3. Linear System
4. Inverse Matrix
5. Linear Combination
Install Packages
# visualization을 위한 helper code입니다.
if 'google.colab' in str(get_ipython()):
print('Downloading plot_helpers.py to util/ (only neded for colab')
!mkdir util; wget https://raw.githubusercontent.com/minireference/noBSLAnotebooks/master/util/plot_helpers.py -P util
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
import scipy as sp
import scipy.linalg
import sympy as sy
from util.plot_helpers import plot_vec, plot_vecs, autoscale_arrows
sy.init_printing()
np.set_printoptions(precision=3)
np.set_printoptions(suppress=True)
Matrix Operation
Matrix Addition 및 Matrix Multiplication은 Matrix A, B, C 그리고 constant c에 대해 다음 식을 만족한다.
Addition
- A + B = B + A
- (A + B) + C = A + (B + C)
- c(A + B) = cA + cB
- (c + d)A = cA + dA
- c(dA) = (cd)A
- A + 0 = A (where 0 is the zero matrix)
- For any A, there exists an -A, such that A + (-A) = 0
Multiplication
- A(BC) = (AB)C
- c(AB) = (cA)B = A(cB)
- A(B + C) = AB + AC
- (B + C)A = BA + CA
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])
A*B # elementwise product # array([[ 5, 12], [21, 32]])
A@B # matrix product # array([[19, 22], [43, 50]])
Matrix Multiplication은 교환법칙이 성립하지 않는다. (AB ≠ BA)
import sympy as sy
A = sy.Matrix([[3, 4], [7, 8]])
B = sy.Matrix([[5, 3], [2, 1]])
A@B

B@A

하지만 Vector Multiplication은 교환법칙이 성립한다.

# 계산에 사용할 기호(symbol)들을 아래와 같이 선언합니다.
x1, x2, y1, y2 = sy.symbols('x1, x2, y1, y2', real = True)
# 위에서 선언한 기호를 활용하여, np.array와 유사한 방식으로 벡터를 선업합니다.
x = sy.Matrix([x1, x2])
y = sy.Matrix([y1, y2])
x.T@y

y.T@x

Matrix Transpose는 Matrix A, B 그리고 constant c에 대해 다음 식들을 만족한다.

a, b, c, d, e, f, g, h, i, j, k, l = sy.symbols('a, b, c, d, e, f, g, h, i, j, k, l', real = True)
A = sy.Matrix([[a, b], [c, d], [e, f]])
B = sy.Matrix([[g, h, i], [j, k, l]])
AB = A@B
AB_tr = AB.transpose()
AB_tr # 4번의 좌항

B_tr_A_tr = B.transpose()@A.transpose()
B_tr_A_tr # 4번의 우항

AB_tr == B_tr_A_tr # True
Linear System
- Linear System은 n(>=1) 개의 Linear Equation(일차 방정식)들의 collection을 뜻한다.
- 동일한 n개의 Variable을 가진 m개의 일차 방정식들은 다음과 같이 나타낼 수 있다.

n = 2 일 때의 Linear System:
x1 = np.linspace(-5, 5, 100)
x2_1 = -x1 + 6
x2_2 = x1 + 4
fig, ax = plt.subplots(figsize = (12, 7))
ax.scatter(1, 5, s = 200, zorder=5, color = 'r', alpha = .8)
ax.plot(x1, x2_1, lw =3, label = '$x_1+x_2=6$')
ax.plot(x1, x2_2, lw =3, label = '$x_1-x_2=-4$')
ax.plot([1, 1], [0, 5], ls = '--', color = 'b', alpha = .5)
ax.plot([-5, 1], [5, 5], ls = '--', color = 'b', alpha = .5)
ax.set_xlim([-5, 5])
ax.set_ylim([0, 12])
ax.legend()
s = '$(1,5)$'
ax.text(1, 5.5, s, fontsize = 20)
ax.set_title('Solution of $x_1+x_2=6$, $x_1-x_2=-4$', size = 22)
ax.grid()

n = 3 일 때의 Linear System:
x1 = np.linspace(-10, 10, 20)
x2 = np.linspace(-10, 10, 20)
X1, X2 = np.meshgrid(x1, x2)
fig = plt.figure(figsize = (9, 9))
ax = fig.add_subplot(111, projection = '3d')
X3_1 = (6 - 2*X2 - X1) * (1/3)
ax.plot_surface(X1, X2, X3_1, cmap ='viridis', alpha = 1)
X3_2 = (4 - 5*X2 - 2*X1) * (1/2)
ax.plot_surface(X1, X2, X3_2, cmap ='summer', alpha = 1)
X3_3 = 2 + 3*X2 - 6*X1
ax.plot_surface(X1, X2, X3_3, cmap ='spring', alpha = 1)
ax.set_xlabel('$x_1$-axis')
ax.set_ylabel('$x_2$-axis')
ax.set_zlabel('$x_3$-axis')
plt.show()

주어진 예시인

형태는

형태로 column 분해할 수 있다. 이 경우 x1, x2, x3는 각 Column Vector의 계수가 된다.
A = sy.Matrix([[1, 2, 3], [2, 5, 2], [6, -3, 1]])
x1, x2, x3 = sy.symbols('x1 x2 x3')
x = sy.Matrix([x1,x2,x3])
print('column vectors:', A.col(0), A.col(1), A.col(2))
fig = plt.figure(figsize = (9,9))
ax = fig.add_subplot(111, projection = '3d')
ax.scatter(6, 4, 2, s = 200, color = 'red')
plot_vecs(A.col(0), A.col(1), A.col(2))
autoscale_arrows()

이는 세 Column Vector([1, 2, 6], [3, 2, 1], [2, 5, -3])을 Linear Combination 해서 b([6, 4, 2])를 만드는 계수 x1, x2, x3을 찾는 문제로 바뀌게 된다.
- Row Picture: 각 row들의 교점을 찾는다.
- Column Picture: 각 column들의 Linear Combination이 b가 되도록 하는 계수 x1, x2, x3를 찾는다.
from sympy.solvers.solveset import linsolve # linsolve 함수로 해를 구할 것입니다
x1, x2, x3 = sy.symbols('x1 x2 x3')
A = sy.Matrix(((1,2,3),(2,5,2),(6,-3,1)))
b = sy.Matrix((6,4,2))
system = A,b # 이와 같이 system을 정의합니다.
linsolve(system, x1, x2, x3) # system, 그리고 x의 원소를 차례로 넣습니다.

해가 없는 경우의 Linear System

Column picture로 Plot:
A = sy.Matrix([[1, 1, 1], [1, -1, -2], [2, 0, -1]])
x1, x2, x3 = sy.symbols('x1 x2 x3')
x = sy.Matrix([x1,x2,x3])
fig = plt.figure(figsize = (9,9))
ax = fig.add_subplot(111, projection = '3d')
ax.scatter(1, 2, 1, s = 200, color = 'red')
plot_vecs(A.col(0), A.col(1), A.col(2))
autoscale_arrows()

세 Column Vector의 Linear Combination으로 b(빨간색 점)을 만들 수 있다면 해가 1개 이상 존재, 만드는 것이 불가능하다면 해가 존재하지 않는다.
A의 해:
x1, x2, x3 = sy.symbols('x1 x2 x3')
A = sy.Matrix(((1,1,1),(1,-1,-2),(2,0,-1)))
b = sy.Matrix((1,2,1))
system = A,b
linsolve(system, x1, x2, x3)

A.det() # 0
해가 무수히 많은 경우의 Linear System

Column Picture로 Plot:
A = sy.Matrix([[0, 1, -1], [2, 1, 2], [2, 2, 1]])
x1, x2, x3 = sy.symbols('x1 x2 x3')
x = sy.Matrix([x1,x2,x3])
fig = plt.figure(figsize = (9,9))
ax = fig.add_subplot(111, projection = '3d')
plot_vecs(A.col(0), A.col(1), A.col(2))
autoscale_arrows()
ax.scatter(4,4,8, s = 200, color = 'red')
ax.set(xlim = [0.,5.], ylim = [0.,5.,], zlim = [0., 10.])
plt.show()

A = sy.Matrix(((0,1,-1),(2,1,2),(2,2,1)))
b = sy.Matrix((4,4,8))
system = A,b
linsolve(system, x1, x2, x3)

위 결과는 어떤 x3의 값에 대해서도 위와 같은 형태의 Vector는 해가 된다는 뜻이므로 해가 무수히 많이 존재하는 경우
A.det() # 0
Inverse Matrix
Square Matrix A의 역행렬

'역행렬이 존재한다' = Input Vector x와 Output Vector Ax 사이에 일대일대응 관계가 성립한다.

Ax로부터 x를 복원할 수 있고, 이를 복원하는 행렬이 A의 역행렬이 된다.
A = np.array([[1, 2, 3], [2, 5, 2], [6, -3, 1]])
b = np.array([6,4,2])
A_inv = np.linalg.inv(A) # np.linalg.inv를 활용하면 A의 inverse를 구할 수 있습니다
A_inv_b = A_inv @ b # A^{-1}b
x = A_inv_b # x = A^{-1}b
print(x)
# 검산해봅시다 (구한 x를 대입)
print(A@x)
print(b)

Linear Combination
두 Vector의 Linear Combination

이를 Plot 하면,
fig, ax = plt.subplots(figsize=(8, 8))
vec = np.array([[[0,0,4,2]],
[[0,0,-2,2]],
[[0,0,2,10]],
[[0,0,8,4]],
[[0,0,-6,6]]])
colors = ['b','b','r','b','b']
# tail이 origin, head가 (4,2), (-2,2), (2,10), (8,4), (-6,6)인 vector plot
for i in range(vec.shape[0]):
X,Y,U,V = zip(*vec[i,:,:])
ax.quiver(X, Y, U, V, angles='xy', scale_units='xy', color = colors[i], scale=1, alpha = .6)
ax.text(x = vec[i,0,2], y = vec[i,0,3], s = '(%.0d, %.0d)' %(vec[i,0,2],vec[i,0,3]), fontsize = 16)
# tail이 (8,4), head가 (2,10)인 vector plot
points12 = np.array([[8,4],[2,10]])
ax.plot(points12[:,0], points12[:,1], c = 'b', lw = 3.5,alpha =0.5, ls = '--')
# tail이 (-6,6), head가 (2,10)인 vector plot
points34 = np.array([[-6, 6],[2,10]])
ax.plot(points34[:,0], points34[:,1], c = 'b', lw = 3.5,alpha =0.5, ls = '--')
ax.set_xlim([-10, 10])
ax.set_ylim([0, 10.5])
ax.set_xlabel('x-axis', fontsize =16)
ax.set_ylabel('y-axis', fontsize =16)
ax.grid()
######################################Basis########################################
a = np.arange(-11, 20, 1)
x = np.arange(-11, 20, 1)
# 붉은색 격자 plot
for i in a:
y1 = i + 0.5*x # 0.5(기울기) = 2/4
ax.plot(x, y1, ls = '--', color = 'pink', lw = 2)
y2 = i - x # -1(기울기) = 2/(-2)
ax.plot(x, y2, ls = '--', color = 'pink', lw = 2)
ax.set_title('Linear Combination of Two Vectors in $\mathbf{R}^2$', size = 22, x =0.5, y = 1.01)
plt.show()

- 붉은 격자는 두 Vector의 Linear Combination으로 도달할 수 있는 공간을 의미한다.
- 해당 붉은 격자가 R2 전체를 커버한다.
'Mathematics > Linear Algebra' 카테고리의 다른 글
| Advanced Eigendecomposition (0) | 2022.05.12 |
|---|---|
| Eigendecomposition (0) | 2022.05.11 |
| Gram-Schmidt orthonormalization & QR decomposition (0) | 2022.05.09 |
| Determinant, Least Square (0) | 2022.05.04 |
| Basis, Span, Change of Basis (0) | 2022.05.03 |