데이터 사이언스 스쿨 에서 공부한 내용입니다.
선형대수는 숫자 데이터의 계산에만 사용되는 것이 아니다. 직선과 화살표, 이미지 등을 다루는 기하학에서도 선형대수는 중요한 역할을 한다. 이 절에서는 선형대수를 기하학에서 어떻게 응용하고 선형대수의 연산이 기하학적으로 어떤 의미를 가지는지 알아본다.
차원 벡터 는 차원의 공간에서
벡터 의 값으로 표시되는 점(point) 또는
원점과 벡터 의 값으로 표시되는 점을 연결한 화살표(arrow)
라고 생각할 수 있다.
예를 들어 2차원 벡터
는 2차원 공간에서 좌표가 , 좌표가 인 점으로 생각할 수도 있고 또는 원점에서 이 점을 가리키는 화살표로 생각할 수도 있다. 벡터를 화살표로 생각하는 경우에는 길이와 방향을 고정시킨 채 평행이동할 수 있다.
(앞으로 나오는 그림은 모두 맷플롯리브 패키지로 그린 그림이다. 이 코드는 파이썬으로 이러한 그림도 제작할 수 있다는 것을 보이기 위한 것일 뿐 이번 절의 내용과는 관계없으므로 그림 코드의 내용은 무시해도 된다.)
import numpy as np
import matplotlib.pylab as plt
plt.rc("font", size=18) # 그림의 폰트 크기를 18로 고정
gray = {"facecolor": "gray"}
black = {"facecolor": "black"}
red = {"facecolor": "red"}
green = {"facecolor": "green"}
blue = {"facecolor": "blue"}
a = np.array([1, 2])
plt.plot(0, 0, 'kP', ms=20)
plt.plot(a[0], a[1], 'ro', ms=20)
plt.annotate('', xy=[-0.6, 1.6], xytext=(0.2, 0.7), arrowprops=gray)
plt.annotate('', xy=a, xytext=(0, 0), arrowprops=black)
plt.annotate('', xy=a + [-1, 1], xytext=(-1, 1), arrowprops=black)
plt.text(0.35, 1.15, "$a$")
plt.text(1.15, 2.25, "$(1,2)$")
plt.text(-0.7, 2.1, "$a$")
plt.text(-0.9, 0.6, "평행이동")
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()
벡터 의 길이는 놈(norm) 으로 정의한다.
넘파이 linalg 서브 패키지의 norm()
명령으로 벡터의 길이를 계산할 수 있다. 위에서 예로 든 2차원 벡터 의 길이는 이다.
a = np.array([1, 2])
np.linalg.norm(a)
2.23606797749979
양의 실수와 벡터를 곱하면 벡터의 방향은 변하지 않고 실수의 크기만큼 벡터의 길이가 커진다. 만약 음의 실수를 곱하면 벡터의 방향이 반대가 된다.
a = np.array([1, 2])
b = 2 * a
c = -a
plt.annotate('', xy=b, xytext=(0, 0), arrowprops=red)
plt.text(0.8, 3.1, "$2a$")
plt.text(2.2, 3.8, "$(2, 4)$")
plt.annotate('', xy=a, xytext=(0, 0), arrowprops=gray)
plt.text(0.1, 1.3, "$a$")
plt.text(1.1, 1.4, "$(1, 2)$")
plt.plot(c[0], c[1], 'ro', ms=10)
plt.annotate('', xy=c, xytext=(0, 0), arrowprops=blue)
plt.text(-1.3, -0.8, "$-a$")
plt.text(-3, -2.5, "$(-1, -2)$")
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 = 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)
(1.0, 1.0, 0.9999999999999999)
벡터와 벡터의 합도 벡터가 된다. 이때 두 벡터의 합은 그 두 벡터를 이웃하는 변으로 가지는 평행사변형의 대각선 벡터가 된다.
a = np.array([1, 2])
b = np.array([2, 1])
c = a + b
plt.annotate('', xy=a, xytext=(0, 0), arrowprops=gray)
plt.annotate('', xy=b, xytext=(0, 0), arrowprops=gray)
plt.annotate('', xy=c, xytext=(0, 0), arrowprops=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$")
plt.text(1.15, 0.25, "$b$")
plt.text(1.25, 1.45, "$c$")
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 = np.array([1, 2])
b = np.array([2, 1])
c = a + b
plt.annotate('', xy=a, xytext=(0, 0), arrowprops=gray)
plt.annotate('', xy=c, xytext=a, arrowprops=gray)
plt.annotate('', xy=c, xytext=(0, 0), arrowprops=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$")
plt.text(1.45, 2.45, "$b$")
plt.text(1.25, 1.45, "$c$")
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 = np.array([1, 2])
b = np.array([2, 1])
c = a + b
plt.annotate('', xy=b, xytext=(0, 0), arrowprops=gray)
plt.annotate('', xy=c, xytext=b, arrowprops=gray)
plt.annotate('', xy=c, xytext=(0, 0), arrowprops=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$")
plt.text(1.25, 0.25, "$b$")
plt.text(1.25, 1.45, "$c$")
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()
지금까지 벡터의 스칼라곱이 어떤 새로운 벡터가 되고 두 벡터의 합이 어떤 새로운 벡터가 되는지 살펴보았다. 여러 개의 벡터를 스칼라곱을 한 후 더한 것을 선형조합(linear combination)이라고 한다.
이 식에서 은 스칼라 계수다.
x1 = np.array([1, 2])
x2 = np.array([2, 1])
x3 = 0.5 * x1 + x2
plt.annotate('', xy=0.5*x1, xytext=(0, 0), arrowprops=gray)
plt.annotate('', xy=x2, xytext=(0, 0), arrowprops=gray)
plt.annotate('', xy=x3, xytext=(0, 0), arrowprops=black)
plt.plot(0, 0, 'kP', ms=10)
plt.plot(x1[0], x1[1], 'ro', ms=10)
plt.plot(x2[0], x2[1], 'ro', ms=10)
plt.plot(x3[0], x3[1], 'ro', ms=10)
plt.plot([x1[0], 0], [x1[1], 0], 'k--')
plt.text(0.6, 2.0, "$x_1$")
plt.text(-0.5, 0.5, "$0.5x_1$")
plt.text(1.15, 0.25, "$x_2$")
plt.text(2.5, 1.6, "$0.5x_1 + x_2$")
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()
벡터 , 가 다음과 같을 때, 가 다음 벡터와 같아지는 선형조합 계수 를 찾아라.
(힌트: 연립방정식의 해를 이용한다.)
(1)
(2)
✒️
import numpy as np
x = np.array([[1, 2], [2, 1]])
y1 = np.array([3, 1])
y2 = np.array([-1, -1])
c1 = np.linalg.solve(x, y1)
c2 = np.linalg.solve(x, y2)
c1, c2
벡터의 차 는 벡터 가 가리키는 점으로부터 벡터 가 가리키는 점을 연결하는 벡터다. 그 이유는 벡터 에 벡터 를 더하면, 즉 벡터 와 벡터 를 연결하면 벡터 가 되어야 하기 때문이다.
a = np.array([1, 2])
b = np.array([2, 1])
c = a - b
plt.annotate('', xy=a, xytext=(0, 0), arrowprops=gray)
plt.annotate('', xy=b, xytext=(0, 0), arrowprops=gray)
plt.annotate('', xy=a, xytext=b, arrowprops=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$")
plt.text(1.15, 0.25, "$b$")
plt.text(1.55, 1.65, "$a-b$")
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 방법을 이용하면 단어(word)를 공간에서 점 또는 벡터(vector)로 표현할 수 있다. word2vec으로 만들어진 벡터는 단어의 의미에 따라 다음처럼 평행사변형 관계를 가질 수 있다.
한국 - 서울
은 서울
에서 한국
으로 향하는 벡터다. 즉 의미론적으로 수도 이름을 나라 이름으로 바꾸는 행위(action) 에 비유할 수 있다. 이러한 행위를 도쿄
에 대해서 적용한 결과가 도쿄 + (한국 - 서울)
이다. word2vec 학습 결과에서 이렇게 계산한 위치에 가장 가까이 있는 단어를 찾으면 도쿄
가 나온다.
a = np.array([2, 2])
b = np.array([3, 4])
c = np.array([4, 1])
d = a + (c - a)
e = b + (c - a)
plt.annotate('', xy=b, xytext=a, arrowprops=black)
plt.annotate('', xy=e, xytext=d, arrowprops=black)
plt.annotate('', xy=c, xytext=[0, 0], arrowprops=gray)
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.text(1.6, 1.5, "서울")
plt.text(2.5, 4.3, "한국")
plt.text(3.5, 0.5, "도쿄")
plt.text(4.9, 3.2, "일본")
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()
남자배우, 여자배우, 남자, 여자, 이렇게 4가지 단어에 대응하는 4개의 벡터에 대해 위와 같은 관계가 성립한다고 가정하자. 다음 식을 완성하라.
남자배우 = 여자배우 + ?
✒️
배우라는 새로운 단어에 대응하는 벡터를 생각해보면
배우 = 남자배우 - 남자 = 여자배우 - 여자 라 할 수 있고 각 변에 남자를 더하면
남자배우 = 여자배우 - 여자 + 남자
위에서 살펴본 의 예시도 비슷하다.
(국가에서 수도를 빼는 것에 대응하는 벡터) = 일본 - 도쿄 = 한국 - 서울 에서 일본 벡터에 대해 정리하면 같은 결과가 얻어진다.
두 벡터가 가리키는 점 사이의 거리를 유클리드 거리(Euclidean distance) 라고 한다. 두 벡터의 유클리드 거리는 벡터의 차의 길이로 구할 수 있다.
벡터의 놈의 정의와 벡터의 차의 정의에서 유클리드 거리는 다음처럼 구한다.
즉,
두 벡터의 내적은 다음처럼 벡터의 길이 , 와 두 벡터 사이의 각도 의 코사인 함수값으로 계산할 수도 있다.
여기에서 는 코사인(cosine) 이라고 하는 함수이다. 코사인은 사인(sine)이라고 하는 함수와 함께 정의할 수 있다. 사인과 코사인을 합쳐서 삼각함수라고 한다.
사인 의 값은 라는 각을 가지는 직각 삼각형에서 빗변(hypotenuse)과 높이(opposite)의 비율을 뜻한다.
코사인 의 값은 라는 각을 가지는 직각 삼각형에서 빗변(hypotenuse)과 밑변(adjacent)의 비율을 뜻한다.
plt.plot([0, 1], [0, 2], 'k-', lw=3)
plt.plot([0, 1], [0, 0], 'k-', lw=3)
plt.plot([1, 1], [0, 2], 'k-', lw=3)
plt.text(0.05, 1, "빗변 h")
plt.text(0.35, -0.2, "밑변 b")
plt.text(1.05, 1, "높이 a")
plt.text(0.12, 0.06, r"$\theta$")
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()
의 값은 가 0에 가까워질수록 0에 가까워지고 가 에 가까워질수록 1에 가까워진다.
반대로 의 값은 가 0에 가까워질수록 1에 가까워지고 가 에 가까워질수록 0에 가까워진다.
함수의 그래프로 표현하면 다음과 같다.
x = np.linspace(0, np.pi/2, 100)
y1 = np.sin(x)
y2 = np.cos(x)
plt.plot(x, y1, 'r--', lw=3, label=r"$\sin\theta$")
plt.plot(x, y2, 'b-', lw=3, label=r"$\cos\theta$")
plt.legend()
plt.xticks([0, np.pi/4, np.pi/2], [r'$0^{\circ}$', r'$45^{\circ}$', r'$90^{\circ}$'])
plt.xlabel(r"$\theta$")
plt.title(r"$\sin\theta$와 $\cos\theta$의 그래프")
plt.show()
두 벡터 와 가 이루는 각이 90도이면 서로 직교(orthogonal) 라고 하며 로 표시한다.
이므로 서로 직교인 두 벡터의 내적은 0이 된다.
예를 들어 다음 두 벡터는 서로 직교한다.
a = np.array([1, 1])
b = np.array([-1, 1])
a @ b
0
(1) 다음 벡터에 대해 직교하는 단위벡터를 찾아라.
✒️
y = (0, 1), (0,-1)
(2) 다음 벡터에 대해 직교하는 단위벡터를 찾아라.
y = (1, -1), (-1,1)
(3) 다음 두 벡터에 대해 모두 직교하는 단위벡터를 찾아라.
z = (0, 0, 1), (0, 0, -1)
만약 개의 단위벡터 가 서로 직교하면 정규직교(orthonormal) 라고 한다.
직교하는 두 차원 벡터 에 대해 다음 식이 성립함을 보여라
✒️
좌변
우변
a, b 가 서로 직교하므로 두 벡터를 내적한 값은 0이다.
즉 좌변을 전개한 식에서 2, 3번째 항이 0이므로 우변과 같아진다.
일 때 이 식은 피타고라스의 정리가 된다.
정규직교하는 세 개의 3차원 벡터 로 이루어진 행렬 에 대해서 다음 등식이 성립함을 보여라.
(1)
✒️
정규직교이므로 자기 자신과의 내적은 1, 다른 벡터와의 내적은 0이다.
(2)
✒️
(3.1.31) 의 양변에 det을 취하면 V의 det 값이 0이 아니므로 역행렬이 존재하고
역행렬의 정의에 의해 (3.1.32)가 얻어진다.
두 벡터의 방향이 비슷할수록 벡터가 비슷하다고 간주하여 두 벡터 사이의 각의 코사인값을 코사인 유사도(cosine similarity) 라고 한다. 코사인값은 각도가 0일때 가장 커지므로 두 벡터가 같은 방향을 가리키고 있으면 코사인 유사도가 최댓값 1을 가진다.
코사인 유사도는 나중에 공부할 추천시스템(recommender system)에서 사용자의 취향이 얼마나 비슷한지를 계산할 때 사용된다. 코사인 유사도를 이용하면 다음처럼 코사인 거리(cosine distance) 도 정의할 수 있다.
a, b, c, 3명의 사용자가 4개의 영화에 준 평점을 다음처럼 벡터로 표현하였다.
(1) a, b, c 사이의 유클리드 거리를 구하라. 어느 두 사용자가 가장 가까운가? 또 어느 두 사용자가 가장 멀리 떨어져 있는가?
(2) a, b, c 사이의 코사인 거리를 구하라. 어느 두 사용자가 가장 가까운가? 또 어느 두 사용자가 가장 멀리 떨어져 있는가?
✒️
import numpy as np
a = np.array([4, 5, 2, 2])
b = np.array([4, 0, 2, 0])
c = np.array([2, 2, 0, 1])
def u_dist(x, y):
return np.linalg.norm(x - y)
def cos_dist(x, y):
return 1 - (x @ y) / (np.linalg.norm(x) * np.linalg.norm(y))
print("{}와 {} 사이의 유클리드 거리:{}".format('a', 'b', u_dist(a, b)))
print("{}와 {} 사이의 유클리드 거리:{}".format('a', 'c', u_dist(a, c)))
print("{}와 {} 사이의 유클리드 거리:{}".format('b', 'c', u_dist(b, c)))
print("{}와 {} 사이의 코사인 거리:{}".format('a', 'b', cos_dist(a, b)))
print("{}와 {} 사이의 코사인 거리:{}".format('a', 'c', cos_dist(a, c)))
print("{}와 {} 사이의 코사인 거리:{}".format('b', 'c', cos_dist(b, c)))
a와 b 사이의 유클리드 거리:5.385164807134504 a와 c 사이의 유클리드 거리:4.242640687119285 b와 c 사이의 유클리드 거리:3.605551275463989 a와 b 사이의 코사인 거리:0.36112343500006017 a와 c 사이의 코사인 거리:0.04761904761904767 b와 c 사이의 코사인 거리:0.40371520600005606
유클리드 거리: b, c가 가장 가깝다. a, b가 가장 멀다.
코사인 거리: a, c가 가장 가깝다. b, c가 가장 멀다.
어떤 두 벡터 , 의 합이 다른 벡터 가 될 때 가 두 벡터 성분(component) , 으로 분해(decomposition) 된다고 말한다.
다음 벡터를 두 개의 벡터로 분해하는 방법을 두 가지 이상 찾고 평면 위에 각각 화살표로 표기하라.
✒️
x = (1, 0) = (1, 1) + (0, -1) # red line
x = (1, 0) = (1, -1) + (0, 1) # blue line
import matplotlib.pylab as plt
plt.arrow(0,0,1,0, head_width=0.05, head_length=0.1)
plt.arrow(0,0,1,1, head_width=0.05, head_length=0.1, color='r')
plt.arrow(1,1,0,-1, head_width=0.05, head_length=0.1, color='r')
plt.arrow(0,0,1,-1, head_width=0.05, head_length=0.1, color='b')
plt.arrow(1,-1,0,1, head_width=0.05, head_length=0.1, color='b')
plt.show()
벡터 를 다른 벡터 에 직교하는 성분과 벡터 에 평행한 성분으로로 분해할 수 있는데, 평행한 성분을 벡터 에 대한 투영성분(projection), 벡터 에 직교하는 성분을 벡터 에 대한 직교성분(rejection) 이라고 하며 각각 다음과 같이 표기한다.
투영성분의 길이는 다음처럼 구할 수 있다.
만약 벡터 자체가 이미 단위벡터이면 단위벡터에 대한 투영길이는 내적이 된다.
투영성분 성분 벡터는 투영성분 길이와 벡터 방향의 단위벡터의 곱이다.
직교성분 벡터는 원래의 벡터에서 투영성분 성분 벡터를 뺀 나머지다.
a = np.array([1, 2])
b = np.array([2, 0])
a2 = (a @ b) / np.linalg.norm(b) * np.array([1, 0])
a1 = a - a2
plt.annotate('', xy=b, xytext=(0, 0), arrowprops=green)
plt.annotate('', xy=a2, xytext=(0, 0), arrowprops=blue)
plt.annotate('', xy=a1, xytext=(0, 0), arrowprops=blue)
plt.annotate('', xy=a, xytext=(0, 0), arrowprops=red)
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$")
plt.text(1.55, 0.15, "$b$")
plt.text(-0.5, 1.05, "$a^{\perp b}$")
plt.text(0.50, 0.15, "$a^{\Vert b}$")
plt.xticks(np.arange(-10, 10))
plt.yticks(np.arange(-10, 10))
plt.xlim(-1.2, 4.1)
plt.ylim(-0.5, 3.2)
plt.show()
일 때, 투영성분 , 직교성분 를 구하라.
✒️
import numpy as np
def decomp(x, y):
projection = ((x @ y) / (np.linalg.norm(y))**2) * y
rejection = x - projection
return projection, rejection
a = np.array([1,2])
b = np.array([2,0])
decomp(a, b)
(array([1., 0.]), array([0., 2.]))
만약 가 원점을 지나는 직선의 방향을 나타내는 단위벡터라고 하자. 이때 그 직선 위에 있지 않는 어떤 점 와 그 직선과의 거리의 제곱이 다음과 같음을 증명하라.
✒️
를 와 평행한 성분과 수직인 성분으로 분해하면 직선과의 거리의 제곱은 의 크기의 제곱과 같다. 는 단위벡터이므로 이므로
이고
v = np.array([2, 1]) / np.sqrt(5)
x = np.array([1, 3])
plt.plot(0, 0, 'kP', ms=10)
plt.annotate('', xy=v, xytext=(0, 0), arrowprops=black)
plt.plot([-2, 8], [-1, 4], 'b--', lw=2)
plt.plot([1, 2], [3, 1], 'g:', lw=2)
plt.plot(x[0], x[1], 'ro', ms=10)
plt.text(0.1, 0.5, "$v$")
plt.text(0.6, 3.2, "$x$")
plt.xticks(np.arange(-3, 15))
plt.yticks(np.arange(-1, 5))
plt.xlim(-3, 7)
plt.ylim(-1, 5)
plt.show()
어떤 벡터 가 있을 때
원점에서 출발한 벡터 가 가리키는 점을 지나면서
벡터 에 수직인
직선의 방정식을 구해보자.
위 두 조건을 만족하는 직선 상의 임의의 점을 가리키는 벡터를 라고 하면, 벡터 가 가리키는 점과 벡터 가 가리키는 점을 이은 벡터 는 조건에 따라 벡터 와 직교해야 한다. 따라서 다음 식이 성립한다.
정리하면 다음과 같아진다.
이 직선과 원점 사이의 거리는 벡터 의 놈 이다.
w = np.array([1, 2])
x1 = np.array([3, 1])
x2 = np.array([-1, 3])
plt.annotate('', xy=w, xytext=(0, 0), arrowprops=black)
plt.annotate('', xy=x1, xytext=(0, 0), arrowprops=green)
plt.annotate('', xy=x2, xytext=(0, 0), arrowprops=green)
plt.plot(0, 0, 'kP', 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.2, 1.5, "벡터 $w$")
plt.text(1.55, 0.25, "$x_1$")
plt.text(-0.9, 1.40, "$x_2$")
plt.text(1.8, 1.8, "$x_1 - w$")
plt.text(-0.2, 2.8, "$x_2 - w$")
plt.text(3.6, 0.8, "직선 $x$")
plt.xticks(np.arange(-2, 5))
plt.yticks(np.arange(-1, 5))
plt.xlim(-2, 5)
plt.ylim(-0.6, 3.6)
plt.show()
예를 들어
일 때
이 방정식은 벡터 가 가리키는 점 를 지나면서 벡터 에 수직인 직선을 뜻한다. 이 직선과 원점 사이의 거리는 이다.
이번에는 벡터 가 가리키는 점을 지나야 한다는 조건을 없애고 단순히
직선 의 방정식을 구해보자.
이때는 직선이 가 아니라 와 방향이 같고 길이가 다른 벡터 을 지날 것이다. 는 양의 실수이다.
위에서 했던 방법으로 다시 직선의 방정식을 구하면 다음과 같다.
여기에서 는 임의의 수가 될 수 있으므로 단순히 벡터 에 수직인 직선의 방정식은 다음과 같이 나타낼 수 있다.
이 직선과 원점 사이의 거리는 다음과 같다.
w = np.array([1, 2])
plt.annotate('', xy=w, xytext=(0, 0), arrowprops=gray)
plt.annotate('', xy=0.5 * w, xytext=(0, 0), arrowprops=black)
plt.plot(0, 0, 'kP', ms=10)
plt.plot(0.5 * w[0], 0.5 * w[1], 'ro', ms=10)
plt.plot([-2, 5], [2.25, -1.25], 'r-', lw=5)
plt.text(-0.7, 0.8, "벡터 $cw$")
plt.text(-0.1, 1.6, "벡터 $w$")
plt.text(1, 1, "직선 $x$")
plt.xticks(np.arange(-2, 5))
plt.yticks(np.arange(-1, 5))
plt.xlim(-2, 5)
plt.ylim(-0.6, 3.6)
plt.show()
예를 들어 이면 벡터 에 수직이고 원점으로부터의 거리가 인 직선이 된다.
직선 과 원점 사이의 거리가 다음과 같다는 것을 증명하라.
✒️
주어진 직선에서 라 하면 이므로
해당 직선은 가 가르키는 점을 지나며 w에 수직인 직선을 의미하고
이 때 원점에서 직선까지의 거리는 이다.
이번에는 직선 과 이 직선 위에 있지 않은 점 사이의 거리를 구해보자.
벡터 에 대한 벡터 의 투영성분 의 길이는 다음과 같다.
직선과 점 사이의 거리는 이 길이에서 원점에서 직선까지의 거리 를 뺀 값의 절댓값이다.
직선의 방정식이 이면 직선과 점의 거리는 다음과 같다.
이 공식은 나중에 분류 방법의 하나인 서포트 벡터 머신(SVM: Support Vector Machine)에서 사용된다.
직선의 방정식이 이면 직선과 점의 거리는 다음과 같다는 것을 증명하라.
✒️
w = np.array([1, 2])
x1 = np.array([4, 3])
x2 = np.array([1, 2]) * 2
plt.annotate('', xy=x1, xytext=(0, 0), arrowprops=gray)
plt.annotate('', xy=x2, xytext=(0, 0), arrowprops=gray)
plt.annotate('', xy=w, xytext=(0, 0), arrowprops=red)
plt.plot(0, 0, 'kP', ms=10)
plt.plot(w[0], w[1], 'ro', ms=10)
plt.plot(x1[0], x1[1], 'ro', ms=10)
plt.plot([-3, 7], [4, -1], 'r-', lw=5)
plt.plot([2, 4], [4, 3], 'k:', lw=2)
plt.plot([3, 4], [1, 3], 'k:', lw=2)
plt.text(0.1, 0.9, "$w$")
plt.text(4.2, 3.1, "$x'$")
plt.text(1.5, 2.4, "$x'^{\Vert w}$")
plt.xticks(np.arange(-3, 15))
plt.yticks(np.arange(-1, 5))
plt.xlim(-3, 7)
plt.ylim(-1, 5)
plt.show()