본 내용은 MIT 18.065 강의 34 번의 일부 내용정리입니다. 교재는 page 257 입니다. 자세한 내용은 해당 강의를 참조하세요.
SVD 응용을 보자. 벡터 \(x_1,,,x_n\) 과 \(y_1,,,y_n\) 이 있다. 어떤 직교행렬 Q 가, y 하고 곱해서 가장 가까운 x 를 구할 수 있을까?
여기서는 translation 과 rescaling 을 허용하지 않는 제약된 상황이라고 가정하자. 이 문제를 Orthogonal Procrustes Problem 이라고 부른다.
해결하는 방법은 아래와 같다.
아래와 같이 4개의 도형에 대한 행렬을 준비한다. 그리고 어떤 행렬이 서로 가장 유사한지를 구한다. 회전만을 고려하며, 반영(reflection) 은 고려하지 않는다.
결론은, B와 C가 제일 유사하다.
행렬
좌표 그림은 https://www.geogebra.org/ 를 이용했습니다.
library(matrixcalc)
# 두 개 행렬을 입력받아, 얼마나 유사한지 정보를 frobenius norm 으로 반환한다.
my_procrustes_similar <- function(X1, Y1) {
# 평균을 빼서 중앙으로 맞춘다.
X <- X1 - rowMeans(X1)
Y <- Y1 - rowMeans(Y1)
# Y^T X 를 구한다.
YTX <- t(Y) %*% X
# YTX 의 SVD 를 구한다.
my_svd <- svd(YTX)
U <- my_svd$u
V <- my_svd$v
# Q를 구한다.
Q <- U %*% t(V)
# X - YQ 를 구한다.
result <- X - (Y %*% Q)
# 성분 제곱합에 대한 제곱근을 구한다.
round(frobenius.norm(result), 2)
}
# 행렬을 구축한다.
A <- matrix(c(1, 3, 3, 3, 3, 4), nrow=2, byrow=TRUE)
B <- matrix(c(4, 4, 6, 4, 3, 3), nrow=2, byrow=TRUE)
C <- matrix(c(1, 3, 3, 2, 2, 1), nrow=2, byrow=TRUE)
D <- matrix(c(4, 6, 5, 2, 2, 1), nrow=2, byrow=TRUE)
my_procrustes_similar(A, B) # A와 B를 비교한다.
## [1] 0.75
my_procrustes_similar(A, C) # A와 C를 비교한다.
## [1] 0.75
my_procrustes_similar(A, D) # A와 D를 비교한다.
## [1] 0.43
my_procrustes_similar(B, C) # B와 C를 비교한다.
## [1] 0