지금까지 우리는 임의의 직사각행렬(Rectangular Matrix)에 집중해 왔다. 이번 챕터부터는 주로 정방행렬(Square Matrix)에 관련된 내용들을 다룰 것이다. 이번 시간과 다음에 이어질 강의에서는 정방행렬의 행렬식(Determinant)에 관해 공부를 할 것이다. 사실 이 행렬식(Determinant)이 필요한 이유는 여러 가지가 있지만, 가장 큰 이유중 한 가지는 바로 고유값(Eigen Value)때문이다. 행렬식과 고유값에 대한 자세한 내용은 이후의 강의에서 공부하도록 하고 이번 강의에서는 행렬식의 속성과 특징들에 대해서 알아보도록 하자. 

 

 

1. 행렬식(Determinant)

 

행렬식(determinant)은 정방행렬(square matrix)에서만 정의되는 숫자이다. 모든 정방행렬은 이 수치를 가지며, 아래와 같이 표현한다. 

 

 

det A, 혹은 양쪽에 bar를 붙여서 |A|로 표현한다. 벡터의 크기를 표현할 때 bar를 양쪽에 두 개씩 붙이는 것( ||a|| )과 혼동하지 말자. 행렬식은 행렬의 행렬식(determinant of the matrix)이다. 

 

행렬식은 magic number와 같다. 이 하나의 숫자로 행렬의 모든 특성이나 속성을 표현할 순 없지만, 어떤 행렬의 가능한 많은 정보들을 압축하여 하나의 숫자에 담고 있다. 가령 수업시간에 많이 배웠던 내용이고 앞으로도 다시 배우겠지만, determinant(행렬이라는 단어와 혼동이 있을까 싶어 앞으로 행렬식이라는 표현보다 영문 표기를 쓰도록 하겠다)가 0이 아닌 경우 그 행렬이 역행렬이 존재함을 의미한다. 혹은 determinant가 0인 경우 행렬이 특이 행렬(singular matrix)임을 의미한다. 따라서 determinant는 어떤 행렬의 invertibility(역행렬의 존재 가능성)를 테스트하는데 사용된다. 수업시간에 determinant에 대해서 주로 이러한 내용에 관해 배웠을 것이다. 하지만 determinant는 이보다 많은 정보들을 담고 있다. 이제부터 하나씩 배워보도록 하자. 

 

사실 많은 학생들이 determinant를 배울 때 invertibility의 체크에 대한 내용과 계산 과정에 대해서만 배웠을 거라고 생각한다. 계산 과정이야 그대로 따라하면 초등학생들도 할 수 있는 것이고 중요한 것은 determinant가 의미하는 것이 무엇이고 어떤 정보들을 나타내고 있는지를 아는 것이다. 그래서 이번 포스팅에서는 계산 식에 대한 내용은 거의 다루지 않고 다음 포스팅에서 계산 식에 대한 내용들을 다룰 예정이다. 이번 포스팅에서는 우선 determinant의 3개의 주요 특성에 대해 먼저 다루고, 이 3개의 특성을 기반으로 7개의 특성에 대해서 설명을 하도록 하겠다

 

 

- prop. (1) 

 

 

 

첫 번째 특성은 단위 행렬(Identity matrix)의 determinant는 1이라는 것이다. 이때 행렬은 n x n크기의 행렬에 대해서 동일하게 적용된다. 계산 과정은 이후에 설명하더라도 첫 번째 특성은 매우 간단하기 때문에 더 이상 설명할 것이 별로 없다. 식 (2)의 예로 2 x 2 단위 행렬의 determinant를 계산해보자. determinant의 실제 계산 수식에 대해선 다음 포스팅에서 자세히 다룰 예정이니 일단 수업 시간에 배웠던 2x2 determinant 계산공식을 활용하여 답을 구해보자. 식 (3.1)은 2x2 행렬의 determinant를 구하는 공식이다. 

 

 

단위 행렬의 determinant를 계산한 결과, 식 (2)의 특성 처럼 1이 나오는 것을 볼 수 있다. 

 

 

 

- prop. (2) 

 

 

두 번째 특성은 행렬의 어떤 row를 다른 row와 바꾸면 determinant의 부호(sign)가 바뀐다는 것이다. 여기 까지의 특성만 봤을 때 혹시 어떤 행렬에 대한 determinant인지 눈치 채셨는가? 

일단 첫 번째 특성은 단위 행렬로부터 시작하였다. n x n에서 n이 얼마이던 간에 단위 행렬이라면 determinant는 1이다. 두 번째 속성은 어떤 정방행렬 이던간에 임의의 row를 교환하면 determinant의 부호가 바뀐다는 것이다. 그런데 특성 1로부터 출발하면 어떤 행렬이 될까? 즉 단위 행렬에서 임의의 row를 교환할 경우 이전에 배웠던 치환 행렬(permutation matrix)이 되는 것을 알 수 있다. 여기서 우리가 알 수 있는 것은 모든 치환 행렬의 determinant는 1 혹은 -1이 된다는 것이다. 이때 1 혹은 -1이 되는 기준은 행 교환(row exchange)을 짝수번(even) 했는지, 아니면 홀수번(odd) 했는지에 따라 정해진다. 즉 맨 처음 단위행렬에서 임의의 행 교환을 1번 했으면 이때의 determinant는 -1이 된다. 여기에서 임의의 행 교환을 한 번 더 하여 총 행 교환을 두 번 하게 되면 determinant는 1이 된다. 

 

 

식 (5)는 치환 행렬에 대한 규칙임을 기억하자. 특성 2는 다른 어떤 정방행렬에도 동일하게 적용되며, 단지 행 교환 이전의 determinant에서 부호가 바뀐다는 것을 명심하자. 마찬가지로 2x2 단위 행렬에 대해 특성 2를 적용하여 실제 계산을 수행해보자. 

 

 

최초의 단위 행렬에서 row exchange를 했을 경우 determinant의 부호가 바뀌는 것을 볼 수 있다. 여기서 한 번 더 하면 부호는 다시 +부호가 된다. 결국 단위 행렬의 row exchange를 짝수번 하면 1, 홀수번 하면 -1이 되는 것을 확인하였다. 이것은 임의의 n x n 치환행렬에 대해서도 동일하게 작용한다. 지금은 2x2크기의 정방 행렬의 determinant 공식만 다루고 있지만 사실 우리가 원하는 것은 n x n의 행렬에도 적용되는 일반적인 방법이다. 계산 방법은 바로 다음 포스팅에서 다루도록 하고 세 번째 특성으로 넘어가자. 

 

 

- prop. (3)-1

 

세 번째 특성은 사실 핵심이 되는 determinant의 특성이니 잘 이해하도록 하자. (3)-1과 (3)-2로 나누어서 정리하도록 하겠다. (3)-1의 특성을 우선 식으로 써보면 아래와 같다. 

 

 

식 (7)이 의미하는 것은 임의의 정방행렬 A에서 임의의 하나의 row에 t라는 scale 상수를 곱한 다음 determinant를 계산하면, A의 determinant에 t라는 상수를 곱한 것과 값이 같다는 것이다. 이때 t는 임의의 하나의 row에만 곱해지는 상수이고 나머지 n-1의 row는 그대로 두는 것이다. t를 2번째 row, 혹은 n번째 row에 곱하고 나머지는 그대로 둔 상태에서 계산해도 식 (7)의 법칙이 적용이 된다. 이것이 특성 (3)-1이다. 실제로 계산해보면 아래와 같다. 

 

 

 

- prop. (3)-2

 

역시 특성 (3)-2를 먼저 아래와 같이 식으로 정리해보자. 

 

 

식 (9)가 의미하는 것은 행렬 A에서 임의의 row에 어떤 벡터를 더했을 때의 determinant는 더한 row를 따로 분리하여 determinant 계산할 수 있다는 것이다.  즉 row1에 v=[a' b']을 더했다면, 원래 행렬의 determinant와 v와 나머지 row들로 만든 행렬의 determinant를 따로 계산하여 더한 값과 같다는 것이다. 이때 주의할 것은 더한 row를 제외한 나머지 n-1의 row들은 그대로 두어야 한다는 것이다. 실제 계산을 해보면 아래와 같다. 

 

 

 

정리해보면 특성 (3)-1과 (3)-2는 임의의 n x n크기의 정방행렬에 동일하게 적용되며, 어느 하나의 row에 scale상수를 곱하거나 임의의 row벡터를 더했을 경우, 나머지 n-1의 row들은 그대로 둬야 한다는 것이다. 결국 이들 특성 (3)-1과 (3)-2로 하여금 determinant를 구하는데 있어 선형 결합(Linear combination)의 규칙이 작용하는 것이다. determinant는 선형 함수(Linear Function)이다. 특성 (3)-1과 (3)-2를 같이 쓰면 아래와 같다. 

 

 

식 (11.1)은 determinant의 선형결합에 관한 식을, (11.2)는 그에 대한 예를 나타낸다. 

 

여기서 어떤 사람들은 오해를 할 수 있다. 즉 determinant가 선형 함수라고 해서 모든 row에 대해서 이러한 선형성이 동시에 적용되는 것이 아니다. 아래 식은 틀린 식이다. 

 

 

식 (12)는 determinant의 선형성이 모든 row에 대해서 동시에 적용되지 않음을 나타내는 것이다. 중요한것은 우리가 지금까지 determinant의 특성들에 대해서 언급하고 예를 들었을 때 단 하나의 row에 대해서만 적용을 하고 나머지 row들은 그대로 뒀다는 것이다. 결국 어떤 정방행렬의 determinant는 각각의 row에 대해서만 독립적으로 선형성(Linearity)을 나타낸다

 

이렇게 하여 determinant의 주요 특성 세 가지를 정리하였다. 우리는 이 세 가지 주요 특성들을 통해 어떠한 행렬의 determinant라도 정의할 수 있다. 그러나 이 세 가지 말고도 determinant는 다양한 특성들을 가지고 있다. 이제 이 세 가지 기본적인 특성들을 기반으로 determinant에 대한 나머지 특성들에 대해서도 알아보자. 

 

 

- prop. (4)

 

 

네 번째 특성은 행렬 A에 똑같은 row가 2개 존재한다면 그 행렬의 determinant는 0이 된다는 것이다. 사실 2 x 2의 경우엔 이해가 간다. 2 x 2에서 두 개의 row가 같아지면 det A=ab-ab=0 이 되기 때문에 당연히 0이 될 것이다. 하지만 왜 n x n의 행렬의 경우에도 같은 row가 두 개 존재하면 determinant가 0이 될까? 예를 들면 10 x 10의 정방행렬에서 row 2와 row 7이 같다고 해보자. 이렇게 큰 행렬에서 단지 두 개의 row가 같다고 해서 왜 determinant가 0이 될까? 

 

우리는 지금까지 determinant의 주요한 3개의 특성을 공부했다. 단위 행렬의 determinant가 1이 되는 특성, 행을 교환하면 determinant의 부호가 바뀌는 특성, 그리고 각각의 row에 독립적으로 적용되는 선형성(linearity)등이다. 어찌 되었든 우리는 앞서 배운 세 개의 특성을 가지고 바로 이 네 번째 특성을 정의해야 한다. 어떻게 할 수 있을까? 바로 prop. (2)로 부터 정의할 수 있다. 

 

prop. (2)는 row exchange가 발생했을 때 원래의 행렬과 다른 행렬이 만들어지게 되고, 결국 determinant의 부호가 바뀐다는 특성이다. 그러나 두 row가 같아져 버리면 row exchange를 해도 원래 행렬과 같아진다. 그러나 prop. (2) 특성은 반드시 만족해야 하기 때문에 부호를 반드시 바꿔야 하는데, 원래 행렬과 같기 때문에 부호를 바꾸어도 똑같아야만 한다. 수 많은 숫자들 중에 부호를 바꿔도 똑같은 숫자가 딱 한가지 있다. 바로 0(zero)이다. 따라서 어떤 행렬 A가 두 개의 같은 row를 가지고 있을 경우, A의 determinant가 0이 되어야만 같은 row를 교환하여 부호가 바뀌어도 prop. (2)가 성립하게 된다. 

 

또한 이렇게 생각해 볼수도 있다. 정방행렬에서 두 개의 같은 row가 있다면 rank는 n보다 작다. 따라서 이 행렬은 역행렬이 존재하지 않게 되므로 처음에 언급했듯이 determinant가 0이 되어야 한다. 

 

 

- prop. (5)

 

다섯 번째 특성은 소거(elimination)와 관련이 있다. Lecture 2에서 배웠듯이 소거 과정에서 우리는 pivot 변수를 지정하고 그 아래에 있는 원소들을 0으로 만들기 위해 pivot row에 특정 상수를 곱한 다음, 제거 할 row에서 이를 빼준다. 따라서 제거 할 k번째 row로 부터 상수값 $l$을 찾아서 pivot row와 곱해준다음 이를 k 번째 row에서 빼준다. 여기서의 특징은 이러한 소거 과정에서 중간에 나타나는 행렬의 determinant는 처음과 같다는 것이다.  즉 아래의 식과 같다. 

 

 

다시 말하자면 원래의 행렬 A를 소거하여 상삼각행렬(Upper triangular matrix) U를 만들었을 때, U의 determinant는 A의 determinant와 동일하다는 것이다. 결국 행렬 A를 소거를 해도, 소거 과정에서 나오는 어떠한 행렬도 determinant는 변하지 않는다. 이것이 다섯 번째 특성이다. 

 

그렇다면 이 특성은 어디서부터 오는가? 설명을 위해 식 (14)를 2x2행렬에 표현해 보자. 

 

 

식 (15)는 2x2행렬에서 소거를 위해 row1에 $l$을 곱하여 row2에서 빼주는 식에 대한 determinant를 나타낸 것이다. 그런데 이 식은 우측과 같이 분리가 가능하다. 바로 특성 prop. (3)-2로 부터 파생되는 것이다. 결과적으로 식 (15)의 최 우측의 determinant는 0이 되어 원래 행렬의 determinant와 같아지는 것을 볼 수 있다. prop. (3)-2를 통해 소거된 행렬과 원래 행렬의 determinant는 같음을 보였다. 

 

여기서 최 우측의 determinant에 prop. (3)-1을 적용할 수 있다. row2에 곱해져 있는 $l$을 밖으로 빼내면 아래와 같이 쓸 수 있다. 

 

 

이렇게 되면 최 우측 행렬의 determinant는 row1과 row2가 같다. 따라서 prop. (4)에 의해 0이 된다. 

 

prop. (5)를 정리하자면 임의의 행렬 A를 소거하는 과정에서 만들어지는 모든 행렬은 원래의 행렬 A와 같은 determinant값을 가진다. 이를 이전에 정리했던 특성들 prop. (3)-1, prop. (3)-2, prop. (4) 를 통해 정리하였다. 

 

 

- prop. (6)

 

Determinant의 여섯 번째 특성은 간단하다. 바로 원소들이 모두 0인 row가 하나 라도 존재한다면 determinant가 0이 된다는 것이다. 

 

 

모든 원소가 0인 row가 하나 라도 존재한다면, 해당 행렬은 특이 행렬(singular matrix)이 되고, rank는 n보다 작아지며, 역행렬은 존재하지 않는다. 그렇다면 이전의 특성들로부터 어떻게 특성 (6)을 유도할 수 있을까? 바로 prop. (3)-1으로부터 유도할 수 있다. 

 

 

예를 들어 t=0이고, t가 어떤 특정 row에 곱해졌다고 생각해보자. t는 prop. (3)-1에 의해 밖으로 뺄 수 있는데, t가 0이기 때문에 결국 determinant는 0이 된다. 

 

 

- prop. (7)

 

일곱 번째 특성은 매우 중요하면서 유용하므로 집중해서 잘 알아두도록 하자. 이는 상삼각행렬(Upper triangular matrix)과 관련되어있다. 2x2크기의 경우엔 determinant를 구하는 것이 어렵지 않지만, 100x100과 같이 큰 행렬일 경우엔 계산 과정이 굉장히 오래 걸린다. 이번 특성은 이러한 determinant의 계산을 손쉽게 해주는 방법이고 굉장히 유용하게 사용될 수 있다. 일단 아래의 상삼각행렬을 보자. 

 

 

4x4처럼 표현 되긴 했지만, 식 (19)를 n x n크기의 정방행렬이라고 생각해보자. 상삼각행렬이기 때문에 대각선 원소들을 중심으로 아래쪽 원소들은 모두 0이다. 대각선 원소들을 d1, d2, ... dn이라고 표현하고, 위쪽에 있는 원소들은 중요하지 않기 때문에 별표로 표시하였다. 

 

상삼각행렬(Upper triangular matrix)은 원래의 행렬 A를 소거(elimination)하여 만들 수 있는 행렬이다. 따라서 prop. (5)에서 확인했듯이 원래 행렬의 determinant와 같다. 그러나 이 상태에서 determinant를 구할 수 있는 더 쉬운 방법이 있다. 바로 상삼각행렬의 determinant는 대각 원소 d1, d2, ... dn들의 곱으로 구할 수 있다. 즉

 

 

따라서 상삼각행렬을 얻었을 때 determinant를 구하려면 대각 원소들을 곱해주기만 하면 된다. MATLAB과 같이 행렬 연산을 하는 software의 경우, 실제 어떤 행렬의 determinant를 계산할 때 먼저 소거(elimination)를 통해 상삼각행렬을 만들어준 뒤 pivot원소인 대각 행렬의 곱을 통하여 determinant를 계산한다. 행렬의 크기가 늘어날 수록 계산이 복잡해지는데, 이와 같은 방법으로 계산을 해주면 훨씬 빠르고 효율적으로 계산할 수 있다. 

 

대각 원소들의 곱으로 determinant를 구하는 건 알았고, 한 가지 더 신경써야 할 부분이 있다. 바로 determinant의 부호이다. 소거를 하는 과정에서 그대로 한 번에 된다면 좋겠지만, 어떠한 경우에는 행 교환(row exchange)을 해야할 때가 생긴다. 소거 과정에서 row exchange가 필요한 경우엔 부호를 살펴야하고 그렇지 않은 경우엔 그대로 대각 원소 d들을 곱해주면 된다. 만약 행 교환이 홀수번 일어나면 대각 원소들의 곱의 결과 값에 -1을 곱해주면 되고, 행 교환이 짝수번 발생하면 그대로 두면 된다. 이는 prop. (2)로 부터 증명할 수 있다. 

 

여기서 한 가지 의문점이 생긴다. 식 (20)에서 determinant를 구하기 위해선 대각 원소들의 곱을 통해 구할 수 있다고 했는데, 왜 *로 표시된 값들은 determinant에 영향을 미치지 않을까? 이를 어떻게 증명할 수 있을까? 이는 prop. (5)를 통해 증명할 수 있다. 소거를 해도 determinant에는 영향을 미치지 않기 때문에 Lecture 3의 Gauss-Jordan에서 했던 위쪽 방향으로의 소거를 해도 같다. 결국 U행렬은 대각 원소들만 존재하는 대각 행렬(diagonal matrix)이 되며,  determinant는 아래 식과 같이 표현할 수 있다. 

 

 

 

이제 대각 행렬을 제외한 나머지 원소들은 determinant에 영향을 미치지 않는 것으로 증명이 되었다. 그런데 왜 하필 대각 원소들의 곱일까? 이는 prop. (1)prop. (3)-1을 통해 증명할 수 있다. 우선 식 (21)을 보면 U의 각 row에 d1, d2, ... dn들이 곱해져 있는 형태이다. prop. (3)-1에 의해 우리는 이 d들을 밖으로 뺄 수 있다. d1을 시작으로 d2, d3, ... dn을 차례로 빼면 아래와 같은 형태가 된다. 

 

 

식 (22)에서 d들을 밖으로 빼면 대각 행렬은 단위 행렬(identity matrix)이 되며, prop. (1)에 의해 단위 행렬의 determinant는 1이 된다. 결과적으로 대각 원소들의 곱으로 상삼각행렬 U의 determinant를 구하는 것을 prop. (1), (2), (3)-1, (5)를 통해 증명하였다. 최초의 행렬 A에서 prop. (5)를 통해 소거를 하여 D를 만들고, prop. (3)-1을 통해 d들을 밖으로 빼내었으며, prop. (1)을 통해 d들의 곱만으로 determinant를 계산할 수 있음을 보였다. 또한 행 교환이 필요한 경우 prop. (2)를 통해 부호를 적절히 바꿀 수 있음을 보였다. 

결국 prop. (7)이 말하고자 하는 것은 A가 특이 행렬(singular matrix)이 아닐 때, determinant를 대각 원소들의 곱만으로 계산할 수 있다는 것이다. 매우 중요하니 잘 알아두도록 하자. 

 

 

- prop. (8)

 

prop. (7)에서는 pivot원소, 즉 d1 ~ dn이 0이 아님을 가정하였다. 그런데 만약 식 (20)에서 만약 어느 하나의 pivot 원소 dk가 0인 경우엔 어떻게 될까? 이 경우엔 위쪽 방향으로의 소거를 통해 식 (21)과 같이 대각 행렬(diagonal matrix)을 만들었을 때 dk=0인 row가 zero row가 된다. 이 경우 prop. (6)에 의해 행렬 자체가 특이 행렬임이 판명나고, 결국 determinant는 0이 된다. 따라서 여덟 번째 특성은 행렬 A가 특이 행렬(singular matrix)일 때 determinant가 0이 되고, A가 특이 행렬이 아닐 때, 즉 역행렬을 가질 때(invertible)는 determinant가 0이 아니다

 

 

어떤 pivot 원소가 0이라는 것은 결과적으로 행렬의 rank가 그 만큼 줄어들게 되고, 하나의 zero row를 갖게 되어 prop. (6)에 따라서 determinant는 0이 된다. 결국 full rank가 아닌 행렬은 특이 행렬이 되어 역행렬이 존재하지 않게 된다. 이것을 우리는 determinant의 계산을 통해 알 수 있다. 따라서 determinant의 계산은 역행렬의 존재 여부를 판단할 수 있는 좋은 방법이다. 

 

반면 행렬 A가 역행렬을 가질 때, 우리는 소거를 통해 A를 U(upper triangular matrix)로 만들고, 다시 위쪽으로 소거하여 D(diagonal matrix)를 만들고, 대각 원소 d1 ~ dn을 곱하여 determinant를 계산한다. 여기서 중요한 사실 한 가지는 우리는 방금 언급한 이 사실을 통하여 determinant의 공식을 유도할 수 있다는 것이다. 2x2크기의 정방행렬에 대한 determinant의 계산 공식은 다들 알다시피 ad-bc이다. 그러나 이 공식이 어떻게 유도되었는지 아는 사람은 그리 많이 않을 것이다. 아래 식을 보자. 

 

 

식 (24)는 행렬 A를 소거하여 상삼각행렬 U를 만든 것이다. (24.1)을 보면 소거할 때 pivot인 a를 소거할 원소인 c와 같게 만들기 위해 c/a를 row1에 곱한 뒤 row2에서 이를 빼준다. 이해가 잘 가지 않는다면 예를 든 (24.2)를 참고하기 바란다. 어쨋든 행렬 A를 소거하여 (24.1)과 같이 상삼각행렬 U를 만들었다. 우리는 prog. (7)을 통해 U의 determinant는 대각 원소들을 곱하면 된다고 이미 배웠다. 0인 pivot이 없으므로 (24.1)의 대각행렬을 곱해보자. 어떤 식이 나오는가? 

 

 

우리가 수업시간에 determinant를 구할 때 늘 써먹던 그 식은 바로 이와 같이 determinant의 prop. (1) ~ prop. (7)로 부터 유도된 것이다. 만약 식 (24)에서 a가 0이면 row exchange를 하고 determinant의 부호를 바꾸면 되고, 그래도 계산할 수 없다면 A가 특이 행렬이다. 

 

정리하자면 어떤 임의의 크기의 정방행렬 A의 determinant는 소거를 통해 만들어진 U의 대각 성분들의 곱으로 간단히 구할 수 있으며, (25)는 이런 절차에 따라 유도된 식이다. 

 

 

- prop. (9)

 

아홉번 째 특성은 간단하면서도 굉장히 유용하다. 일단 먼저 써보도록 하겠다. 

 

 

행렬 A와 B의 곱의 determinant는 determinant A와 determinant B의 각각의 곱과 같다는 것이 아홉번째 특성이다. 언뜻 보면 별것 아닌 것처럼 보이겠지만, 이 특성은 굉장히 값지고 유용한 특성이다. 이전의 prop. (3)-2의 식 (12)에서 행렬의 덧셈에 대한 determinant는 성립하지 않음을 알았다. 즉 모든 row에 대한 선형성(linearity)이 동시에 적용되지는 않는다는 것이다. 그러나 재밌게도 행렬의 곱셈에 대한 determinant는 분리하여 정의할 수 있다. 

 

예를 한 번 들어보자. A의 역행렬(inverse matrix)에 대한 determinant는 어떻게 정의할 수 있을까? 

 

 

식 (27.1)은 A의 역행렬과 A를 곱하면 단위행렬이 된다는 우리가 잘 아는 관계식이다. 식 (27.1)을 식 (26)을 이용하여 determinant를 구하면 (27.2)와 같이 되는데, 우변의 단위 행렬의 determinant는 prop. (1)에 의해 1이 된다. 여기서 식 (27.2)의 양변을 det A로 나눠주면 아래와 같이 det A(inverse)를 정의할 수 있다. 

 

 

A의 역행렬의 determinant는 1/(det A)로 정의할 수 있다. 사례를 한 번 들어보자. A를 소거를 통하여 대각 행렬(diagonal matrix) D로 만들었다고 했을 때, 식 (28)의 내용을 아래와 같이 쓸 수 있다. 

 

 

결과적으로 식 (26)이 의미하는 것은 어떤 두 개의 대각 행렬(diagonal matrix)의 관계를 정의할 때 유용하게 사용될 수 있으며, 이때 만약 행렬들이 대각행렬이 아니라면 소거 과정을 통해 대각 행렬을 만들어 이들을 적용할 수 있다. 

 

앞서 언급했지만 determinant는 행렬 A의 역행렬의 존재 여부(invertibility)를 체크하는데 사용된다. 즉 A가 역행렬을 가지면 determinant는 0이 아니고, 역행렬을 가질 수 없으면(singular matrix이면) determinant는 0이 된다. 이를 식 (28)을 통해 설명할 수 있다. A determinant가 0이 되면 A의 역행렬의 determinant가 1/0이 되어 식이 이상하게 되어버린다. 따라서 determinant는 역행렬의 존재 여부를 판별할 때 좋은 기준이 된다. 

 

약간 다른 경우도 한 번 살펴보자. A의 제곱인 경우엔 어떨까? 즉 A*A말이다. 이 역시 (det A)(det A)가 된다. 그렇다면 2*A의 determinant는 어떻게 될까? 2*A는 A+A이다. 이 경우엔 어떻게 정의할 수 있을까? 이때는 단순히 2*(det A)는 틀린 답이다. 2*A라는 것은 A의 모든 row에 각각 2씩을 곱해준 것이다. 따라서 prop. (3)-1과 식(22)와 같이 2를 앞쪽으로 빼줄 수 있다. row1에 곱해진 2를 먼저 앞으로 빼고, row2, ... row n에 곱해진 2를 차례로 앞으로 빼면 결과적으로 2를 n번 만큼 앞으로 빼서 곱해준 셈이 되기 때문에 2의 n승이 된다. 이들을 정리하면 다음과 같다. 

 

 

식 (30.1)은 식 (26)에 의해 정의된 것이다. 또한 나중에 자세히 다룰 기회가 있겠지만 식 (30.2)의 determinant는 어떤 volume을 정의하는데 있어 유용하게 사용된다. 

 

 

- prop. (10)

 

마지막 열 번째 특성도 그리 어렵진 않다. 바로 적어보겠다. 

 

 

열 번째 특성은 A의 transpose의 determinant는 원래 A의 determinant와 같다는 것이다. 일단 여기서 다루고 있는 행렬은 정방행렬이므로 전치(transpose)를 해도 A의 가로, 세로의 크기는 변하지 않는다. 눈여겨 봐야할 것은 row와 column이 바뀐다는 것이다. 

 

 

지금까지 우리는 determinant와 관련된 모든 작업을 row 기준으로 해왔다. 모든 원소가 0인 row가 하나라도 있을 경우 determinant는 0이 되는 등 row기준으로 모든 작업을 진행해왔다. 그렇다면 모든 원소가 0인 column이 존재한다면 determinant는 어떻게 될까? 정답은 똑같이 0이다. 마찬가지로 행 교환(row exchange)을 했을 때 부호가 바뀌었다면, 열 교환(column exchange)을 했을 때에도 부호가 바뀐다. 그리고 일단 식 (31)의 determinant를 구했을 때, 양쪽 모두 ad-bc로 식은 같다.

 

 뭔가 같은 것 같긴 하지만 그래도 이전의 특성들을 활용해 식 (31)을 증명해보자. 아래 식을 보자. 

 

 

최초의 식 (33.1)에서 Lecture 4에서 배웠던 LU 분해(LU decomposition)를 통해 식 (33.2)와 같이 만들 수 있다(두 행렬의 곱에 transpose를 취하면 순서가 바뀜에 유의). 식 (33.2)는 하삼각행렬(Lower triangular matrix) L과 상삼각행렬(Upper triangular matrix) U의 곱으로 이루어져 있다. 이를 바로 전에 배웠던 prop. (9)의 특성을 이용하여 정리하면 식 (33.3)과 같이 된다. 여기서 L의 경우 대각 원소들은 1로 이루어져있다. 이 L행렬들의 대각 원소들을 제외한 나머지 원소들은 소거(elimination)를 통하여 없앨 수 있고, 결국 L의 determinant는 1이 된다. 

이제 남은 것은 식 (33.4)의 U이다. 알다시피 U도 transpose이던 아니던 삼각행렬(triangular matrix)의 형태를 띈다. 어떤 삼각 행렬이던간에 대각 원소들을 제외한 나머지 원소들은 소거를 통하여 없앨 수 있으며 determinant의 계산에 영향을 미치는 것은 결국 대각 원소(diagonal elements)들이다. 따라서 U를 transpose해도 대각 원소들은 바뀌지 않기 때문에 결과적으로 determinant는 같다. 이렇게 하여 determinant의 열 번째 특성도 증명을 하였다.  

 

 

2. 마치며

 

이번 강의에선 행렬식(determinant)의 특성들에 대해서 알아보았다. 아직 2x2크기의 행렬 이외의 determinant를 구하는 계산식은 배우지 않았는데 이들은 다음 포스팅에서 다룰 예정이다. 사실 계산식을 배우는 것 보다는 determinant가 가지고 있는 특성들을 먼저 이해하는 것이 나중에 응용될 여러 가지 수식들에 대해서도 훨씬 유용하다. 우리는 먼저 determinant의 중요한 3가지 특성들을 정리하고, 이를 기반으로 나머지 7개의 특성들에 대해서 정리하였다. 마지막으로 중요한 말 한 가지만 하자면, determinant는 pivot들의 곱으로 이루어지는 수치이다 !.

 

각 특성들은 determinant를 이해하는 데에 중요하기 때문에 반드시 이해하고 넘어가시기 바랍니다. 

특성들이 총 10가지나 되기 때문에 이를 한 눈에 알아보기 쉽게 아래에 표로 정리하였으니 참고하기 바랍니다. 꼭 표만 보지 마시고 반드시 본문의 내용을 숙지하신 뒤 참고용으로만 보시는 것을 추천드립니다

  • Determinant의 특성들
 특성 수식  설명 
 prop. (1) 
  • 단위행렬의 determinant는 1이다. 
 prop. (2) 
  • 행을 바꾸면 determinant의 부호가 바뀐다. 
  • 홀수번 바꾸면 -1, 짝수번 바꾸면 원래 부호 그대로. 
 prop. (3)-1
  • 행렬의 하나의 row에 곱해진 상수는 밖으로 뺄 수 있다. 
 prop. (3)-2   
  • 행렬의 하나의 row에 더해진 row벡터는 분리하여 정리할 수 있다. 
 prop. (4)   
  • 행렬에 두 개의 똑같은 row가 존재하면 determinant는 0이 된다. 
 prop. (5)   
  • 행렬을 Gauss소거법으로 소거하여도 determinant의 값은 변하지 않는다. 
 prop. (6)   
  • 모든 원소가 0인 row가 하나 라도 존재한다면, determinant는 0이다. 
 prop. (7)   
  • 삼각행렬(triangular matrix)의 determinant는 대각 원소들의 곱으로 간단히 구할 수 있다. 이때 d들은 0이 아니어야 한다. 
  • 일반 행렬들도 소거를 통해 삼각행렬을 만들고 대각 원소들의 곱으로 간단히 determinant를 구할 수 있다. 
 prop. (8) 
  •  행렬 A가 특이 행렬(singular matrix)이면 determinant는 0이다. 
  •  역행렬이 존재하면 determinant는 0이 아니다. 
  • 반대로 determinant를 통해 행렬의 역행렬 존재 여부를 판별할 수 있다.
 prop. (9)   





  • 두 행렬의 곱 AB의 determinant는 각 행렬의 determinant의 곱과 같다. 
  • A의 역행렬의 determinant는 A의 determinant의 역수이다. 
  • A의 제곱의 determinant는 A의 determinant의 제곱과 같다.
  •  A에 상수를 곱한 determinant는 상수의 n승을 A의 determinant에 곱한 것과 같다. 
 prop. (10)   
  • 행렬 A의 transpose의 determinant는 원래 행렬의 determinant와 같다. 
  • 즉 transpose를 해도 determinant는 변하지 않는다.  

 

최근 정부를 비롯해 기업에서도 많은 관심을 기울이고 있는 것이 바로 4차 산업혁명이다. 이 4차 산업혁명을 의미하는 키워드들을 간략히 언급하자면 다음의 것들이 있다. 


인공지능(Artificial Intelligence), IoT(Internet of Things), 3D-Printer, 로봇(Robotics), AR(Augmented Reality), VR(Virtual Reality), 빅데이터(Big-Data), 웨어러블로봇(Wearable Robotics), 자율주행차(Autonomous Driving Car), 드론(Drone), ... 



관련 전공자가 아니더라도 한 번쯤은 들어봤던 단어들일 것이다. 

위에 나열한 키워드들을 보면 공통적으로 요구되는 기술이 있다. 바로 소프트웨어(Software)기술이다. 위에 나열된 그 어떠한 것도 소프트웨어 없이는 구현될 수 없다. 정부에서도 이러한 소프트웨어의 중요성을 인식하고 2018년부터 관련 교육을 의무화 한다고 공표하였다. 그 만큼 중요하다. 


그렇다면 전 세계적으로 어떠한 소프트웨어들이 사용되고 있을까? 또한 어떠한 소프트웨어들이 존재하는 것일까? 소프트웨어 관심을 가진 사람이라면 한 번쯤 이러한 생각을 해본 적이 있을 것이다. 이번 포스팅에서는 세상에 존재하는 수 많은 프로그래밍 언어들이 얼마나 인기가 있고 널리 사용되는지에 대해 알아보고자 한다. 




1. TIOBE index 



