Vector Space


In [12]:
%matplotlib inline
%config InlineBackend.figure_formats = {'png', 'retina'}

import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
import matplotlib as mpl

1. vector length (norm)

$ \| a \| = \sqrt{a^T a } = \sqrt{a_1^2 + \cdots + a_K^2} $


In [7]:
import numpy as np
a = np.array([1, 1])
np.linalg.norm(a)


Out[7]:
1.4142135623730951

2. Unit Vector

길이가 1인 벡터 : $\dfrac{x}{\| x \|}$


In [8]:
a = np.array([1, 0])
b = np.array([0, 1])
c = np.array([1/np.sqrt(2), 1/np.sqrt(2)])
np.linalg.norm(a), np.linalg.norm(b), np.linalg.norm(c)


Out[8]:
(1.0, 1.0, 0.99999999999999989)

3. Sum of Vector

$ a = \begin{bmatrix}1 \\ 2\end{bmatrix} ,\;\; b = \begin{bmatrix}2 \\ 1\end{bmatrix} \;\;\; \rightarrow \;\;\; c = a + b = \begin{bmatrix}3 \\ 3\end{bmatrix} \;\; $

4. Decomposition of Vector

어떤 두 벡터 $a$, $b$의 합이 다른 벡터 $c$가 될 때 $c$가 두 벡터 성분(vector component) $a$, $b$으로 분해(decomposition)될 수 있다.


In [13]:
a = np.array([1, 2])
b = np.array([2, 1])
c = a + b

plt.annotate('', xy=a, xytext=(0,0), arrowprops=dict(facecolor='gray'))
plt.annotate('', xy=b, xytext=(0,0), arrowprops=dict(facecolor='gray'))
plt.annotate('', xy=c, xytext=(0,0), arrowprops=dict(facecolor='black'))

plt.plot(0, 0, 'ro', ms=10)
plt.plot(a[0], a[1], 'ro', ms=10)
plt.plot(b[0], b[1], 'ro', ms=10)
plt.plot(c[0], c[1], 'ro', ms=10)
plt.plot([a[0], c[0]], [a[1], c[1]], 'k--')
plt.plot([b[0], c[0]], [b[1], c[1]], 'k--')

plt.text(0.35, 1.15, "$a$", fontdict={"size": 18})
plt.text(1.15, 0.25, "$b$", fontdict={"size": 18})
plt.text(1.25, 1.45, "$c$", fontdict={"size": 18})

plt.xticks(np.arange(-2, 4))
plt.yticks(np.arange(-1, 4))
plt.xlim(-1.4, 4.4)
plt.ylim(-0.6, 3.8)
plt.show()


5. Orthogonal of Vector

두 벡터 $a$와 $b$가 이루는 각이 90도이면 서로 직교(orthogonal)라고 하며 $ a \perp b $로 표시한다.

서로 직교인 두 벡터의 벡터 내적(inner product, dot product)는 0이된다.

$ a^T b = b^T a = 0 \;\;\;\; \leftrightarrow \;\;\;\; a \perp b $

note
  • inner product : $x*y = x^T*y = \begin{bmatrix}3 & 1\end{bmatrix} \begin{bmatrix}2 \\ 4\end{bmatrix} = 3*2 + 1*4 = 10 $ (result is scala)

In [15]:
a = np.array([1, 1])
b = np.array([-1, 1])
np.dot(a, b)


Out[15]:
0

6. Projection of Vector

$ a^Tb = \| a \|\| b \|\cos\theta $

$ a^Tb = (a_1 + a_2)^Tb = a_1^Tb + a_2^Tb = a_2^Tb \;\; (a_1^Tb = 0,\; a_1\perp b) $

$ \| a_2 \| = a^T\dfrac{b}{\|b\|} = \dfrac{a^Tb}{\|b\|} = \dfrac{b^Ta}{\|b\|} $


In [52]:
a = np.array([1, 2])
b = np.array([2, 0])
c = np.array([1, 2])

plt.annotate('', xy=a, xytext=(0,0), arrowprops=dict(facecolor='black'))
plt.annotate('', xy=b, xytext=(0,0), arrowprops=dict(facecolor='black'))

plt.plot(1, 0, 'ro', ms=10)
plt.plot([1, 1], [0, 2], 'k--')
plt.plot([1, 1.2], [0.2, 0.2], "b")
plt.plot([1.2, 1.2], [0.2, 0], "b")

