행렬을 컴퓨팅을 통해 접근하는 글이며, matplotlib, numpy를 활용한다. 수학적이 아닌 직관적/경험-중심 접근임을 미리 알린다.

import numpy as np
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt

1. 벡터공간

행렬을 많은 방식으로 볼 수 있지만, 이 글에선 벡터 공간속에서의 어떤 역활로 이해/사용한다. 이는 사람에게 공간에 대한 지각력이 선천적이기에, 직관적 접근이 용이하기 때문이라고 생각한다. 여기서는 우리는 벡터를 basis vectors의 조합으로 볼 수 있다.

1.1. 벡터를 basis vectors의 조합으로 보기

벡터 $\vec{v}$를 보았을때, 이는 $\vec{v}=\mathbf{I}\vec{v}$라 하자. 이는 어떤 벡터 공간안에 있는가를 명시적으로 표현한 것이다. 예를들어 벡터공간이 삼차원이라 한다면, $\hat{x}=\{1,0,0\}$, $\hat{y}=\{0,1,0\}$, $\hat{z}=\{0,0,1\}$를 축으로 하는 $\mathbf{I}=\{\hat{x},\hat{y},\hat{z}\}$가 있다고 하자. 이를 가지고 확장하는 벡터 공간인 셈이다. 우린 이때 행렬 $\mathbf{I}$를 벡터들의 벡터라 볼 수도 있을 것이다. 이 행렬을 아래와 같이 시각해 보자.

# pos, direction pairs
vecs = np.array([[0, 0, 0, 1, 0, 0],
                 [0, 0, 0, 0, 1, 0],
                 [0, 0, 0, 0, 0, 1],
                 [0, 0, 0, 1, 1, 1]])

X, Y, Z, U, V, W = zip(*vecs)

vecs2 = np.array([[0, 0, 0, 1, 0, 0],
                  [1, 0, 0, 0, 1, 0],
                  [1, 1, 0, 0, 0, 1],
                  [0, 0, 0, 1, 1, 1]])
X2, Y2, Z2, U2, V2, W2 = zip(*vecs2)

cs = [[1, 0, 0, 1],
      [0, 1, 0, 1],
      [0, 0, 1, 1],
      [0, 0, 0, 1]]

C2 = cs[:] # shallow-copy
[(C2.append(x),C2.append(x)) for x in cs]

C = cs[:3]
[(C.append(x),C.append(x)) for x in cs[:3]]

fig = plt.figure(figsize=plt.figaspect(0.5))
ax = fig.add_subplot(1,2,1, projection='3d', title="fig 1. Basis Vectors")
ax.quiver(X[:3], Y[:3], Z[:3], U[:3], V[:3], W[:3], color=C)
ax.set_xlim([-0.1, 1.1])
ax.set_ylim([-0.1, 1.1])
ax.set_zlim([-0.1, 1.1])
ax = fig.add_subplot(1,2,2, projection='3d', title="fig 2. linear combination")
ax.quiver(X2, Y2, Z2, U2, V2, W2, color=C2)
ax.set_xlim([-0.1, 1.1])
ax.set_ylim([-0.1, 1.1])
ax.set_zlim([-0.1, 1.1])
plt.show()

좌측 fig 1은 basis vectors인 $\hat{x},\hat{y},\hat{z}$를 나타낸 벡터 공간이며, 우측 fig 2는 $\hat{x},\hat{y},\hat{z}$ 의 linear combination 으로 검정색 벡터 $\vec{v}=\{1,1,1\}$을 나타낸 것이다. 즉 $\vec{v}=\hat{x}\cdot{1}+\hat{y}\cdot{1}+\hat{z}\cdot{1}$ 으로 볼 수 있다.

1.2 행렬

이를 간편하게 사용할 방법이 없을까? 어떤 basis vectors로 이루어진 공간을 "벡터들의 벡터" 혹은 "벡터들의 배열"로서 행렬을 쓰면 된다. 예로 든 벡터 공간은 $\mathbf{I}=\{\hat{x},\hat{y},\hat{z}\}$위에 있고 그 공간속 벡터 ${\vec{v}}$는 $\mathbf{I}\cdot\vec{v}=\hat{x}\cdot{1}+\hat{y}\cdot{1}+\hat{z}\cdot{1}$ 으로 basis vectors의 조합이라 할 수 있다.
이 조합을 간편히 행렬과 벡터로 아래와 같이 적을 수 있다. $$\mathbf{I}\cdot{\vec{v}}=\begin{pmatrix} 1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \\ \end{pmatrix}\cdot \begin{pmatrix} 1 \\ 1 \\ 1 \\ \end{pmatrix}$$ 행렬안의 열벡터가 basis vectors이니, 벡터 $\vec{v}$와 행렬 $\mathbf{I}$의 곱을 통해 조합 함을 볼 수 있다.

1.3 행렬, 다른 좌표계

아래와 같이 basis vectors가 $\hat{x},\hat{y},\hat{z}$ 아닌 다른 좌표계를 표현 할 수 있다. 새로운 basis vectors를 $\hat{i},\hat{j},\hat{k}$라 하자. 이때, $$\begin{cases} \hat{i}=\{\frac{1}{2},\frac{1}{2},0\} \\ \hat{j}=\{-\frac{1}{2},\frac{1}{2},0\} \\ \hat{k}=\{0, 0,\frac{1}{2}\} \\ \end{cases}$$ 위 basis vectors을 쓰는 행열 $\mathbf{A}=\{\hat{i},\hat{j},\hat{k}\}$의 공간 상에 $\vec{v}$를 아래와 같이 보자. (쉬운 숫자를 위해 orthonormal basis가 아님)

