다차원 벡터 사이의 각도
두 벡터 \(\vec{u}\) 와 \(\vec{v}\) 사이의 각도
두 \(n\)-차원 벡터 \(\vec{u}\) 와 \(\vec{v}\) 의 내적은 다음과 같습니다.
\[\vec{u} \cdot \vec{v} = u_1 v_1 + u_2 v_2 + \cdots + u_n v_n\]
그리고 두 벡터 사이의 각도는 다음의 코사인 2법칙을 활용하여 구할 수 있습니다.
코사인 제 2법칙은 다음과 같습니다.
\[|\vec{w}|^2 = |\vec{u}|^2 + |\vec{v}|^2 – 2|\vec{u}||\vec{v}| \cos\theta\]
이 법칙은 피타고라스 정리(\(|\vec{w}|^2=|\vec{u}|^2+|\vec{v}|^2\))의 일반화된 형식으로 피타고라스 법칙은 빗변의 상대각이 직각인 경우에만 사용할 수 있지만, 코사인 제 2법칙은 어떤 각도에 대해서도 사용할 수 있습니다. (\(\vec{w}\) 는 \(\vec{u}-\vec{v}\) 또는 \(\vec{v}-\vec{u}\) 입니다.)
사실 2차원에서는 각도란 눈에 보이기 때문에 그 의미를 정확하게 파악할 수 있지만 고차원 상의 두 벡터에 대해 각도를 상상하는 것은 직관적으로 쉽게 다가오지 않을 수 있습니다. 하지만 \(n\)-차원 상의 한 벡터 \(\vec{v}\) 의 길이를 \(\sqrt{v_1^2 + v_2^2 + \cdots + v_n^2}\) 라고 할 때, 두 벡터를 포함하는 2차원 평면을 상상한다면, 이 평면 상에서도 위의 코사인 법칙이 성립할 것이고, 따라서 고차원 공간 속의 두 벡터에 대해서도 각도를 구할 수 있게 됩니다.
다차원 공간 속의 두 벡터의 각도는 이런 식으로 2차원 상의 각도 개념을 확장시킨 것으로 생각하면 됩니다.
위의 식을 풀면 두 벡터 \(\vec{u}\), \(\vec{v}\) 의 사이각은 다음과 같습니다.
\[\theta = \cos^{-1}\left(\frac{|\vec{u}|^2+|\vec{v}|^2-|\vec{w}|^2}{2|\vec{u}||\vec{v}|}\right)\]
이를 각 벡터의 성분으로 표현한다면 다음과 같습니다. (\(\vec{w} = \vec{u}-\vec{v}\))
\[\theta = \cos^{-1}\left(\frac{\sum{u_i^2}+\sum{v_i^2}-\sum(u_i-v_i)^2}{2\sqrt{\sum{u_i^2}}\sqrt{\sum{v_i^2}}}\right)\]
그리고 이를 잘 정리하면 다음과 같은 식을 얻을 수 있습니다.
\[\theta = \cos^{-1}\left(\frac{\sum{u_i v_i}}{\sqrt{\sum{u_i^2}}\sqrt{\sum{v_i^2}}}\right)\]
이를 R에서 계산한다면 다음과 같이 할 수 있습니다.
R로 구현하는 두 벡터 사이의 각도
u = c(1,3,2,4,7)
v = c(2,-1,4,3,0)
# inner product
sum(u*v)
## [1] 19
u %*% v
## [,1] ## [1,] 19
# angle
acos(sum(u*v)/(sqrt(sum(u*u))*sqrt(sum(v*v))))
## [1] 1.169858
라디안을 도로 바꾸려면 \(\times180/\pi\) 를 해주면 된다.
rad = acos(sum(u*v)/(sqrt(sum(u*u))*sqrt(sum(v*v))))
deg = rad * 180 / pi
deg
## [1] 67.0279
예제: 30 차원 상의 두 벡터 사이 각도
u = rnorm(30)
v = 2* rnorm(30)
# angle
rad = acos(sum(u*v)/(sqrt(sum(u*u))*sqrt(sum(v*v))))
deg = rad * 180 / pi
rad
## [1] 1.807722
deg
## [1] 103.5748
생각해볼 거리: 고차원 상의 두 무작위 벡터 사이 각도
고차원에 대해 알려진 사실의 하나는 고차원 상의 두 무작위 벡터는 차원이 높아질 수록 \(90^\circ\) 에 가까울 가능성이 크다는 것입니다. 다음의 그래프는 이를 보여주고 있습니다. 3차원 상의 무작위 벡터 사이 각도는 다소 골고루 분포되어 있다면 100차원 상의 두 무작위 벡터 사이의 각도는 대부분 \(90^\circ\) 에 가깝습니다. 이를 보통 고차원이 될 수록 어떤 한 방향에 대해 직각의 방향이 많기 때문이라고 설명합니다.
deg = data.frame(n=rep(c(3,10,100),1000), i=rep(1:1000,3), deg=NA)
for (n in c(3,10,100)) {
for (i in 1:1000) {
u = rnorm(n)
v = 2* rnorm(n)
rad = acos(sum(u*v)/(sqrt(sum(u*u))*sqrt(sum(v*v))))
deg[deg$n==n & deg$i == i, "deg"] = rad * 180 / pi
#deg[j, "deg"] = rad * 180 / pi
}
}
library(ggplot2)
ggplot(data=deg, aes(x=deg)) + geom_histogram() + facet_wrap(~n) + geom_vline(xintercept=90, linetype='dotted')
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
이상으로 고차원 상의 두 벡터 사이 각도를 구하는 방법을 알아보았습니다.
Leave a comment