plt.text(0.85, 2.05, "$a$", fontdict={"size": 18})
plt.text(1.85, -0.35, "$b$", fontdict={"size": 18})
plt.text(1.10, 0.95, "$a1$", fontdict={"size": 18})
plt.text(0.50, -0.35, "$a2$", fontdict={"size": 18})

plt.xticks(np.arange(-1, 4))
plt.yticks(np.arange(-1, 4))
plt.show()


7. Straight Line of Vector

$f(x) = w^T(x - w) = w^Tx - w^Tw = w^Tx - \| w \|^2 = w^Tx - w_0 = 0$

example :

$ w = \begin{bmatrix}1 \\ 2\end{bmatrix} ,\;\; w_0 = 5 $

$ \begin{bmatrix}1 & 2\end{bmatrix} \begin{bmatrix}x_1 \\ x_2 \end{bmatrix} - 5 = x_1 + 2x_2 - 5 = 0 $

이면 벡터 $w$가 가리키는 점 (1, 2)를 지나면서 벡터 $w$에 수직인 선을 뜻한다.


In [53]:
w = np.array([1, 2])
x1 = np.array([3, 1])
x2 = np.array([-1, 3])
w0 = 5

plt.annotate('', xy=w, xytext=(0,0), arrowprops=dict(facecolor='red'))
plt.annotate('', xy=x1, xytext=(0,0), arrowprops=dict(facecolor='gray'))
plt.annotate('', xy=x2, xytext=(0,0), arrowprops=dict(facecolor='gray'))

plt.plot(0, 0, 'ro', ms=10)
plt.plot(w[0], w[1], 'ro', ms=10)
plt.plot(x1[0], x1[1], 'ro', ms=10)
plt.plot(x2[0], x2[1], 'ro', ms=10)
plt.plot([-3, 5], [4, 0], 'r-', lw=5)

plt.text(0.35, 1.15, "$w$", fontdict={"size": 18})
plt.text(1.55, 0.25, "$x_1$", fontdict={"size": 18})
plt.text(-0.9, 1.40, "$x_2$", fontdict={"size": 18})

plt.xticks(np.arange(-2, 4))
plt.yticks(np.arange(-1, 4))
plt.xlim(-1.7, 4.2)
plt.ylim(-0.5, 3.5)
plt.show()


8. Distance of between Line and Point

직선 $ w^Tx - w_0 = 0 $ 과 이 직선 위에 있지 않은 점 $x'$의 거리는 단위 벡터 $\dfrac{w}{\|w\|}$에 대한 $x'$의 투영에서 $\|w\|$를 뺀 값의 절대값이다. 따라서 다음과 같이 정리할 수 있다.

