다운로드
작성자: admin 작성일시: 2016-06-16 23:33:11 조회수: 6146 다운로드: 302
카테고리: 기초 수학 태그목록:

선형대수와 해석기하의 기초

벡터의 기하학적 의미

$N$차원 벡터(vector) $a$는 $N$차원의 공간상에서

  • 벡터 $a$의 값으로 표시되는 점(point) 또는
  • 원점과 벡터 $a$의 값으로 표시되는 점을 연결한 화살표(arrow)

로 간주할 수 있다.

예를 들어 2차원 벡터 $a = [a_1 \;\; a_2]^T$ 는 2차원 상의 공간에서 $x$ 좌표가 $a_1$, $y$ 좌표가 $a_2$인 점, 또는 원점에서 이 점을 가리키는 화살표가 된다. 벡터를 화살표로 간주하는 경우에는 길이와 방향을 고정시킨채 평행 이동할 수 있다.

In:
a = np.array([1, 2])

plt.annotate('', xy=a, xytext=(0, 0), arrowprops=dict(facecolor='black'))
plt.plot(0, 0, 'kP', ms=20)
plt.plot(a[0], a[1], 'ro', ms=20)
plt.text(0.35, 1.15, "$a$", fontdict={"size": 18})
plt.text(1.15, 2.25, "$(1,2)$", fontdict={"size": 18})

plt.annotate('', xy=a + [-1, 1], xytext=(-1, 1),
             arrowprops=dict(facecolor='black'))
plt.text(-0.7, 2.1, "$a$", fontdict={"size": 18})

plt.xticks(np.arange(-2, 4))
plt.yticks(np.arange(-1, 4))
plt.xlim(-2.4, 3.4)
plt.ylim(-0.8, 3.4)
plt.show()

벡터의 길이

2차원 벡터 $a$의 길이는 피타고라스 정리를 이용하여 계산할 수 있으며 그 값은 벡터의 놈(norm) $\| a \|$이다. N차원 벡터의 길이도 마찬가지로 벡터 놈으로 정의한다.

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

numpy의 linalg 서브 패키지의 norm 명령으로 벡터의 길이를 계산할 수 있다.

In:
a = np.array([1, 2])
np.linalg.norm(a)
Out:
2.2360679774997898

스칼라와 벡터의 곱

양의 실수와 벡터를 곱하면 벡터의 방향은 변하지 않고 실수의 크기만큼 벡터의 길이가 커진다. 만약 음의 실수를 곱하면 벡터의 방향이 반대가 된다.

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

plt.annotate('', xy=b, xytext=(0,0), arrowprops=dict(facecolor='red'))
plt.text(0.8, 3.1, "$2a$", fontdict={"size": 18})
plt.text(2.2, 3.8, "$(2, 4)$", fontdict={"size": 18})

plt.annotate('', xy=a, xytext=(0,0), arrowprops=dict(facecolor='gray'))
plt.text(0.1, 1.3, "$a$", fontdict={"size": 18})
plt.text(1.1, 1.4, "$(1, 2)$", fontdict={"size": 18})

plt.plot(c[0], c[1], 'ro', ms=10)
plt.annotate('', xy=c, xytext=(0,0), arrowprops=dict(facecolor='blue'))
plt.text(-1.3, -0.8, "$-a$", fontdict={"size": 18})
plt.text(-3, -2.5, "$(-1, -2)$", fontdict={"size": 18})

plt.plot(0, 0, 'kP', ms=20)

plt.xticks(np.arange(-5, 6))
plt.yticks(np.arange(-5, 6))
plt.xlim(-4.4, 5.4)
plt.ylim(-3.2, 5.2)
plt.show()

단위 벡터

길이가 1인 벡터를 단위 벡터(unit vector)라고 한다. 예를 들어 다음과 같은 벡터들은 모두 단위 벡터이다.

$$ a = \begin{bmatrix}1 \\ 0\end{bmatrix} ,\;\; b = \begin{bmatrix}0 \\ 1\end{bmatrix} ,\;\; c = \begin{bmatrix} \dfrac{1}{\sqrt{2}} \\ \dfrac{1}{\sqrt{2}} \end{bmatrix} $$

임의의 벡터 $x$에 대해 다음 벡터는 벡터 $x$와 같은 방향을 가리키는 단위 벡터가 된다.

$$ \dfrac{x}{\| x \|} $$
In:
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:
(1.0, 1.0, 0.99999999999999989)

벡터의 합

벡터와 벡터의 합도 벡터가 된다. 이때 두 벡터의 합으로 만들어진 벡터의 위치는 두 벡터를 이웃하는 변으로 가지는 평행사변형의 다른 쪽 모서리의 위치가 된다.

$$ a = \begin{bmatrix}1 \\ 2\end{bmatrix} ,\;\; b = \begin{bmatrix}2 \\ 1\end{bmatrix} \;\;\; \rightarrow \;\;\; c = a + b = \begin{bmatrix}3 \\ 3\end{bmatrix} \;\; $$
In:
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, 'kP', 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, 5))
plt.yticks(np.arange(-1, 4))
plt.xlim(-1.4, 4.4)
plt.ylim(-0.6, 3.8)
plt.show()

또는 벡터를 방향과 길이가 고정된 화살표로 보고 더하고자 하는 벡터의 끝점이 차례대로 연결되도록 벡터를 평행 이동시켜 마지막 벡터가 가리키는 점으로 계산할 수도 있다.

In:
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=c, xytext=a, arrowprops=dict(facecolor='gray'))
plt.annotate('', xy=c, xytext=(0,0), arrowprops=dict(facecolor='black'))

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

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

