행렬 연산
R에서 하는 벡터/행렬 연산
- R에서는 여러 벡터/행렬 연산을 지원한다. 여기서는 이들의 사용방법을 알아본다.
목차
- 벡터연산
- 두 벡터의 내적 \(\vec{a} \cdot \vec{b}\)
- 두 벡터의 외적(Cross product) \(\vec{a} \times \vec{b}\)
- 두 벡터의 외적(Outer product) \(a b^T\)
- 한 행렬 연산
- 크기 \(n\) 의 단위 행렬 \(I_n\)
- 대각행렬 \(A\), \(A_{ij} = 0 (i \neq j)\)
- 행렬 \(A\) 의 대각원소 \(A_{ii}\)
- 행렬 \(A\) 의 전치행렬 \(A^T(A’)\)
- 행렬 \(A\) 의 대각합 \(tr(A)\)
- 두 행렬의 연산
- 곱 \(AB\)
- 아다마르 곱 \(A \circ B\)
- 크로네커 곱 \(A \otimes B\)
- 직접합 \(A \oplus B\)
- 선형(행렬) 대수
- 행렬식 \(Ax=b\) 의 해
- 역행렬 \(A^{-1}\)
- 일반화역행렬 \(A^{+}\)
- 계수 \(rank(A)\)
- 행렬식 \(|A|, \text{det}(A)\)
- QR 분해 \(A = QR, Q Q^T = Q^T Q = I_n, R_{ij} = 0(i>j)\)
- 양의 정부호행렬(정칙행렬) \(\forall \vec{x}, \vec{x}^T A \vec{x} > 0 ?\)
- 고유값, 고유벡터 \(A\vec{v} = \lambda \vec{v}\)
- 특이값 분해 \(A = U \Sigma V^T, A : (m \times n)-\text{행렬}, \Sigma_{ij}=0(i \neq j), U^T U = I_m, V^T V = I_n\)
벡터 연산
a = c(1, 5, -2)
b = c(3, -1, 7)
두 벡터의 내적 : dot(a,b)
\[ \vec{a} \cdot \vec{b} \]
pracma::dot(a, b) # 두 벡터의 내적
## [1] -16
sum(a*b)
## [1] -16
두 벡터의 외적(Cross product) : cross(a,b)
\[ \vec{a} \times \vec{b} \]
pracma::cross(a,b) # 두 벡터의 외적(cross product)
## [1] 33 -13 -16
두 벡터의 외적(Outer product) : outer(a,b)
outer(a,b); a %o% b # 두 벡터의 외적(outer product)
## [,1] [,2] [,3] ## [1,] 3 -1 7 ## [2,] 15 -5 35 ## [3,] -6 2 -14
## [,1] [,2] [,3] ## [1,] 3 -1 7 ## [2,] 15 -5 35 ## [3,] -6 2 -14
a %*% t(b); tcrossprod(a, b)
## [,1] [,2] [,3] ## [1,] 3 -1 7 ## [2,] 15 -5 35 ## [3,] -6 2 -14
## [,1] [,2] [,3] ## [1,] 3 -1 7 ## [2,] 15 -5 35 ## [3,] -6 2 -14
-
외적이 cross product 또는 outer product로 번역됨을 유의하자. 벡터 외적(vector product)라고도 불리는 외적(cross product)의 경우, 두 삼차원 벡터의 외적은 삼차원 벡터이다. 반면 두 삼차원 벡터의 외적(outer product)는 행렬이다.
-
만약 벡터를 열벡터(열이 하나인 행렬)로 나타내면 외적은 \(a b^T\) 이고, 내적은 \(a^T b\) 이 된다.
벡터가 행렬로 변환될 때에는 열벡터(열이 하나인 행렬)이 된다.
as.matrix(a)
## [,1] ## [1,] 1 ## [2,] 5 ## [3,] -2
t(a)
## [,1] [,2] [,3] ## [1,] 1 5 -2
한 행렬 함수
A = matrix(c(1,3,-2, 5, 7, -3, 1, 0, 1), 3, 3)
B = matrix(c(5,2,-1,0,7,-2,3,-5,1), 3, 3)
크기 n
의 단위 행렬 : diag(n)
\[ I_n \]
diag(2)
## [,1] [,2] ## [1,] 1 0 ## [2,] 0 1
diag(4)
## [,1] [,2] [,3] [,4] ## [1,] 1 0 0 0 ## [2,] 0 1 0 0 ## [3,] 0 0 1 0 ## [4,] 0 0 0 1
대각 원소가 c(d1, d2, d3)
인 대각행렬 : diag(c(d1, d2, d3))
\[ A_{ij} = 0 (i \neq j) \]
diag(c(1,-1))
## [,1] [,2] ## [1,] 1 0 ## [2,] 0 -1
diag(c(2,5,3,1))
## [,1] [,2] [,3] [,4] ## [1,] 2 0 0 0 ## [2,] 0 5 0 0 ## [3,] 0 0 3 0 ## [4,] 0 0 0 1
행렬 A
의 대각원소 : diag(A)
\[ A_{ii} \]
A; diag(A)
## [,1] [,2] [,3] ## [1,] 1 5 1 ## [2,] 3 7 0 ## [3,] -2 -3 1
## [1] 1 7 1
B; diag(B)
## [,1] [,2] [,3] ## [1,] 5 0 3 ## [2,] 2 7 -5 ## [3,] -1 -2 1
## [1] 5 7 1
전치 행렬 : t(A)
\[ A^T \]
A; t(A)
## [,1] [,2] [,3] ## [1,] 1 5 1 ## [2,] 3 7 0 ## [3,] -2 -3 1
## [,1] [,2] [,3] ## [1,] 1 3 -2 ## [2,] 5 7 -3 ## [3,] 1 0 1
B; t(B)
## [,1] [,2] [,3] ## [1,] 5 0 3 ## [2,] 2 7 -5 ## [3,] -1 -2 1
## [,1] [,2] [,3] ## [1,] 5 2 -1 ## [2,] 0 7 -2 ## [3,] 3 -5 1
대각합 : matrix.trace(A)
\[ tr(A) \]
# matrix.trace(A)와 sum(diag(A))의 차이는
# matrix.trace(A)는 행렬 A가 정방행렬인지 먼저 확인한다.
A; matrixcalc::matrix.trace(A); sum(diag(A))
## [,1] [,2] [,3] ## [1,] 1 5 1 ## [2,] 3 7 0 ## [3,] -2 -3 1
## [1] 9
## [1] 9
A2 <- cbind(A, c(1,2,1))
A2; matrixcalc::matrix.trace(A2); sum(diag(A2))
## [,1] [,2] [,3] [,4] ## [1,] 1 5 1 1 ## [2,] 3 7 0 2 ## [3,] -2 -3 1 1
## Error in matrixcalc::matrix.trace(A2): argument x is not a square matrix
## [,1] [,2] [,3] [,4] ## [1,] 1 5 1 1 ## [2,] 3 7 0 2 ## [3,] -2 -3 1 1
## [1] 9
두 행렬의 연산
두 행렬의 곱 : A %*% B
\[ AB \]
A; B; A %*% B
## [,1] [,2] [,3] ## [1,] 1 5 1 ## [2,] 3 7 0 ## [3,] -2 -3 1
## [,1] [,2] [,3] ## [1,] 5 0 3 ## [2,] 2 7 -5 ## [3,] -1 -2 1
## [,1] [,2] [,3] ## [1,] 14 33 -21 ## [2,] 29 49 -26 ## [3,] -17 -23 10
두 행렬의 아다마르 곱 : A * B
\[ A \circ B \]
A; B; A * B
## [,1] [,2] [,3] ## [1,] 1 5 1 ## [2,] 3 7 0 ## [3,] -2 -3 1
## [,1] [,2] [,3] ## [1,] 5 0 3 ## [2,] 2 7 -5 ## [3,] -1 -2 1
## [,1] [,2] [,3] ## [1,] 5 0 3 ## [2,] 6 49 0 ## [3,] 2 6 1
두 행렬의 크로네커 곱 : A %x% B
\[ A \otimes B \]
A; B; A %x% B
## [,1] [,2] [,3] ## [1,] 1 5 1 ## [2,] 3 7 0 ## [3,] -2 -3 1
## [,1] [,2] [,3] ## [1,] 5 0 3 ## [2,] 2 7 -5 ## [3,] -1 -2 1
## [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] ## [1,] 5 0 3 25 0 15 5 0 3 ## [2,] 2 7 -5 10 35 -25 2 7 -5 ## [3,] -1 -2 1 -5 -10 5 -1 -2 1 ## [4,] 15 0 9 35 0 21 0 0 0 ## [5,] 6 21 -15 14 49 -35 0 0 0 ## [6,] -3 -6 3 -7 -14 7 0 0 0 ## [7,] -10 0 -6 -15 0 -9 5 0 3 ## [8,] -4 -14 10 -6 -21 15 2 7 -5 ## [9,] 2 4 -2 3 6 -3 -1 -2 1
두 행렬의 직접합 : matrixcalc::direct.sum(A, B)
\[ A \oplus B \]
A; B; matrixcalc::direct.sum(A, B)
## [,1] [,2] [,3] ## [1,] 1 5 1 ## [2,] 3 7 0 ## [3,] -2 -3 1
## [,1] [,2] [,3] ## [1,] 5 0 3 ## [2,] 2 7 -5 ## [3,] -1 -2 1
## [,1] [,2] [,3] [,4] [,5] [,6] ## [1,] 1 5 1 0 0 0 ## [2,] 3 7 0 0 0 0 ## [3,] -2 -3 1 0 0 0 ## [4,] 0 0 0 5 0 3 ## [5,] 0 0 0 2 7 -5 ## [6,] 0 0 0 -1 -2 1
선형대수(행렬대수)
$Ax=b$의 해 : solve(A, b)
\[ Ax = b \]
A; b=c(2,-1,1)
## [,1] [,2] [,3] ## [1,] 1 5 1 ## [2,] 3 7 0 ## [3,] -2 -3 1
x = solve(A, b)
near(A %*% x, b)
## [,1] ## [1,] TRUE ## [2,] TRUE ## [3,] TRUE
역행렬 : solve(A)
\[ A^{-1} \]
A; solve(A)
## [,1] [,2] [,3] ## [1,] 1 5 1 ## [2,] 3 7 0 ## [3,] -2 -3 1
## [,1] [,2] [,3] ## [1,] -2.333333 2.666667 2.333333 ## [2,] 1.000000 -1.000000 -1.000000 ## [3,] -1.666667 2.333333 2.666667
일반화 역행렬(무어-펜로즈 일반화 역행렬) : MASS::ginv(A)
\[ A^{+} \]
A; MASS::ginv(A)
## [,1] [,2] [,3] ## [1,] 1 5 1 ## [2,] 3 7 0 ## [3,] -2 -3 1
## [,1] [,2] [,3] ## [1,] -2.333333 2.666667 2.333333 ## [2,] 1.000000 -1.000000 -1.000000 ## [3,] -1.666667 2.333333 2.666667
행렬의 계수(rank) : matrixcalc::matrix.rank(A)
\[ rank(A) \]
A; matrixcalc::matrix.rank(A)
## [,1] [,2] [,3] ## [1,] 1 5 1 ## [2,] 3 7 0 ## [3,] -2 -3 1
## [1] 3
행렬의 행렬식(determinant); det(A)
\[ det(A) \]
A; det(A)
## [,1] [,2] [,3] ## [1,] 1 5 1 ## [2,] 3 7 0 ## [3,] -2 -3 1
## [1] -3
행렬의 QR 분해 : qr(A)
\[ A = QR \]
\[ Q Q^T = Q^T Q = I_n, R_{ij} = 0(i>j) \]
qrA = qr(A)
qr.Q(qrA); qr.R(qrA)
## [,1] [,2] [,3] ## [1,] -0.2672612 0.86452993 -0.4256283 ## [2,] -0.8017837 0.04550158 0.5958796 ## [3,] 0.5345225 0.50051733 0.6810052
## [,1] [,2] [,3] ## [1,] -3.741657 -8.552360 0.2672612 ## [2,] 0.000000 3.139609 1.3650473 ## [3,] 0.000000 0.000000 0.2553770
대칭행렬이 양의 정부호행렬인가? : is.positive.definite(A)
\[ \forall \vec{x}, \vec{x}^T A \vec{x} > 0 ? \]
S = A + t(A) # Symmetric matrix
matrixcalc::is.positive.definite(S) # 양의 정부호행렬
## [1] FALSE
matrixcalc::is.positive.semi.definite(S) # 양의 준정부호행렬
## [1] FALSE
matrixcalc::is.negative.definite(S) # 음의 정부호행렬
## [1] FALSE
matrixcalc::is.negative.semi.definite(S) # 음의 준정부호행렬
## [1] FALSE
행렬의 고유치, 고유벡터 : eigen(A)
\[ A\vec{v} = \lambda \vec{v} \]
eigen(A)$values
## [1] 8.7315978 0.7355243 -0.4671222
eigen(A)$vectors
## [,1] [,2] [,3] ## [1,] -0.4532277 0.4164446 -0.8290741 ## [2,] -0.7852188 -0.1994315 0.3330898 ## [3,] 0.4219195 0.8870180 -0.4490961
# 첫 번째 고유치, 고유벡터
A %*% eigen(A)$vectors[,1]; eigen(A)$values[1] * eigen(A)$vectors[,1]
## [,1] ## [1,] -3.957402 ## [2,] -6.856215 ## [3,] 3.684031
## [1] -3.957402 -6.856215 3.684031
near(A %*% eigen(A)$vectors[,1], eigen(A)$values[1] * eigen(A)$vectors[,1])
## [,1] ## [1,] TRUE ## [2,] TRUE ## [3,] TRUE
행렬의 특이값 분해(Singular Value Decomposition) : svd(A)
\[ A = U \Sigma V^T\]
\[ A : (m \times n)-\text{행렬}, \Sigma_{ij}=0(i \neq j), U^T U = I_m, V^T V = I_n \]
A = rbind(A, c(1,5,4))
A
## [,1] [,2] [,3] ## [1,] 1 5 1 ## [2,] 3 7 0 ## [3,] -2 -3 1 ## [4,] 1 5 4
svd(A)$u #U
## [,1] [,2] [,3] ## [1,] -0.4602679 0.04856669 -0.81407479 ## [2,] -0.6647193 -0.41684977 0.08637949 ## [3,] 0.2872983 0.48493653 -0.43587676 ## [4,] -0.5135770 0.76727707 0.37394152
diag(svd(A)$d) # Sigma
## [,1] [,2] [,3] ## [1,] 11.1956 0.000000 0.0000000 ## [2,] 0.0000 3.877862 0.0000000 ## [3,] 0.0000 0.000000 0.7878675
svd(A)$v #V
## [,1] [,2] [,3] ## [1,] -0.3164279 -0.36220436 0.8767448 ## [2,] -0.9275211 -0.07569614 -0.3660255 ## [3,] -0.1989422 0.92901997 0.3119998
A; svd(A)$u %*% diag(svd(A)$d) %*% t(svd(A)$v)
## [,1] [,2] [,3] ## [1,] 1 5 1 ## [2,] 3 7 0 ## [3,] -2 -3 1 ## [4,] 1 5 4
## [,1] [,2] [,3] ## [1,] 1 5 1.000000e+00 ## [2,] 3 7 5.724587e-16 ## [3,] -2 -3 1.000000e+00 ## [4,] 1 5 4.000000e+00
near(A, svd(A)$u %*% diag(svd(A)$d) %*% t(svd(A)$v))
## [,1] [,2] [,3] ## [1,] TRUE TRUE TRUE ## [2,] TRUE TRUE TRUE ## [3,] TRUE TRUE TRUE ## [4,] TRUE TRUE TRUE
참고문헌
- Gerrard와 Johnson(2015). Mastering Scientific Computing with R.
추가 사항
- 삼각행렬
- LU 분해
- 촐레스키(Cholesky) 분해
- 슈어(Shur) 분해
Leave a comment