$ \left| \dfrac{w^Tx'}{\|w\|} - \|w\| \right| = \dfrac{\left|w^Tx' - \|w\|^2 \right|}{\|w\|}= \dfrac{\left|w^Tx' - w_0 \right|}{\|w\|} $

아래 그림에서 $w \;line$과 $x'$ 사이의 거리

$ w + w1 = \dfrac{w^Tx'}{\|w\|} $

$ w = \|w\| $

$ w1 = \dfrac{w^Tx'}{\|w\|} - \|w\| = \dfrac{w^Tx' - \|w\|^2}{\|w\|} $


In [113]:
w = np.array([1, 2])
w1 = np.array([2, 4])
w0 = 5

plt.annotate('', xy=w, xytext=(0,0), arrowprops=dict(facecolor='red'))
plt.annotate('', xy=w1, xytext=(1,2), arrowprops=dict(facecolor='blue'))

plt.plot(0, 0, 'ro', ms=10)
plt.plot(w[0], w[1], 'ro', ms=10)
plt.plot(0, 5, 'bo', ms=10)
plt.plot([-3, 5], [4, 0], 'r-', lw=5)
plt.plot([-3, 5], [6.5, 2.5], 'b-', lw=5)

plt.text(0.2, 1.15, "$w$", fontdict={"size": 18})
plt.text(5.2, 0, "$w\;line$", fontdict={"size": 18})
plt.text(1, 3, "$w1$", fontdict={"size": 18})
plt.text(-0.3, 4.5, "$x'$", fontdict={"size": 18})

plt.xticks(np.arange(-2, 6))
plt.yticks(np.arange(-1, 6))
plt.xlim(-1.7, 6.2)
plt.ylim(-0.5, 5.5)
plt.show()


9. Linearly Dependent & Linearly Independent

벡터들의 선형 조합이 0이 되는 모두 0이 아닌 스칼라값들이 존재하면 그 벡터들은 선형 종속(linearly dependent)이라고 한다.

$ a = \begin{bmatrix}1 \\ 2\end{bmatrix} ,\;\; b = \begin{bmatrix}3 \\ 3\end{bmatrix} \;\; c = \begin{bmatrix}10 \\ 14\end{bmatrix} \;\; $

$ 2a + b - \frac{1}{2}c = 0 $

벡터들의 선형 조합이 0이 되는 모두 0이 아닌 스칼라값들이 존재하지 않으면 그 벡터들은 선형 독립(linearly independent)이라고 한다.

$ \alpha_1 a_1 + \cdots + \alpha_K a_K = 0 \;\;\;\; \leftrightarrow \;\;\;\; \alpha_1 = \cdots = \alpha_K = 0 $


In [54]:
# Linearly Dependent
a = np.array([1, 2])
b = np.array([3, 3])
c = np.array([10, 14])
2*a + b - 0.5*c


Out[54]:
array([ 0.,  0.])

10. Basis Vector

벡터 공간에 속하는 벡터의 집합이 선형 독립이고 다른 모든 벡터 공간의 벡터들이 그 벡터 집합의 선형 조합으로 나타나면 그 벡터 집합을 벡터 공간의 기저 벡터(basis vector)라고 한다.

예를 들어 다음과 같은 두 벡터는 2차원 벡터 공간의 기저 벡터이다.

$ a = \begin{bmatrix}1 \\ 0\end{bmatrix} ,\;\; b = \begin{bmatrix}0 \\ 1\end{bmatrix} \;\; $

또는

$ a = \begin{bmatrix}1 \\ 1\end{bmatrix} ,\;\; b = \begin{bmatrix}2 \\ 3\end{bmatrix} \;\; $

다음과 같은 두 벡터는 2차원 벡터 공간의 기저 벡터가 될 수 없다.

$ a = \begin{bmatrix}1 \\ 2\end{bmatrix} ,\;\; b = \begin{bmatrix}2 \\ 4\end{bmatrix} \;\; $


In [56]:
# Linearly Dependent : No Basis Vector
a = np.array([1, 2])
b = np.array([2, 4])
2*a - b


Out[56]:
array([0, 0])

11. Column Space

행렬은 열 벡터의 집합으로 볼 수 있다. 이 때 열 벡터들의 조합으로 생성되는 벡터 공간을 열 공간(column space)이라고 한다.

$ A = \begin{bmatrix} 1 & 5 & 6 \\ 2 & 6 & 8 \\ 7 & 1 & 8 \end{bmatrix} \;\;\;\; \rightarrow \;\;\;\; \alpha_1 \begin{bmatrix} 1 \\ 2 \\ 7 \end{bmatrix} + \alpha_2 \begin{bmatrix} 5 \\ 6 \\ 1 \end{bmatrix} + \alpha_3 \begin{bmatrix} 6 \\ 8 \\ 8 \end{bmatrix} \; \in \; \text{column space} $

12. Column Rank

행렬의 열 벡터 중 서로 독립인 열 벡터의 최대 갯수를 열 랭크(column rank) 혹은 랭크(rank)라고 한다.

예를 들어 다음 행렬의 랭크는 2이다.

$ A = \begin{bmatrix} 1 & 5 & 6 \\ 2 & 6 & 8 \\ 3 & 11 & 14 \end{bmatrix} $

numpy의 linalg 서브 패키지의 matrix_rank 명령으로 랭크를 계산할 수 있다.


In [59]:
A = np.array([[1, 5, 6], [2, 6, 8], [3, 11, 14]])
np.linalg.matrix_rank(A)


Out[59]:
2

13. Coordinate

벡터의 성분, 즉 좌표(coordinate)는 표준 기저 벡터들에 대한 해당 벡터의 투영(projection)으로 볼 수 있다.

아래 좌표는 $(e_1, e_2) = (2,1)$ 이다.

  • 좌표계를 $(e_1, e_2)$로 정의 했으므로 $(1,2)$가 아니다.

In [115]:
e1 = np.array([1, 0])
e2 = np.array([0, 1])
a = np.array([1, 2])

plt.annotate('', xy=e1, xytext=(0,0), arrowprops=dict(facecolor='green'))
plt.annotate('', xy=e2, xytext=(0,0), arrowprops=dict(facecolor='green'))
plt.annotate('', xy=a, xytext=(0,0), arrowprops=dict(facecolor='gray'))

plt.plot(0, 0, 'ro', ms=10)
plt.plot(a[0], a[1], 'ro', ms=10)

plt.text(1.05, 1.35, "$a$", fontdict={"size": 18})
plt.text(-0.2, 0.5, "$e_1$", fontdict={"size": 18})
plt.text(0.5, -0.2, "$e_2$", fontdict={"size": 18})

plt.xticks(np.arange(-2, 4))
plt.yticks(np.arange(-1, 4))
plt.xlim(-1.5, 3.5)
plt.ylim(-0.5, 3)
plt.show()


14. Coordinate Transform

새로운 기저 벡터를에 대해 벡터 투영을 계산하는 것을 좌표 변환(coordinate transform)이라고 한다.

좌표 변환은 새로운 기저 벡터로 이루어진 변환 행렬(transform matrix) $A$ 와의 내적으로 계산한다.

$$ Aa' = a $$$$ a' = A^{-1}a $$

예를 들어, 기존의 기저 벡터가

$$ e_1 = \begin{bmatrix}1 \\ 0\end{bmatrix} ,\;\; e_2 = \begin{bmatrix}0 \\ 1\end{bmatrix} \;\; $$

이면 벡터 $a$는 사실

$$ a = \begin{bmatrix}2 \\ 2\end{bmatrix} = 2 \begin{bmatrix}1 \\ 0\end{bmatrix} + 2 \begin{bmatrix}0 \\ 1 \end{bmatrix} = 2 e_1 + 2 e_2 $$

새로운 기저 벡터가

$$ g_1 = \begin{bmatrix} \dfrac{1}{\sqrt{2}} \\ \dfrac{1}{\sqrt{2}} \end{bmatrix} ,\;\; g_2 = \begin{bmatrix} -\dfrac{1}{\sqrt{2}} \\ \dfrac{1}{\sqrt{2}} \end{bmatrix} ,\;\; $$

이면 벡터 $a$의 좌표는 다음과 같이 바뀐다.

$$ a = \begin{bmatrix}2 \\ 2\end{bmatrix} \;\;\;\; \rightarrow \;\;\;\; a' = A^{-1}a = \begin{bmatrix} e'_1 & e'_2 \end{bmatrix} a = \begin{bmatrix} \dfrac{1}{\sqrt{2}} & -\dfrac{1}{\sqrt{2}} \\ \dfrac{1}{\sqrt{2}} & \dfrac{1}{\sqrt{2}} \end{bmatrix}^{-1} \begin{bmatrix}2 \\ 2\end{bmatrix} = \begin{bmatrix} \dfrac{1}{\sqrt{2}} & \dfrac{1}{\sqrt{2}} \\ -\dfrac{1}{\sqrt{2}} & \dfrac{1}{\sqrt{2}} \end{bmatrix} \begin{bmatrix}2 \\ 2\end{bmatrix} = \begin{bmatrix}2\sqrt{2}\\0\end{bmatrix} $$

In [124]:
e1 = np.array([1, 0])
e2 = np.array([0, 1])
a = np.array([2, 2])
g1 = np.array([1, 1])/np.sqrt(2)
g2 = np.array([-1, 1])/np.sqrt(2)

plt.annotate('', xy=e1, xytext=(0,0), arrowprops=dict(facecolor='green'))
plt.annotate('', xy=e2, xytext=(0,0), arrowprops=dict(facecolor='green'))
plt.annotate('', xy=g1, xytext=(0,0), arrowprops=dict(facecolor='red'))
plt.annotate('', xy=g2, xytext=(0,0), arrowprops=dict(facecolor='red'))
plt.annotate('', xy=a, xytext=(0,0), arrowprops=dict(facecolor='gray', alpha=0.5))

plt.plot(0, 0, 'ro', ms=10)
plt.plot(a[0], a[1], 'ro', ms=10)

plt.text(1.05, 1.35, "$a$", fontdict={"size": 18})
plt.text(-0.2, 0.5, "$e_1$", fontdict={"size": 18})
plt.text(0.5, -0.2, "$e_2$", fontdict={"size": 18})
plt.text(0.2, 0.5, "$g_1$", fontdict={"size": 18})
plt.text(-0.6, 0.2, "$g_2$", fontdict={"size": 18})

plt.xticks(np.arange(-2, 4))
plt.yticks(np.arange(-1, 4))
plt.xlim(-1.5, 3.5)
plt.ylim(-0.5, 3)
plt.show()

# e1,e2 좌표계에서 g1,g2 좌표계로 변환
# a는 (2,2)에서 (2.82842712, 0)으로 변환됨
A = np.vstack([g1, g2]).T
Ainv = np.linalg.inv(A)
Ainv.dot(a)


Out[124]:
array([ 2.82842712,  0.        ])

In [ ]: