오늘은 IDL에서 행렬곱을 수행하는 연산자인 #와 ##에 대하여 알아보고자 합니다. 사실 다른 고수들이 작성한 IDL 코드들을 보면 이런 연산자가 많이 사용되는 것을 볼 수 있습니다. 또한 #와 ## 모두 행렬곱, 즉 dot에 해당되는 연산자라는 것도 많이들 아시리라 생각합니다. 그런데 과연 #와 ##의 차이가 무엇인지를 정확히 아시는 분들은 그리 많지 않은 것 같습니다. 이 글을 작성중인 저 조차도 사실 매번 혼란스러웠던 부분이기도 합니다. 그래서 저도 맘먹고 다시 찾아봤고, 이 내용을 함께 공유했으면 하는 차원에서 이 글을 올려봅니다.
우리가 수학(고등학교 수학 또는 선형대수학이겠죠)시간에 가장 먼저 배우는 행렬곱의 방법이 기억나십니까? 아마 앞 행렬의 가로방향(Row) 원소들과 뒷 행렬의 세로방향(Column) 원소들과의 곱의 합을 계산한다는 사실이 어렴풋하게나마 기억이 나실겁니다. 그 방식이 바로 IDL에서는 ## 연산자의 역할입니다. 제가 약간 신경써서 도식적으로 다음과 같은 그림을 만들어봤는데, 보시면 이해가 바로 가실겁니다. 이 그림이면 더 이상의 말로 된 설명은 필요없을 것 같습니다.
그리고 # 연산자의 역할은 그 반대입니다. 이 역시 그림으로 나타내보면 다음과 같습니다.
정리해서 말한다면, ## 연산자는 앞 행렬의 가로방향(Row) 원소들을 뒷 행렬의 세로방향(Column) 원소들과 곱하는 것이고, # 연산자는 앞 행렬의 세로방향(Column) 원소들을 뒷 행렬의 가로방향(Row) 원소들과 곱하는 것이라고 이해하시면 되겠습니다. 이 얘기는 바꿔 말하면 ## 연산자를 사용하는데 있어서 앞 행렬의 가로방향(Row)의 원소 갯수와 뒷 행렬의 세로방향(Column)의 원소 갯수가 서로 같아야 한단 얘기입니다. 그렇지 않으면 행렬곱 자체가 불가능합니다. 앞서 그림의 경우처럼 "3X3 행렬 ## 1X3 행렬"의 연산은 가능하지만, "2X3 행렬 ## 1X3 행렬"과 같은 연산은 성립이 안되는 것이죠. # 연산자에 대해서도 같은 요령으로 생각하면 됩니다.
IDL에서는 행렬곱을 이와 같이 # 또는 ## 연산자를 이용해서 수행합니다. 물론 또 다른 방법도 있는데요. MATRIX_MULTIPLY라는 함수도 있습니다. 단, 이 함수의 경우는 # 연산만이 가능하고, ## 연산은 지원되지 않습니다. 그래서 A # B라는 연산을 수행할 경우에는 MATRIX_MULTIPLY(A, B)와 같이 해줘도 똑같은 결과를 얻게 됩니다. 그리고 이 함수는 A 또는 B 행렬을 전치행렬(Transposed Matrix)로 바꾸는 기능을 지원하는 키워드들도 있습니다. IDL 도움말에 자세히 나와있으니 참조하시면 되겠습니다.
그리고 바로 위에서 언급된 전치행렬을 산출해주는 역할을 하는 TRANSPOSE라는 함수에 관해서도 잠깐 언급해보겠습니다. 이 함수는 행렬의 원소들을 대각방향(Diagonal)을 기준으로 대칭하여 재배치하는 역할을 합니다. 여기서 "대각방향"의 의미는 단위행렬에서 1의 값들이 배치된 방향, 즉 왼쪽 상단에서 오른쪽 하단으로의 방향을 의미합니다. 마치 대각선 방향의 거울을 통하여 자신을 바라보는 것과 유사한 느낌이라고도 비유해볼 수 있습니다. 정확히 얘기하면, (i, j)의 위치에 있던 원소를 (j, i)의 위치로 옮겨놓는 것입니다. 역시 이해를 돕기 위하여 다음과 같이 그림을 한번 그려봤습니다.
따라서 3X2의 구조를 갖는 행렬에 대하여 TRANSPOSE 함수를 적용하면 2X3의 구조를 갖는 행렬로 바뀝니다. 참고로 알아두시면 좋을 것 같습니다.
'IDL > Math' 카테고리의 다른 글
| IDL에서 적분을 해봅시다 (Part 2) (0) | 2013.11.04 |
|---|---|
| KRIG2D 함수의 속도 개선 [Updated] (0) | 2013.10.11 |
| IDL에서 적분을 해봅시다 (Part 1) (0) | 2013.09.23 |
| IDL로 연립방정식을 풀어봅시다 (0) | 2013.09.17 |
| Spline Interpolation (0) | 2013.09.11 |