plt.xticks(np.arange(-2, 5))
plt.yticks(np.arange(-1, 4))
plt.xlim(-1.4, 4.4)
plt.ylim(-0.6, 3.8)
plt.show()
In:
a = np.array([1, 2])
b = np.array([2, 1])
c = a + b

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

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

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

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

벡터의 차

벡터의 차 $a - b = c$는 벡터 $b$가 가리키는 점으로부터 벡터 $a$가 가리키는 점을 연결하는 벡터이다. 그 이유는 벡터 $b$에 벡터 $a-b$를 더하면, 즉 벡터 $b$와 벡터 $a-b$를 연결하면 벡터 $a$가 되어야 하기 때문이다.

$$ a - b = c $$$$ b + c = b + (a-b) = a $$
In:
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=a, xytext=b, arrowprops=dict(facecolor='black'))

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

plt.text(0.35, 1.15, "$a$", fontdict={"size": 18})
plt.text(1.15, 0.25, "$b$", fontdict={"size": 18})
plt.text(1.55, 1.65, "$a-b$", fontdict={"size": 18})

plt.xticks(np.arange(-2, 5))
plt.yticks(np.arange(-1, 4))
plt.xlim(-0.8, 2.8)
plt.ylim(-0.8, 2.8)
plt.show()

Word2Vec

추후 공부하게 될 word2vec을 이용하면 하나의 단어를 공간상의 벡터 하나로 표현할 수 있으며, 이 벡터들은 단어의 의미에 따라 다음처럼 평행사변형 관계를 가질 수도 있다.

woman = man + (queen - king)

queen - king은 king에서 queen으로 향하는 벡터이다. 즉 의미론적으로 king에서 국가 최고 권력자라는 의미는 남겨둔 채로 여성성을 추가하는 행위에 비유할 수 있다. 이러한 행위를 man에 대해서 한 결과가 man + (queen - king)이다. word2vec 학습 결과에서 이렇게 계산한 위치에 가장 가까이 있는 단어를 찾으면 woman이 된다.

In:
a = np.array([3, 4])
b = np.array([4, 3])
c = a + b

plt.annotate('', xy=a, xytext=(2,2), arrowprops=dict(facecolor='gray', ls="dashed"))
plt.annotate('', xy=(5,5), xytext=b, arrowprops=dict(facecolor='gray', ls="dashed"))

plt.plot(0, 0, 'kP', ms=10)
plt.plot(2, 2, '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.text(1.6, 1.6, "$king$", fontdict={"size": 18})
plt.text(2.5, 4.3, "$queen$", fontdict={"size": 18})
plt.text(4, 2.6, "$man$", fontdict={"size": 18})
plt.text(4.9, 5.1, "$woman$", fontdict={"size": 18})

plt.xticks(np.arange(-2, 7))
plt.yticks(np.arange(-1, 6))
plt.xlim(-1.4, 6.4)
plt.ylim(-0.6, 5.8)
plt.show()

유클리드 유사도

두 벡터가 가리키는 점의 거리를 구한 것을 유클리드 거리(Euclidean distance)라고 한다. 유클리드 거리가 작아질 수록 커지는 값을 정의할 수 있는데 이를 유클리드 유사도(Euclidean similarity)라고 한다.

두 벡터의 유클리드 거리는 벡터의 차의 길이로 구할 수 있다.

$$ \begin{eqnarray} \| a - b \|^2 &=& \sum_{i=1} (a_i - b_i)^2 \\ &=& \sum_{i=1} a_i^2 + \sum_{i=1} b_i^2 - 2 \sum_{i=1} a_i b_i \\ &=& \| a \|^2 + \| b \|^2 - 2 a^Tb \end{eqnarray} $$

벡터의 내적과 코사인 유사도

두 벡터의 내적은 다음처럼 벡터의 길이 $\|a\|$, $\|b\|$ 와 두 벡터 사이의 각도 $\theta$로 계산할 수도 있다.

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

$\cos\theta$는 $\theta$라는 각을 가지는 다음과 같은 직각 삼각형에서 빗변 $a$, 아랫변 $b$의 길이의 비율을 뜻한다.

$$ \cos\theta = \dfrac{b}{a} $$
In:
a = np.array([1, 2])
b = np.array([2, 0])
a2 = np.dot(a, b)/np.linalg.norm(b) * np.array([1, 0])

plt.annotate('', xy=a, xytext=(0,0), arrowprops=dict(fc='green'))
plt.annotate('', xy=a2, xytext=(0,0), arrowprops=dict(fc='green'))

plt.text(0.35, 1.15, "$a$", fontdict={"size": 18})
plt.text(0.50, -0.35, "$b$", fontdict={"size": 18})
plt.text(0.20, 0.125, r"$\theta$", fontdict={"size": 18})

plt.xticks(np.arange(-2, 4))
plt.yticks(np.arange(-1, 4))
plt.xlim(-1.1, 2.1)
plt.ylim(-0.5, 2.3)
plt.show()

이 값은 $\theta$가 0으로 가면 1이 되고 $\theta$가 90${}^{\circ}$로 가면 0이 된다. 함수의 그래프로 표현하면 다음과 같다.

In:
x = np.linspace(-2, 7, 100)
y = np.cos(x)
plt.plot(x, y)
plt.xticks([-np.pi/2, 0, np.pi/2, np.pi, 3*np.pi/2, 2*np.pi], 
           [r'$-90^{\circ}$', r'$0^{\circ}$', r'$90^{\circ}$', r'$180^{\circ}$', r'$270^{\circ}$', r'$360^{\circ}$'])
plt.xlabel(r"$\theta$")
plt.ylabel(r"$\cos\theta$")
plt.title(r"Graph of $\cos\theta$")
plt.show()