# pos, direction pairs
vecs = np.array([[0, 0, 0, 0.5, 0.5, 0],
                 [0, 0, 0, -0.5, 0.5, 0],
                 [0, 0, 0, 0.0, 0, 0.5],
                 [0, 0, 0, 1, 1, 1]])

X, Y, Z, U, V, W = zip(*vecs)

vecs2 = np.array([[0, 0, 0, 0.5, 0.5, 0],
                  [0.5, 0.5, 0, -0.5, 0.5, 0.0],
                  [0.0, 1.0, 0, 0, 0, 0.5],
                  [0, 0.0, 0.0, 0, 1, 0.5]])
X2, Y2, Z2, U2, V2, W2 = zip(*vecs2)

cs = [[1, 0, 0, 1],
      [0, 1, 0, 1],
      [0, 0, 1, 1],
      [0, 0, 0, 1]]

C2 = cs[:] # shallow-copy
[(C2.append(x),C2.append(x)) for x in cs]

C = cs[:3]
[(C.append(x),C.append(x)) for x in cs[:3]]

fig = plt.figure(figsize=plt.figaspect(0.5))
ax = fig.add_subplot(1,2,1, projection='3d', title="fig 3. Basis Vectors")
ax.quiver(X[:3], Y[:3], Z[:3], U[:3], V[:3], W[:3], color=C)
ax.set_xlim([-0.51, 0.51])
ax.set_ylim([-0.21, 0.51])
ax.set_zlim([-0, 0.51])
ax = fig.add_subplot(1,2,2, projection='3d', title="fig 4. linear combination")
ax.quiver(X2, Y2, Z2, U2, V2, W2, color=C2)
ax.set_xlim([-0.1, 0.51])
ax.set_ylim([-0.1, 1.1])
ax.set_zlim([-0.1, 0.51])
plt.show()

이때 $\mathbf{I}$-공간1 상의 $\vec{v}$ 와 $\mathbf{A}$-공간 상의 $\vec{v}$는 다른 basis로 인해 다름을 알 수 있다. $\mathbf{A}$-공간 상에 다른 scalars로 조합할 벡터 $\vec{u}=\{2,0,2\}$를 쓰면 같은 벡터를 표현 할 수 있고 아래와 같다.

# pos, direction pairs
vecs = np.array([[0, 0, 0, 0.5, 0.5, 0],
                 [0, 0, 0, -0.5, 0.5, 0],
                 [0, 0, 0, 0.0, 0, 0.5],
                 [0, 0, 0, 1, 1, 1]])

X, Y, Z, U, V, W = zip(*vecs)

vecs2 = np.array([[0, 0, 0, 0.5, 0.5, 0],
                  [0.5, 0.5, 0, 0.5, 0.5, 0.0],
                  [1.0, 1.0, 0, 0.0, 0.0, 0.5],
                  [1.0, 1.0, 0.5, 0.0, 0.0, 0.5],
                  [0, 0.0, 0.0, 1, 1, 1]])
X2, Y2, Z2, U2, V2, W2 = zip(*vecs2)

cs = [[1, 0, 0, 1],
      [0, 1, 0, 1],
      [0, 0, 1, 1],
      [0, 0, 0, 1]]

C2 = [cs[0],cs[0],cs[2],cs[2],cs[3],
      cs[0],cs[0],cs[0],cs[0],
      cs[2],cs[2],cs[2],cs[2],
      cs[3],cs[3]]

C = cs[:3]
[(C.append(x),C.append(x)) for x in cs[:3]]

fig = plt.figure(figsize=plt.figaspect(0.5))
ax = fig.add_subplot(1,2,1, projection='3d', title="fig 3. Basis Vectors")
ax.quiver(X[:3], Y[:3], Z[:3], U[:3], V[:3], W[:3], color=C)
ax.set_xlim([-0.51, 0.51])
ax.set_ylim([-0.21, 0.51])
ax.set_zlim([-0, 0.51])
ax = fig.add_subplot(1,2,2, projection='3d', title="fig 5. linear combination")
ax.quiver(X2, Y2, Z2, U2, V2, W2, color=C2)
ax.set_xlim([-0.1, 1.1])
ax.set_ylim([-0.1, 1.1])
ax.set_zlim([-0.1, 1.1])
plt.show() 

즉 $\mathbf{A}\cdot\vec{u}=\mathbf{I}\cdot\vec{v}$와 같음을 알 수 있다.

$\begin{pmatrix} \frac{1}{2} & -\frac{1}{2} & 0 \\ \frac{1}{2} & \frac{1}{2} & 0 \\ 0 & 0 & \frac{1}{2} \\ \end{pmatrix}\cdot \begin{pmatrix} 2 \\ 0 \\ 2 \\ \end{pmatrix}= \begin{pmatrix} 1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \\ \end{pmatrix}\cdot \begin{pmatrix} 1 \\ 1 \\ 1 \\ \end{pmatrix}$

이렇듯 행렬은 어떤 basis를 제공해 임의의 vector space를 나타낼 수 있게 한다. 위의 경우, 다른 basis로 만들어진 공간에 같은 벡터를 나타낸 경우이다.

1.4 확인

A = np.array([[1/2, -1/2, 0],
              [1/2, 1/2, 0],
              [0,0,1/2]])
A @ [2,0,2]
array([1., 1., 1.])

2. 연관 글타래

작성중


1. 편의상 I의 basis로 이루어진 vector space를 I-공간이라 표기