Fig. 1 TIOBE Ranking. 검색엔진의 쿼리와 웹페이지 정보를 기반으로 Ranking을 정한다. (2017년 4월 기준)



전 세계 사람들이 가장 많이 사용하는 프로그래밍 언어는 무엇일까? 이와 관련된 정보를 제공해주는 회사가 네덜란드에 위치한 TIOBE(https://www.tiobe.com/)이다. 이 회사에서 제공하는 서비스 중 한 가지는 프로그래밍 언어에 대한 Ranking을 제공한다. Google, Yahoo, Baidu, Wikipedia, Youtube 외에 사람들에게 널리 사용되는 검색엔진들의 검색 쿼리(queries)와 관련 웹페이지들을 수집하여 쿼리와 웹페이지에 포함된 각 프로그래밍 언어의 단어 숫자들의 통계치를 기반으로 순위를 매기는 방식이다. 이 index는 한 달에 한 번 업데이트 되며, 무료로 볼 수 있다. 그러나 긴 기간동안의 특정 통계치는 팔기도한다.  


주의해야 할 것은 이들이 제공하는 Ranking은 최고의 프로그래밍 언어(Best Programming Language)에 대한 Ranking이 아니며, 가장 많은 수의 line이 작성된 언어도 아니다. 단지 인터넷에서 많이 회자되는 언어를 기반으로 전세계에서 가장 많이 사용되는 프로그래밍 언어를 추정한 추정치이다. 프로그래밍 관련 순위를 보려면 아래 링크로 접속하면 된다. 


https://www.tiobe.com/tiobe-index//


2017년 4월 기준으로 Java가 1위이며, C와 C++, C#, python등이 뒤를 잇는다. 순위에 따른 점유율(Ratings)을 제공하며, 그간의 순위 변동을 그래프로 볼 수도 있다. 




2. PYPL index 



Fig. 2 PYPL Ranking. Google trends데이터를 기반으로 Ranking이 정해진다. 프로그래밍 언어 뿐만 아니라 통합개발환경(IDE), DB언어 등에 대한 Ranking도 제공한다. (2017년 4월 기준)



PYPL(PopularitY of Programming Language) index는 Google trends의 통계데이터를 기반으로하며, 사용자들이 각 프로그래밍 언어의 튜토리얼(tutorial)을 얼마나 검색하는지에 대한 통계치를 기반으로 Ranking을 매긴다. 프로그래밍 언어 뿐만 아니라 visual studio 등과 같은 통합개발환경 IDE(Integrated Development Environment), ODE(Online Integrated Development Environment), 그리고 SQL과 같은 DB언어에 대한 Ranking도 보여준다. 아래 링크에서 순위를 볼 수 있다. 


http://pypl.github.io/PYPL.html


이들이 주장하는 바로는 TIOBE index는 단순히 웹페이지에 포함된 프로그래밍 언어 단어들을 기반으로 추정치를 산출하기 때문에 정확하지 않다고 한다. 단순히 웹페이지나 쿼리에 프로그래밍 언어와 관련된 단어가 존재한다고 해서 그것을 사람들이 사용하거나 공부한다고는 할 수 없으며, 관련 튜토리얼을 검색한 사람이 적극적인 유저라고 할 수 있기 때문에 자신들이 더 정확하다고 주장한다. 뭐 어느 정도는 일리있는 것 같긴 하다. 2017년 4월을 기준으로 1위는 Java로 TIOBE의 Ranking과 같으며, python, php, C#, Javascript가 뒤따른다. 순위가 약간 다르다. 




3. RedMonk index 



Fig. 3 RedMonk Ranking. Github와 StackOverflow의 자료를 기반으로 Ranking을 정한다. (2017년 4월 기준)



RedMonk의 프로그래밍 언어 Ranking은 Github와 Stackoverflow자료를 기반으로 제공된다. Github에 각 프로그래밍 언어로 작성된 소스코드들의 Pull Request(소스코드가 변경되었다고 Github와 다른 사용자들에게 알리는 행위)의 숫자를 수집하고, Stack Overflow사이트에서 주고 받는 질문과 답변, 그리고 태그 정보들을 수집하여 이 둘을 조합하여 순위를 매기는 방식이다. TIOBE나 PYPL index와 달리 실제 소스코드에 대한 지표를 고려한다는 점에서 차별화 되어있다. RedMonk의 Ranking은 아래의 링크에서 확인할 수 있다. 


http://redmonk.com/sogrady/category/programming-languages/





4. 마치며 


위에서 언급한 사이트 이외에도 다양한 Ranking사이트들이 존재한다. 그러나 가장 널리 알려진 것은 위의 세개 정도이며, 나머지 Ranking index에 관한 내용은 여기에서 간략히 볼 수 있다. 

사실 어떤 지표가 더 낫다, 더 정확하다고 자신있게 얘기할 순 없다. 각기 다른 기준의 지표를 사용하고 있으며 각자가 주장하는 합리적 근거가 있기 때문에 그저 개인의 판단에 맡기는 수밖에 없을 것 같다. 세부적으로는 순위에 약간씩 차이가 있긴 하지만, 높은 순위에 Rank되는 언어들은 비슷한 양상을 보인다. Java계열 언어는 거의 독보적 1위를 차지하고 있으며 python과 C계열 언어, PHP등이 높은 순위에 올라와있다. 약간씩 다른 기준과 지표들을 활용하고 있지만, 결과적으로는 비슷한 양상을 보이기 때문에 너무 어느 한 쪽을 맹신하거나 혹은 불신하거나 하지는 않아도 될 것 같다. 개인적으로는 튜토리얼 검색 기반의 PYPL방식이 가장 좋아보이기는 한다. 그리고 IDE나 DB언어의 Ranking을 함께 제공해주는 것도 가장 마음에 든다. 어디까지나 개인적인 의견일 뿐이지만.


사실 필자도 이렇게나 많은 언어가 존재하는지는 몰랐다. Java가 너무 우위를 점하고 있어서 Java를 배울까 하는 생각을 아주 잠깐 하기도 했었지만, 어떤 언어를 다루는지는 사실 그렇게 중요하지 않을 수 있다. 중요한건 문제 파악 능력과 해결 능력이 아닐까. 




참고로 프로그래밍 입문자나 새로운 프로그래밍 언어를 배워보고자 하는 사람이 있다면 "Which Programming Language should I learn first"을 참고하는 것도 괜찮을 것 같다. 


지난 강의 Lecture 17-(1)에 이어 직교행렬과 그람-슈미트 과정 두 번째 강의다. 반드시 이전 강의에서 직교행렬(orthogonal matrix)을 공부하고 오기를 추천한다. 이제 그람-슈미트 과정(Gram-Schmidt Process)에 대해 공부해보도록 하자. 

 

 

4. 그람-슈미트 과정(Gram-Schmidt Process)

 

지난 강의의 마지막 부분에서 잠깐 언급했듯이, 그람-슈미트 과정(Gram-Schmidt Process)은 어떤 임의의 행렬 A의 column vector를 orthonormal column들로 바꾸는 것이다. 즉 행렬 A를 정규직교벡터(orthonormal vector)들로 이루어진 직교 행렬(orthogonal matrix) Q로 만드는 것이다. 이때 중요한 조건은 A의 column vector들이 독립(independent)이어야 한다. 아래 그림을 보자. 

 

 

Fig. 1 두 개의 독립(independent)인 벡터

 

 

Fig. 1은 두 개의 독립(independent)인 벡터를 나타낸다. 두 벡터 a와 b를 임의의 차원의 공간에서 2차원을 정의하는 기저벡터라고 하자. a와 b는 독립이기 때문에 분명 선형조합(Linear combination)을 통해 2차원 공간의 모든 벡터를 나타낼 수는 있다. 그러나 보다 효과적인 연산, 간단한 연산을 위해 이들을 똑같은 공간을 정의하는 정규직교벡터(orthonormal vector)로 만들고 싶은 것이다. 그람-슈미트 과정은 이렇게 독립인 벡터들을 정규직교벡터로 만들어준다. 

 

그람-슈미트 과정의 아이디어는 다음과 같다. 먼저 맨 처음 벡터인 a는 그대로 두고 시작한다. 이 a를 기준으로 a에 직교(orthogonal)한 벡터를 만들어낸다. 이를 각각 q1, q2라고 하자. 즉 a->q1, b->q2로 만드는 것이다. 여기까지 그람(Gram)의 아이디어다. 다음으로 할 일은 직교 벡터인 q1, q2를 정규직교벡터(orthonormal vector)로 만드는 것이다. 이는 q1과 q2를 각각 자신의 크기로 나누어주면 된다. 이것이 슈미트(schmidt)의 아이디어다. 지금까지의 과정을 정리하면 아래와 같다. 

 

Fig. 2 그람-슈미트(Gram-Schmidt)의 과정

 

 

- (1) Making Orthogonal Vectors (by Gram)

 

이제 Fig. 1의 두 벡터 a와 b를 가지고 그람-슈미트 과정을 수행해보자. 먼저 벡터 a는 그대로 q1이 된다. 마치 초기값과 같은 것이다. a->q1으로 변하는 과정은 전혀 문제가 없다. 문제는 b->q2의 과정이다. 왜냐하면 b는 a에 직교하지 않기 때문이다. 우리가 하고자 하는 것은 a와 독립이지만 직교는 아닌 벡터 b에서 출발하여 a와 직교인 벡터 q2를 찾는 것이다. q2를 어떻게 만들 수 있을까? 바로 Lecture 15에서 배웠던 투영(Projection)을 이용하는 것이다. 아래 그림을 보자. 

 

 

Fig. 3 투영을 이용한 직교 벡터 계산 방법

 

 

첫 번째 벡터인 빨간색 a는 그대로 q1이 된다. 그다음 두 번째 벡터 b를 a에 투영시켜서 p를 만드는데, 이때 error벡터인 e를 만들어낼 수 있다. 즉 b를 a에 투영시킬때, a에서 b에 가장 가까운 지점은 b와 연결되면서 a에 수직한 지점이다. 투영의 정의에 의해서 b와 연결되는 a에 수직한 지점으로 투영이 되어 벡터 p가 생성되고, 결과적으로 b에서 p를 빼면 e=b-p 를 계산할 수 있다. 이때의 e는 a와 수직(perpendicular)한 벡터가 되고 e가 곧 q2가 된다. 결국 투영(projection)을 이용하여 a=q1에 수직한 벡터 e=q2를 만들어낼 수 있다

 

투영 파트에서는 구하고자 하는 벡터가 p였고 e는 그저 버려지는 벡터였는데, 이번엔 반대로 p가 버려지고 e를 취하게 되었다. 투영에 관한 자세한 사항은 위에 링크를 걸어놓은 Lecture 15를 참고바란다. 

 

 

그렇다면 q2에 대한 실제 식은 어떻게 될까? 아직 투영 행렬 P를 모르는 상태이고, 주어진 것은 벡터 b와 벡터 a=q1이다. e=b-p에서 p에 대한 식만 정리하면 된다. 식은 아래와 같다. 

 

 

뭔가 익숙한 식일 것이다. Lecture 15(이해가 안가면 꼭 먼저 공부하고 오자)에서 벡터를 이용하여 투영 벡터를 구할 때 보던 식이다. p=xa에서 분수 부분이 바로 x에 해당한다. 현재 q1은 원래의 a와 같다. 이렇게 하여 q2를 구하였다. 결과적으로 q1과 q2는 수직(perpendicular)이다. 즉 내적(dot product)을 했을 때 결과가 0이어야 한다. 식이 맞는지 확인해보도록 하자. 

 

 

 

식을 곱해서 전개하면 분수의 분모가 캔슬되고 분자만 남게되고(분수의 계산 결과는 상수임을 기억하자), 결과는 0이 된다. q1과 q2가 직교(orthogonal)임을 식의 전개를 통해 확인하였다. 

 

우리는 지금까지 두 개의 독립인 벡터 a와 b를 가지고 a를 기준으로 서로 직교(orthogonal)인 벡터 q1과 q2를 만들었다. 이제 세 번째 벡터 q3를 만들어보자. q3를 만들기 위해선 a와 b와 독립인 벡터 c가 필요하다. Fig. 1의 a와 b에서 화면으로 나오는 방향, 혹은 들어가는 쪽으로 비스듬하게 독립인 벡터 c가 있었다고 가정해보자(이때의 행렬은 3x3크기의 full rank=3인 행렬). Fig. 3은 a와 b로부터 q1과 q2를 만든 모습이다. 아래의 Fig. 4는 이 시점에서부터 시작한다. 

 

 

Fig. 4 독립 벡터 c의 그람-슈미트 과정 첫 번째 단계. 왼쪽 그림은 옆에서 바라본 장면이다. 

(2D로 표현하기에는 한계가 있어서 3D-CAD툴을 이용하여 표현하였다)

 

 

Fig. 4는 독립인 벡터 c를 q1과 q2에 동시에 직교(orthogonal)한 벡터로 만드는 그람-슈미트 과정의 첫 번째 단계를 나타낸다. 파란색 벡터 c는 독립이긴 하지만 q1과 q2어느 누구와도 직교는 아닌 상태이다(Fig. 4의 왼쪽 side view 참고). 여기서 우리가 해야할 일은 c를 q1과 q2에 동시에 직교하게 만들어야 하는데, 먼저 q1과 직교하게 만들고 그 다음 q2와 직교하게 만들면 된다. Fig. 4는 이 중 q1과 직교하게 만드는 과정을 나타낸다. 

 

벡터 c를 a에 투영시키면 녹색 벡터 p를 얻을 수 있고, p=xa와 ec1=c-p에 의해 a와 직교한 에러 벡터 ec1을 구할 수 있다. 이 과정은 식 (1)과 같은 과정이며, e->ec1, b->c, 와 같이 c에 맞게 바뀐 것이다. 이것을 식으로 나타내면 아래와 같다. 

 

 

벡터 c로부터 이렇게 q1과 직교인 에러 벡터 ec1을 만들어냈다. q1과 직교인 벡터를 만들어 냈으니 다음은 q2와 직교한 벡터를 만들 차례다. 아래 그림은 Fig. 4에 이어 q2와 직교한 벡터를 만드는 과정을 나타낸다. 

 

 

 

Fig. 5 q2와 직교한 벡터 ec2를 만드는 과정. 결과적으로 에러 벡터 ec2는 q1과 q2에 동시에 직교하므로 ec2=q3이다. 

 

 

 

q1과 직교한 벡터 ec1을 q2에 투영시키면 벡터 p를 얻고, 이 둘 사이의 에러 벡터인 ec2=ec1-p를 계산해주면 최종적으로 ec2를 구할 수 있다. Fig. 5에서 보는 것과 같이 ec2는 q1과 q2모두에 직교한 벡터이기 때문에 결과적으로 ec2=q3가 된다. 이를 식으로 나타내면 아래와 같다. 

 

 

약간 복잡해 보이지만 그리 어렵지 않으니 차근차근 확인해보자. 먼저 ec2는 앞서 구한 ec1에서 투영 벡터 p를 빼주면 구할 수 있는데, 이때 투영 벡터 p는 q2에 어떤 스칼라(scalar)상수를 곱한 것과 같다. 이 예에선 음수 값이 될 것이다. 그리고 ec2는 q2와 직교 하기 때문에 내적(dot product)을 해주면 그 결과가 0이 된다. 이러한 정의들을 가지고 식을 치환하고 전개해서 풀어주면 x에 관한 식을 (4.1)과 같이 구할 수 있다. 

 

 

그 다음 ec2=ec1-p에서 p를 x q2로 치환한 후 (4.1)의 x를 대입해주면 (4.2)와 같은 식을 구할 수 있다. 그런데 식에 ec1이 있어서 약간 혼란스러울지도 모르겠다. ec1을 식 (3)에서 정의한 내용으로 치환하여 다시 정리하면 아래와 같다. 

 

 

 

식이 많이 길지만 겁먹을 건 없다. 그저 치환해서 정리한 것 뿐이다. 먼저 (5.1)은 (4.2)의 분수의 분자에 있는 ec1을 (3)으로 대체하여 정리한 것이고 (5.2)와 같이 전개된다. 이때 분자에 q2 transpose와 q1을 내적하는 부분이 있는데, q1과 q2는 직교(orthogonal)이기 때문에 0이 되어 사라지고 (5.3)과 같이 된다. 이제 (5.3)의 ec1을 (3)으로 대체하여 정리해주고 ec2를 q3로 바꿔주면 최종적으로 식 (5.5)와 같이 정리된다. 

 

이렇게 하여 임의의 독립(independent)인 column 벡터 a, b, c로부터 같은 column space를 공유하면서 직교(orthogonal)하는 직교 벡터(orthogonal vector) q1, q2, q3를 구하였다. 다시 한 번 식을 한 번에 정리해보자. 

 

 

 

 

q1은 굉장히 쉽게 구했다. 그냥 첫 번째 벡터인 a를 대입하면 된다. q2는 b의 투영을 통해 a와 직교한 에러 벡터(error vector) e를 구하는 식이다. 마지막 q3는 c를 q1과 q2에 순차적으로 투영시켜 에러 벡터를 구하게 된다. q3의 패턴을 살펴보면 원래의 벡터 c에서 q1으로 투영시킨 벡터, q2로 투영시킨 벡터를 각각 빼준다. 여기서 한 가지 중요한 사실은 만약 4차원, 5차원, n차원 column vector가 더 있다면 q4, q5, qn을 위와 같은 패턴으로 구할 수 있다는 것이다. 물론 조건은 독립(independent)이어야 한다. 만약 q4를 구해야 한다면 원래 벡터인 d에서 q1, q2, q3로 각각 투영시킨 벡터들을 빼주면 된다. 이것이 Gram이 제안한 직교벡터를 만드는 아이디어이다. 

 

마지막으로 q3를 구하는 과정을 하나의 그림으로 살펴보고 다음으로 schmidt가 제안한 아이디어를 알아보도록 하자. 아래 그림은 q3를 구하는 과정을 하나의 그림으로 표현한 것이다. Fig. 4와 Fig. 5를 하나로 합친 것으로 생각하면 된다. 벡터 c부터 시작한다. 

 

 

Fig. 6  q3를 구하는 과정. 벡터 c부터 시작

 

 

 

- (2) Making Orthonormal Vectors (by Schmidt)

 

그 다음 과정은 상대적으로 간단하다. 지금 까지 구한 직교 벡터(orthogonal vector)는 정규화(normalized)가 되어 있지 않다. 즉, 각 벡터의 크기가 제각각이다. 이들을 방향 성분만을 나타내는 벡터로 만들기 위해선 정규화를 통해 정규직교벡터(orthonormal vector)로 만들어 줘야한다. 정규직교벡터를 만드는 방법은 각 벡터를 자신의 크기로 나누어 주면 된다. 

 

 

 

기존의 직교 벡터(orthogonal vector)와 구분해주기 위해 q hat으로 표현을 했다. 이렇게 직교 벡터로부터 정규직교벡터를 만드는 것은 schmidt의 아이디어이다. 

이렇게 해서 기존의 독립(independent)인 column vector a, b, c로부터 정규직교벡터(orthonormal vector) q1, q2, q3를 만들어냈다. 이 실제 벡터를 이용해서 계산해 보도록 하자. 

 

 

 

5. 예제와 MATLAB 구현

 

- 2D subspace in R3

 

아래의 두개의 독립인 3차원 벡터를 그람-슈미트 방법(Gram-Schmidt Process)을 이용하여 정규직교벡터(orthonormal vector)로 만들어보자. 벡터 a와 b는 3차원 공간에 존재하는 벡터들이며, 이 두 벡터가 이루는 column space는 2차원 평면 임을 알아두자. 

 

 

 

먼저 식 (6.1)과 (6.2)를 이용하여 직교 벡터(orthogonal vector)로 만들면 아래와 같다. 

 

 

 

 

직교 벡터 q1과 q2는 구했고, 이제 정규화를 해보자. q1과 q2를 각각의 크기로 나누어주면 아래와 같이 단위 벡터가 만들어진다. 

 

 

 

이렇게 하여 a와 b로부터 정규직교벡터(orthonormal vector) q1과 q2를 구하였다. 이렇게 계산한 q1(hat)과 q2(hat)로 직교 행렬(orthogonal matrix)을 만들 수 있는데, 간단히 q1(hat), q2(hat), ... qn(hat)을 순서대로 column vector로 삽입하면 된다

 

 

우리는 기존의 행렬 A로부터 직교행렬 Q를 만들었다. 이미 언급했지만 여기서 column space에 관한 얘기를 한 번 더 해보자. column space라는 것은 column vector들의 가능한 모든 선형 조합(Linear Combination)을 통해 형성하는 공간을 의미한다. 그렇다면 원래의 행렬 A와, A로부터 만든 직교행렬 Q와는 무슨 관계가 있을까? A와 Q의 column space는 똑같은 공간을 공유한다. 즉 원래의 행렬 A의 column vector들은 column space의 기저(basis)이며, 선형 조합을 통해 column space를 형성한다. 마찬가지로 Q의 column vector들도 기저(basis)로써 A와 같은 공간을 형성하는데, 기저가 정규직교벡터(orthonormal vector)이기 때문에 A보다는 계산 등에 훨씬 유리하다. 정리하자면 A의 column space의 기저(basis)를 보다 효율적이고 최적화된 기저로 만드는 방법이 그람-슈미트 방법(Gram-Schmidt Process)이라고 생각하면 된다. 

 

MATLAB구현을 보기 전에 q1(hat)과 q2(hat)가 직교인지 확인해보자. 내적(dot product)을 하여 결과 값이 0이 나오는지 확인하면 된다. 

 

 

 

내적 결과 값이 0이므로 q1과 q2가 직교한다는 사실을 확인했다. 

 

 

아래 그림은 위의 q1과 q2를 MATLAB을 이용하여 구현한 것이다. 

 

Fig. 7 Gram-Schmidt Process를 이용한 정규직교벡터의 그래프

 

 

Fig. 7은 식 (8)의 벡터 a, b와 이를 그람-슈미트를 이용하여 정규직교벡터로 만든 q1(hat), q2(hat)를 그래프로 나타낸 것이다. 보다시피 원래의 벡터 a와 b는 독립이며 노란색으로 표현된 column space를 "span"할 수 있다. 그러나 a와 b의 선형 조합(Linear combination)을 이용하여 column space를 표현할 경우 계산상에 많은 불리함이 있다. 

 

보라색과 하늘색 벡터는 a와 b를 정규직교벡터로 만든 q1(hat)과 q2(hat)이다. 앞서 말했듯이 q1(hat)은 a를 그대로 대입하고 정규화 했기 때문에 a와 같은 선상에 위치한 것을 볼 수 있다. q1(hat), q2(hat)는 a와 b로 형성했던 column space와 같은 공간에 위치한 것을 볼 수 있으며, 같은 column space를 "span"하더라도 계산상에 있어 훨씬 유리한 점이 많다. 이 점에 대해서는 지난 강의 Lecture 17-(1)에 언급해 놓았으니 참고하기 바란다. q1(hat)과 q2(hat)는 90도 각도를 이루고 있음을 볼 수 있다. Fig. 7에 보이는 그래프에서는 완벽한 90도가 아닌 것 처럼 보일 수는 있으나 이것은 MATLAB그래프의 가로 세로의 비율(aspect ratio)과 바라보는 각도때문에 왜곡이 생겨서 그렇다. 실제로는 90도를 이루고 있다. 

 

직교성을 확인하기 위해 MATLAB에서 계산한 q1(hat)과 q2(hat)를 실제로 내적하면 정확하게 0이 안나오는 경우가 생긴다. 이는 컴퓨터로 계산할 때 발생하는 round off 에러 때문인데, 컴퓨터의 수치 정밀도 때문에 발생하는 것이다(자세한 것은 구글 참조). 실제로 Fig. 7의 q1(hat)과 q2(hat)의 내적을 계산하면 1.6653e-16 이라는 수치가 나오는데, 엄청나게 작은 수 이므로 0으로 간주하는 것이다. 아래의 첨부된 MATLAB 코드를 참조하여 실제로 구현해서 확인해보는 것을 추천한다. 

 

 

 

 

- 3D space

 

이번에는 a, b에 이어 c가 추가된 3차원 column space에 대한 그람-슈미트 과정(Gram-Schmidt Process)을 수행해보도록 하자. 벡터 c는 아래와 같다. A는 c가 추가된 행렬을 나타낸다. 

 

 

 

q1과 q2는 이미 구했으니 c와 관련된 q3만 구하면 된다. 식 (6.3)을 이용하여 계산해보자. 

 

 

 

 

 

계산하다보니 숫자가 좀 커졌지만, 어쨋든 q3를 구하였다. 이제 정규화(normalization)를 통해 q3를 정규직교벡터로 만들어보자. 

 

 

 

 

 

이렇게하여 a, b, c로부터 정규직교벡터 q1(hat), q2(hat), q3(hat)를 만들었다. 직교행렬(orthogonal matrix)을 만드는 것은 식 (11)과 같기 때문에 넘어가도록 하겠다. 직교성을 확인하기 위해 q1(hat), q2(hat)와 내적하는 것은 MATLAB을 이용하거나 직접 해보길 바란다. 아래 그래프는 식 (13)의 벡터와 이에 대한 그람-슈미트 과정을 통해 얻은 정규직교벡터를 나타낸다. 

 

 

Fig. 8 식 (13)의 벡터와 그들의 정규직교벡터 그래프

 

Fig. 8을 보면 기존의 독립 벡터 a, b, c는 3차원 공간을 "span"하기는 하지만 크기도 제각각이고 column space인 3차원 공간의 기저(basis)가 되기엔 뭔가 최적화 되어 있지 않아 보인다. 반면 그람-슈미트 과정을 통해 만든 정규직교벡터 q1(hat), q2(hat), q3(hat)는 정규화된 동일한 크기의 벡터이고 서로 완벽하게 직교(orthogonal)를 이루는 모습을 볼 수 있다. 아래는 이를 구현한 MATLAB 코드이다. 

 

 

 

 

 

이번 포스팅에서는 3차원 정규직교벡터인 q3까지 구하였다. 하지만 이전에도 언급했듯이 4차원, 5차원, n차원의 벡터에 대해서도 계산은 가능하다. q1->q2->q3로 가면서 계산하는 패턴은 동일하기 때문에 n차원 그람-슈미트 방법에 대한 구현도 어렵지않게 할 수 있을 것이다. 

 

 

 

6. QR분해(QR decomposition)

 

- QR decomposition basic

 

마지막으로 살펴볼 내용능 지금까지 계산했던 그람-슈미트 방법(Gram-Schmidt Process)을 행렬로 정리하는 것이다. 이를 QR 분해(QR decomposition, QR factorization)라고 한다. 그러나 여기에선 그리 많은 양을 다루진 않고 간략히 살펴보고 넘어가도록 하겠다. 나중에 기회가 되면 따로 정리하도록 하고 일단 이런게 있구나 정도만 보고 넘어가면 될 것 같다. 

 

우리는 지난 Lecture 4에서 A=LU 분해(A=LU decomposition)를 배웠다. A라는 행렬을 소거 행렬(elimination matrix)을 통해 삼각행렬(triangular matrices)들의 곱으로 분해해서 표현하는 방법인데, QR 분해 역시 마찬가지로 원래의 A행렬을 Q행렬과 R행렬의 곱으로 분해하여 표현하는 방법이다. 여기서 Q행렬은 우리가 지금까지 그람-슈미트 방법을 통해 구했던 직교 행렬(orthogonal matrix)을 의미하며, R행렬은 A와 Q를 연결시켜주는 행렬이라고 생각하면 된다. 특히 R행렬은 상삼각행렬(Upper triangular matrix)의 형태를 띄고 있는데, 지금부터 이 R행렬이 무엇이고 왜 상삼각행렬의 모양으로 하고 있는지 알아보자. 

 

행렬 A와 Q, R은 아래와 같이 나타낼 수 있다. 

 

 

 

위의 식 (16)을 보고 어떤 사람들은 이렇게 생각할지도 모르겠다. 아까 분명히 Q행렬을 만들 때 q1, q2, ... 들을 순서대로 Q의 column vector에 삽입하면 된다고 했는데, 왜 갑자기 Q가 m x m이 되는 거지? 사실 식 (16)은 QR 분해를 할 때 A가 정방행렬(square matrix)의 형태 뿐만 아니라 직사각행렬(rectangular matrix)의 형태까지 고려한 일반적인 형태이다. 직사각행렬인 경우 계산 과정이 약간 더 복잡해진다. 이에 대한 자세한 내용은 QR분해 위키를 참조하도록 하고 일단 정방행렬인 경우만 고려하여 생각하도록 하자. 

 

우선 A행렬의 column vector들을 a1, a2, ...로 표현했는데, 위에서 설명한 a, b, c, 등의 벡터를 나타낸다. Q행렬은 A와 똑같은 column space를 형성하는 기저(basis)들로 구성되어 있으며 정규직교벡터들로 구성되어 있다. 중요한건 R행렬인데, 각 원소들은 a1, a2 등의 벡터들과 Q행렬의 column vector인 q1, q2 벡터들과의 내적으로 구성되어 있다. 그런데 대각선을 기준으로 아래쪽 원소들은 전부다 0이 된다. 왜 그럴까? 

 

아래쪽 원소의 식을 보면 a1과 q2, 그리고 a2와 q3와 같이 q벡터와 이전 index의 벡터들과 내적을 한다. 어째서 어떤 q벡터와 이전 index의 a벡터와 내적을 하면 0이 될까? 그것은 그람-슈미트의 계산 과정과 관련이 있다. 식 (6.3)이나 Fig. 6을 보면 우리가 벡터 c로부터 q3를 만들 때 먼저 q1과 직교하게 만들고, 그 다음 q2와 직교하게 만들어서 q3를 생성하게 된다. 이 말은 qn을 만들 때 qn-1과는 반드시 직교(orthogonal)해야하고 따라서 q1, q2등과 대응 되는 a, b, c, ... 등의 이전의 모든 벡터와는 직교해야함을 의미한다. 따라서 아래쪽 삼각형 원소들은 모두 0이 되고 R은 상삼각행렬(upper triangular matrix)의 형태가 된다. 

 

 

- QR matrices and MATLAB function

 

Q행렬은 그람-슈미트 과정을 통해 얻은 q벡터들을 Q의 column vector들로 삽입하여 간단히 얻을 수 있다고 하였다. 그렇다면 R행렬은 어떻게 구할 까? A행렬이 정방행렬(square matrix)이라고 가정할 때, 아래의 식을 통해 간단히 얻을 수 있다. 

 

 

결국 원래 행렬 A에 Q transpose행렬을 곱해주면 R을 얻을 수 있다. 아래 그림은 식 (13)을 MATLAB을 이용하여 계산한 결과다. 

 

Fig. 9 식(13)의 QR decomposition

 

 

기존에 구했던 q1, q2, q3를 이용하여 직교행렬 Q를 만든 다음, 식 (17)과 같이 R을 계산하고 Q와 R을 곱하여 식이 맞는지 확인하였다. 결과적으로 A와 같음을 볼 수 있다. 

 

그런데 MATLAB에는 행렬 A만 있으면 기본적으로 QR decomposition을 해주는 함수가 있다. 명령어는 " [Q R]=qr(A) " 와 같이 치면 되고 자동으로 Q와 R행렬을 계산해준다. 그러나 Fig. 9에서 계산한것과 부호 등이 다른 경우가 있는데, 이는 구현 알고리즘이 달라서 발생하는 현상이며 결국은 같은 기능을 하는 것이다. 실제 구현에서는 Householder reflection방법을 많이 사용하는데, 수치계산에 있어서 그람-슈미트보다 훨씬 안정적이라고 한다. 자세한 사항은 QR분해 위키를 참조하자. 아래는 MATLAB내장함수인 qr()을 이용하여 계산한 결과다. Fig. 9의 결과와 비교해보자. 

 

Fig. 10 MATLAB내장 함수를 이용하여 수행한 QR decomposition

 

 

 

7. 마치며

 

이번 포스팅에선 그람-슈미트 방법(Gram-schmidt Process)에 대해서 공부하였다. 그람-슈미트는 기존 행렬의 column space를 이루는 기저(basis)를 계산에 있어서 보다 효율적이고 최적화된 기저로 바꾸는 방법이며, 바뀐 기저는 정규직교벡터(orthonormal vector)의 형태를 띈다. 이는 계산 상에 있어 여러 모로 효율적이다. 정규화된 단위 벡터이기 때문에 크기는 1이며, 방향 성분만을 나타내는 벡터이다. 따라서 overflow, underflow등과 같은 문제에 있어 자유롭고, 계산을 간단하게 해주는 특징을 보인다. 

그람-슈미트 방법은 기본적으로 투영(projection)의 개념을 이용하여 계산되며, 이 그람-슈미트 방법은 이후 SVD(singular value decomposition)에 응용 되기도 하니 잘 알아두도록 하자. 

 

이번 강의에서 배울 내용은 직교행렬(Orthogonal Matrix)과 그람 슈미트 과정(Gram-Schmidt Process)이다. 먼저 이들을 간략히 설명하면 다음과 같다. 직교 행렬은 모든 column vector가 자기 자신을 제외한 나머지 모든 column vector들과 직교이면서 크기가 1인 단위 벡터들로 구성된 행렬을 의미한다. 그리고 그람 슈미트 과정은 임의의 독립 행렬(independent matrix)로부터 각 column vector가 정규직교(Orthonormal)한 벡터들로 구성된 직교 행렬을 만드는 과정 혹은 방법을 의미한다. 이 설명만 가지고는 이해하기가 어려울 수 있으니 차근차근 공부해 보도록 하자. 먼저 정규직교벡터(Orthonormal vector)에 대해 공부해보자. 

 

 

 

1. 정규직교벡터(Orthonormal Vector)

 

- 단위 벡터(Unit Vector)

 

정규직교벡터(Orthonormal Vector)를 알아보기 전에 먼저 단위 벡터에 대해 먼저 알아보도록 하자. 

 

일반적으로 어떤 벡터는 크기와 방향 성분을 가진다. 예를 들어 벡터 vv=[2 1]T라고 했을 때, v는 바닥에서 약 26.5도 회전한 쪽으로의 방향을 가리키고 있고, √5의 크기를 갖는다. 여기서 어떤 scale상수를 곱해서 벡터의 길이를 늘린다고 가정해보자. scale상수가 3이면 3 x v = [6 3]T = √45 = 3√5의 크기가 된다. 즉 원래 벡터의 길이에 곱해진 scale만큼 길이가 더 늘어나게 된다. 

 

그렇다면 단위 벡터(Unit Vector)란 무엇인가? 정의하자면 길이가 1인 벡터를 의미한다. 즉 길이가 1이라는 것은 단위 길이(Unit length)를 의미하며 오직 방향성분만을 나타내는 벡터이다. 우리가 길이를 나타낼 때 표준 단위계(SI)에선 m(meter)을 이용하여 길이를 표현한다. 가령 2미터를 나타낼 때 "2m"과 같이 숫자 뒤에 m을 붙여주는데, 이때 m은 길이의 단위를 나타낼 뿐 실제 길이에 어떠한 영향도 끼치지는 않는다. 

단위 벡터는 바로 "m"과 같은 역할을 하는 것이다. 힘의 크기와 방향 등을 벡터로 나타낼 때 단위 벡터(Unit vector)는 크기 성분에는 전혀 영향을 끼치지 않는다. 방향 성분만을 나타내기 때문에 어떤 scale상수를 곱하여 길이를 늘린다고 했을 때 그 늘린 길이가 scale상수 그 자체이다. scale이 3, 벡터 v가 단위 벡터라고 했을 때 3 x v의 길이(크기)는 3이다. 

 

일반 벡터를 단위벡터로 만들기 위해선 아래 식과 같이 기존의 벡터를 벡터의 크기로 나누어주면 된다. 

 

 

식 (1)을 참고하여 벡터 v=[2 1 3]T를 단위벡터(Unit vector)로 만들어보자. 

 

 

 

우리는 이러한 단위 벡터를 정규화 벡터(normalized vector)라고도 한다. 즉 서로 다른 스케일을 가지고있는 벡터들을 동일한 스케일에서 바라보기위해 벡터의 크기로 나누어 정규화(normalization)한 벡터를 의미한다. 

 

 

 

- 정규직교벡터(Orthonormal vector)

 

직교 벡터(orthogonal vector)는 알다시피 벡터 사이의 각도가 90도, 즉 직각(perpendicular)을 이루는 벡터를 말한다. 즉 어떤 a라는 벡터가 있고, a와 직각인 벡터 b가 있을 때 a와 b벡터를 우리는 직교벡터라고 하며 이때 a와 b의 내적(dot product)은 0이 된다. 따라서 직교 벡터는 어떤 하나의 벡터로는 정의할 수 없고 반드시 한 쌍 이상의 벡터로부터 정의되어야 한다

 

그렇다면 정규직교벡터(orthonormal vector)란 무엇일까? 이는 바로 직교 벡터(orthogonal vector)이면서 단위 벡터(unit vector)인 벡터를 말한다. 즉 두 벡터가 90도의 각도를 이루고, 각 벡터의 길이(크기)는 1인 방향성분만을 나타내는 벡터를 우리는 정규직교벡터(orthonormal vector)라 한다. 이를 수식으로 나타내면 아래와 같다. 

 

 

Orthonormal vector를 각각 qi, qj라고 했을 때, qi는 자기 자신에게는 직교(orthogonal)하지 않는다. qi를 자기 자신과 곱하면, 즉 자기 자신과 내적(dot product)하면 그 결과값은 1이 된다. 이것이 의미하는 것은 q는 벡터의 크기가 1인 단위 벡터(unit vector)라는 의미다. 단위 벡터인 식 (2)의 v hat을 제곱해보자. 결과는 4/14 + 1/14 + 9/14 = 1이 될 것이다. 이처럼 벡터들이 서로 직교(orthogonal)하면서 동시에 정규화된 벡터이기 때문에 ortho-normal이라는 이름을 사용하는 것이다. 

 

자기 자신을 제외한 나머지 모든 벡터들과는 직교(orthogonal)한다. 즉 자기 자신을 제외한 나머지 벡터들과의 내적(dot product)결과가 0이 되는 것이다. 아래 그림은 이러한 정규직교벡터(orthonormal vector)의 한 예를 나타낸다. 

 

 

Fig. 1 정규직교벡터(orthonormal vector)의 예

 

 

Fig. 1은 sin과 cos으로 이루어진 벡터를 나타낸다. 이들 벡터 a, b의 길이는 각각 1이며 둘 사이의 각도는 90도이다. 두 벡터가 직교(perpendicular)하며 각 벡터의 길이는 1로써 방향성분만을 나타내므로 이들은 정규직교벡터이다. 

 

이러한 정규직교벡터들을 행렬의 column vector에 삽입하면 직교행렬(orthogonal matrix)이 된다. 즉 Q를 직교행렬이라고 했을 때 orthonormal vector들이 Q의 정규직교기저(orthonormal basis)가 되는 것이다. 이러한 정규직교기저는 선형대수의 행렬 계산에 있어 좋은 결과를 보여준다. 특히 선형대수계산을 연구하는 분야인 Numerical Linear Algebra의 대부분의 연산은 이러한 orthonormal vector를 기반으로 이루어진다. 이들은 수치 연산을 하는 과정에서 값이 무한정 커지거나 작아져서 발생하는 overflow나 underflow문제에 있어서 자유롭다. 왜냐하면 크기에 영향을 미치지않는 단위 행렬(unit vector)성분을 가지고 있기 때문이다. 이것이 정규화(normalization)의 힘이다.

 

 

 

2. 직교행렬(Orthogonal Matrices)

 

- Basic of Orthogonal Matrix

 

직교행렬(orthogonal matrix)은 행렬의 row와 column vector들이 자기 자신을 제외한 나머지 모든 row, column vector들과 직교(perpendicular)이면서 동시에 단위 벡터(unit vector)인 행렬을 의미한다. 즉 orthonormal vector들을 행렬 Q에 집어넣은 것과 같다. 아래 식과 같이 말이다.  

 

 

 

식 (4)는 orthonormal vector를 행렬 Q에 column vector로써 삽입한 형태이다. 이때 임의의 벡터 qi는 자기 자신을 제외한 나머지 벡터들과 직교(perpendicular)하다. 즉 식 (3)의 규칙을 따르는 것이다. 식 (3)의 규칙을 확인하기 위해서는 Q transpose와 Q를 곱한 값을 보면 알 수 있다. 

 

 

식 (5)는 Q transpose와 Q의 곱셈 결과를 나타낸다. Q transpose는 q transpose를 Q의 row vector로 삽입한것과 같다. 이를 Q와 곱하면 어떤 결과가 나오는가? 바로 단위 행렬(Identity matrix)이다. Q transpose의 row1과 Q의 col1의 곱은 자기 자신과의 곱셈이다. 따라서 모든 row(i)와 col(j), (i=j)의 곱셈은 자기 자신과의 곱셈이기 때문에 결과 행렬의 대각 성분은 1이 된다. 반면 나머지 벡터끼리의 곱셈은 직교(orthogonal)하기 때문에 0이 되어 결과적으로 단위 행렬이 나오는 것이다. 결국 

는 

와 마찬가지로 모든 row와 column 벡터들 끼리의 내적(dot product)을 확인하는 것이다. 식 (3)의 정의와 맞는 것을 볼 수 있다. 

 

이렇게 하여 우리는 orthonormal column을 가진 orthogonal matrix를 배웠다. 사실 Q에 대한 더 정확한 표현은 orthonormal matrix이다. 각 벡터들이 orthogonal이 아닌 orthonormal한 벡터를 가지고 있기 때문이다. 그러나 무슨 이유에서인지 표현은 항상 orthogonal matrix로 한다

 

 

- Square Orthogonal Matrix

 

직교 행렬(orthogonal matrix)이면서 정방행렬(square)인 경우의 가장 대표적인 예는 단위행렬(identity matrix)이다. 단위행렬의 각 column vector는 자기 자신을 제외한 나머지 벡터들과 90도의 각도를 이루면서 각각의 크기는 1이다. 이를 시각화하면 아래 그림과 같다. 

 

Fig. 2 직교행렬(orthogonal matrix)이면서 정방행렬(square matrix)인 단위행렬(identity matrix)의 시각화

 

 

Fig. 2는 어디서 많이 본 그림일 것이다. 바로 표준 기저(standard basis)이다. x축은 y축과 z축에 각각 수직(perpendicular)이며, y는 x와, z축에, z는 x와 y에 각각 수직이다. 각 벡터끼리 내적(dot product)을 하면 0이 되는 것을 볼 수 있다. 또한 각 축의 기저는 정규화(normalized)된 크기인 1이다. 이러한 표준 기저의 선형 조합(Linear combination)을 통해 우리는 3차원 공간의 모든 벡터, 점 등을 정의할 수 있다. 

 

이와 같이 직교 행렬이 정방행렬일 경우 한 가지 흥미로운 특성을 갖는다. 그것은 바로 transpose가 역행렬(inverse matrix)과 같다는 것이다. 다시 정리해보자면

 



정규직교벡터(orthonormal vector)로 구성된 직교 행렬(orthogonal matrix) Q가 row의 수와 column의 수가 같은(m=n) 정방행렬(square)인 경우
의 관계에 의해서 Q의 transpose는 Q의 역행렬(inverse matrix)이 된다. 즉





 

 

사실 식 (5)를 잘 살펴보면 당연하다. Q transpose와 Q를 곱했을 때 단위행렬이 된다는 것은 Q가 정방행렬인 상황에서 Q transpose가 당연히 역행렬이어야 한다. 예를 한 번 들어보자. 우리는 지난 Lecture 5에서 행 교환(row exchange)연산을 해주는 치환행렬(permutation matrix)에 대해 공부했었다. 치환행렬은 정규직교벡터로 구성된 직교 행렬(orthogonal matrix)이다. 아래 식을 보자. 

 

 

 

식 (6)의 치환행렬(permQ)의 column vector나 row vector들은 각자의 크기는 1이면서 자기 자신을 제외한 나머지 벡터들과는 수직(perpendicular)이다. 이제 여기에 Q의 transpose를 곱해보자. 결과는 아래와 같다. 

 

 

직교 행렬 Q에 Q transpose를 곱했더니 단위행렬이 나오는 것을 볼 수 있다. 따라서 Q transpose는 Q의 역행렬과 같다. 

한 가지 예를 더 들어보자. Fig. 1과 관련이 있는 예다. 

 

 

식 (8)은 cos과 sin으로 이루어진 직교 행렬(orthogonal matrix)이다. column 벡터들을 보면 각각 col1=[cos sin]T, col2=[-sin cos]T인데, 둘은 Fig. 1에 보이는 것과 같이 직교하며 내적(dot product)을 하면 0이 된다. 각 column vector의 크기는 1이며, 크기 구하는 식에 대입해보면 바로 알 수 있다. 

 

 

 

 

한 가지 예를 더 들어보자. 아래의 행렬은 직교 행렬인가? 

 

 

분명 column 혹은 row vector를 비교해보면 직교 벡터를 가지고 있다. 그러나 각 벡터의 길이가 1이 아니다. 어떻게 이들의 길이를 1로 만들어줄 수 있을까? 위의 단위 벡터 편에서 단위 벡터를 만들기 위해선 벡터의 크기로 나눠주면 된다는 것을 배웠다. 마찬가지로 벡터의 크기로 행렬 원소 전체를 나눠주면 된다. 다음 식과 같이 말이다. 

 

 

식 (11)의 임의의 qi의 길이(크기)를 계산해보면 √(1/2+1/2)=√(1)=1이 되는 것을 알 수 있다. 사실은 column 1과 column 2가 직교(orthogonal)하지만, 크기가 다를 경우가 있다. 따라서 보다 정확하게 말하자면 column 1은 column 1의 크기로, column 2는 column 2의 크기로 각각 나누어줘야 한다

 

이제 마지막 예를 들어보도록 하겠다. 다음 행렬을 살펴보자. 식 (10)의 행렬을 반복하여 만든 행렬이다. 

 

 

식 (12)는 식 (10)의 행렬 Q의 각 원소들에 Q를 대입한 것과 같은 형태이다. 먼저 직교성(orthogonality)을 계산해보면 Q의 임의의 column qi와 나머지 column vector와 내적을 하면 결과는 0이 된다. 그러나 각 column 혹은 row vector의 길이는 1이 아니다. 즉 직교성은 만족하지만, 단위 행렬(unit vector)속성은 만족하지 않는다. 따라서 직교행렬이 되기 위해선 식 (11)과 같이 단위 행렬로 만들어야 한다. 이를 위해서 해당 column 혹은 row 벡터의 길이(length or magnitude)로 자기 자신을 나누어주면 된다. 

 

 

식 (13)의 어떠한 벡터의 크기를 계산해도 1이 된다. 따라서 식 (13)은 직교 행렬(orthogonal matrix)이다. 식 (13)의 행렬을 특히 Adhemar matrix이라고 부른다. 이에 대한 자세한 것은 구글을 참고하자. 여기선 그냥 넘어가도록 하겠다. 

 

 

- Rectangular Orthogonal Matrix

 

지금까지는 직교 행렬(Rectangular Matrix)이 정방행렬인 경우만 살펴보았다. 이번엔 임의의 직사각 형태인 직교 행렬을 살펴보도록 하자. 아래 식은 직사각 형태의 직교 행렬을 나타낸다. 

 

 

 

식 (14.1)일 때는 그저 단순히 하나의 단위 벡터(unit vector)이다. 여기에 col1벡터와 독립인 col2벡터를 추가하여 (14.2)와 같은 직사각형 형태(Rectangular) 식을 만들었다. 이때의 column vector들은 3차원 공간에서 2차원 부분 공간(subspace)의 column space를 이루는 기저(basis)가 된다. 여기에 세 번째 column vector를 더하면 (14.3)과 같이 된다. 

 

사실 여기서 말하고자 하는 것은 (14.1)에서 (14.2)로 넘어갈 때, 그리고 (14.2)에서 (14.3)으로 넘어갈 때 어떻게 직교벡터(orthogonal vector)를 만드느냐이다. 특별한 알고리즘이나 방법이 없이는 우리의 직관에 의해서 직교 벡터들을 만들어서 기존의 행렬에 더해줘야 한다. 그러나 이는 행렬의 크기가 커질 수록 너무나 어려운 일이다. 이후에 설명할 그람-슈미트 과정(Gram-Schmidt Process)은 이러한 직교 행렬을 만들어주는 특별한 방법이다. 즉 임의의 독립된 column vector들로 구성된 행렬, 즉 독립(independent)인 행렬(matrix)이 있을 때, 이 독립인 행렬을 직교행렬(orthogonal matrix)로 만들어주는 방법이다. 

 

본격적으로 그람-슈미트 과정을 공부하기 전에 먼저 직교 행렬을 이용하여 연산을 했을 때 어떠한 이점이 있는지 살펴보도록 하자. 

 

 

- Advantage of using Orthogonal Matrix

 

직교 행렬(orthogonal matrix) Q를 활용하여 계산하면 몇 가지 이점이 있다. 먼저 수식이 굉장히 간단해진다. 우리가 어떤 벡터 b를 행렬 A의 column space로 투영(projection)시키고 싶을 때, 투영행렬(projection matrix)을 통해 이를 할 수 있음을 Lecture 15에서 배웠다. 투영 행렬의 식을 다시 상기시켜보자. 

 

 

식 (15)의 투영행렬식은 얼핏 보면 약간 복잡해 보이긴 한다. 그렇다면 A대신 Q를 이용하여 투영행렬을 만들게 되면 식이 어떻게 변할까? 

 

 

Q는 정규직교(orthonormal) column vector들로 이루어진 직교 행렬(orthogonal matrix)이다. A대신 Q를 이용하여 투영 행렬(projection matrix)를 만들었더니 식 (16)과 같이 식이 굉장히 간단해졌다. 괄호 안의 Q transpose Q가 식 (5)에서 본 것과 같이 단위행렬이 되기 때문이다. 따라서 괄호 안의 식은 없어지는 것과 마찬가지가 되고 결국 양 끝에 Q와 Q transpose만 남게 된다. 이때 Q가 임의의 직사각행렬(rectangular matrix)이라면, (16)의 결과 행렬은 대칭 행렬(symmetric matrix)이 된다. 

 

만약 Q가 정방행렬(square matrix)이라면 어떨까? 이 경우엔 식이 훨씬 더 단순해진다. 우리는 위의 노란박스에서 Q가 정방행렬일 경우 Q의 전치(transpose)는 Q의 역행렬이라고 배웠다. 식 (16)에서 Q의 투영행렬은 

이 되므로 결과적으로 단위 행렬이 된다. 식은 아래와 같다. 

 

 

왜 Q가 정방행렬일 경우 투영행렬이 단위 행렬이 되는지 잘 생각해보자. 투영 행렬은 임의의 벡터 b를 행렬 A 혹은 Q의 column space로 투영(column space의 가장 가까운 벡터로의 매칭)시키는 역할을 한다. 그런데 Q가 정방행렬이 되어버리면 Q의 column space가 전체 공간과 같아져버리게 된다. 따라서 임의의 벡터 b는 전체 공간인 Q의 column space에 이미 존재하기 때문에 투영 자체가 의미가 없어져버린다. 그래서 정방행렬(square matrix)인 직교 행렬(orthogonal matrix)의 투영 행렬(projection matrix)이 단위 행렬이 되는 것이다. 

 

마지막으로 투영 행렬의 특성중 하나인 

를 확인해보자. 투영시킨 벡터를 다시 투영해도 그 결과는 같다는 것 말이다. 식 (16)을 기준으로 이 특성을 다시 써보면 아래와 같다. 

 

식 (18)의 밑줄 친 부분이 단위행렬이 되므로 결과는 P와 같다. 

 

이와 같이 기존의 임의의 행렬 A에 대한 해를 구하는 식은 Q를 이용할 경우 훨씬 간단해진다. Lecture 15-(1)에서 배웠던 overdetermined case의 해를 구하는 식을 Q를 이용하여 정리하면 아래와 같이 간단하게 정리된다. 

 

 

앞의 Q transpose Q가 단위 행렬이 되어 사라지고 뒤의 식만 남게된다. 결과적으로 Q를 이용할 경우 해(solution) x hat의 각 원소들은 Q transpose와 b의 내적(dot product)연산에 의해 간단히 정의된다. 

 

 

 

3. 마치며..(continue)

 

이번 강의에선 그람-슈미트 과정을 배우기에 앞서 필요한 선행 지식인 직교행렬에 관해 공부하였다. 직교행렬(orthogonal matrix)은 정규직교벡터(orthonormal vector)들로 이루어진 행렬이며 계산을 간단하게 해주는 특징이 있다는 것을 공부하였다. 또한 실제 계산에 있어서 정규화(normalized)된 직교(orthogonal) 벡터들을 이용하기 때문에 계산 결과값이나 overflow, underflow와 같은 문제에 있어서 훨씬 좋은 성능을 보인다. 

 

그러나 여기서 어떤 사람들은 이런 의문이 들수도 있을 것이다. A대신 Q를 이용해서 식을 만들면 좋은건 알겠는데, 대체 A랑 Q랑 무슨 관계지? Q가 좋긴 하지만 A대신 사용하게 되면 원래 식과는 완전히 달라지는거 아냐? 

이후 과정에서 더 자세히 설명하긴 하겠지만, A와 Q는 같은 column space를 공유하는 행렬이다. 즉 A의 column vector들을 기반으로 A와 똑같은 column space, 혹은 부분 공간(subspace)을 이루는 행렬 Q를 만드는 것이다(※이때 A는 반드시 독립이어야 함). 다시 말하면 원래 A가 가지고 있던 column vector들은 column space의 기저(basis)이긴 하지만, 최적의 기저는 아닐 가능성이 크다. 원래의 행렬 A의 column space의 기저(basis)를 보다 최적화된 기저로 만들어준다! 정도로 생각하면 될 것 같다. 

 

원래 그람-슈미트 과정(Gram-Schmidt Process)까지 이번 포스팅에서 다루려고 했으나, 내용이 너무 길어질 것 같아서 나누어서 하겠습니다. 다음 강의(17-(2))에서는 직교행렬에 이어 그람-슈미트 과정을 다루도록 하겠습니다. 

 






지적 대화를 위한 넓고 얕은 지식, 일명 "지대넓얕"의 두 번째 편 (철학, 과학, 예술 종교, 신비)편을 읽었다.



책의 전반적인 흐름은 우선 진리를 추구하고 찾으려는 인간에 대한 역사와 통찰을 바탕으로 세 가지 철학적 접근법을 제시하였다. 절대주의, 상대주의, 회의주의가 그것이고, 이 세 가지 철학 정신을 중심으로 철학, 과학, 예술, 종교, 신비에 대한 주제들을 이야기했다. 



얼핏 보면 이 다섯 가지 주제가 따로 떨어져 있는 것 처럼 보이지만 저자는 위에서 언급했던 세 가지 철학적 접근법을 이용해 이들을 연결지어 설명하였다. 구체적인 것을 이야기 하자면 한도 끝도 없고.. 그냥 느낀점을 이야기 하자면 저자는 최대한 객관성을 유지하려고 노력한 듯 보인다. 저자 자신의 생각을 나열하는 것은 최대한 자제하면서 객관적인 사실을 토대로 판단은 독자들에게 남기려고 애쓴 흔적이 보인다. 저자의 생각을 너무 나열하여 자칫 편향된 사고로 빠질 수 있는 위험성을 최대한 줄이고 독자 스스로 생각할 수 있도록 한 점이 개인적으로는 마음에 든다. 



지난 번 (역사, 경제, 정치, 사회, 윤리)편과 이번 (철학, 과학, 예술 종교, 신비)편을 읽으면서 느꼈던 점을 하나의 키워드로 말하자면 바로 링크(Link)이다. 연관이 거의 없을 것 같은 다양한 분야의 지식 사이에 연결고리를 만들어서 마치 하나의 거대한 유기체적 지식이 형성된 느낌이다. 이렇게 지식들 사이에 연결 고리, 즉 링크를 많이 만들 수록 우리의 사고는 좀 더 창의적으로 발전할 수 있을 거라 생각한다. 




이번 편에서 가장 감명깊게 읽었던 부분을 마지막으로 짧은 서평을 마무리할까 한다. 


신비 편의 의식 파트가 있다. 이 부분에서 칸트의 세계를 현상과 물자체로 나누는 관념론을 바탕으로 세상을 이해하는 우리의 의식에 대해 이야기한다. 즉 우리가 바라보고 이해하고 있는 세계는 현상, 즉 우리 개개인의 지극히 주관적인 감각과 관념을 통해 만들어낸 세계라는 것이다. 탁자위의 컵, 밤하늘의 별, 비틀즈의 Let it be, 달콤한 사과, 빨간색 펜 등은 우리의 감각기관인 시각, 청각, 미각, 촉각, 후각과 기존의 기억과 관념들로 부터 형성된 각자만의 해석으로 만들어진 주관적인 세계이다. 우리가 느끼는 세상은 실제가 아니라는 것이다. 실제 세상은 원자와 분자들의 결합구조와 수많은 전자에너지들이 휘몰아치는 그런 세계일 것이다. 


또한 똑같은 빨간색을 보더라도, 똑같은 사과를 먹더라도 사람들마다 느끼는 정도는 사실 엄청나게 다를 것이다. "빨갛다", "달콤하다"와 같은 우리 감각에 대한 특정 기준에 따른 표현을 공통적으로 하지만, 그 기준이라는 것이 실제로는 사람마다 다를 것이다. 이는 책에서 언급한 색맹 실험에 관한 이야기에서 나타난다. 우리는 굉장히 한정된 감각기관과 한정된 관념을 통해 각자만의 세상을 가지고 있고, 결국 사람들은 자신들만의 거대한 우주를 가지고 있는 것이다. 



의식 파트를 읽으며 들었던 한 가지 생각은 남을 이해한다는 것은 또다른 하나의 커다란 우주를 이해하는 것이다. 이 얼마나 어려운 일인가? 그토록 어려운 일이기에 연인과의 다툼, 가족, 친구들과의 갈등, 나아가 사회, 국가간의 갈등이 끊임 없이 발생하는 것 같다. 


그러나 또 다른 한편으로는 이런 생각도 든다. 이토록 재밌는일이 또 있을까? 다른 우주를 이해한다는 것 말이다

그래서인지, 저자는 아래의 문장으로 책을 마무리 했는지도 모르겠다. 




"인생의 의미와 깊이는 타인과의 대화 속에서 비로소 빛을 낸다."


+ Recent posts