학교 다닐 때 행렬로 연립방정식 풀었던 기억이 날 듯 합니다. 선형대수(Linear Algebra)는 통계, 기계학습, 공학, 영상/이미지 처리 등 여러 분야에서 활용이 됩니다. 선형대수를 전부 다루려면 너무나 방대하므로, 이번 포스팅에서는 Python의 NumPy에 있는 선형대수(Linear Algebra) 함수들 중에서 자주 사용하는 함수에 대해서만 선별적으로 소개하겠습니다. 그리고 선형대수의 이론적인 부분은 별도로 참고할 수 있는 링크를 달도록 하겠습니다. 


  • 대각행렬 (Diagonal matrix): np.diag(x)
  • 내적 (Dot product, Inner product): np.dot(a, b)
  • 대각합 (Trace): np.trace(x)
  • 행렬식 (Matrix Determinant): np.linalg.det(x)
  • 역행렬 (Inverse of a matrix): np.linalg.inv(x)
  • 고유값 (Eigenvalue), 고유벡터 (Eigenvector): w, v = np.linalg.eig(x)
  • 특이값 분해 (Singular Value Decomposition): u, s, vh = np.linalg.svd(A)
  • 연립방정식 해 풀기 (Solve a linear matrix equation): np.linalg.solve(a, b)
  • 최소자승 해 풀기 (Compute the Least-squares solution): m, c = np.linalg.lstsq(A, y, rcond=None)[0]






  1. 대각행렬 (Diagonal matrix): np.diag(x)


대각행렬은 대각성분 이외의 모든 성분이 모두 '0'인 n차 정방행렬을 말합니다. 아래 예시의 행렬에서 빨간색으로 표시한 원소를 '0'으로 바꾼 행렬이 대각행렬입니다. 


* 참고 링크 : http://rfriend.tistory.com/141


 

In [1]: import numpy as np


In [2]: x = np.arange(9).reshape(3, 3)


In [3]: print(x)

[[0 1 2]

 [3 4 5]

 [6 7 8]]


In [4]: np.diag(x)

Out[4]: array([0, 4, 8])


In [5]: np.diag(np.diag(x))

Out[5]:

array([[0, 0, 0],

        [0, 4, 0],

        [0, 0, 8]])





  2. 내적 (Dot product, Inner product): np.dot(a, b), a.dot(b)


matrix dot product, inner product, scalar product, projection product

Python에서 '*' 를 사용한 두 행렬 간 곱은 원소 간 곱(element-wise product)을 반환하며, 선형대수에서 말하는 행렬 간 내적 곱을 위해서는 np.dot() 함수를 이용해야 합니다. 


원소 간 곱 (element-wise product)

: a*b

내적 (dot product, inner product)

: np.dot(a, b)

 

In [6]: a = np.arange(4).reshape(2, 2)


In [7]: print(a)

[[0 1]

 [2 3]]


In [8]: a*a

Out[8]:

array([[0, 1],

        [4, 9]])


In [6]: a = np.arange(4).reshape(2, 2)


In [7]: print(a)

[[0 1]

 [2 3]]


In [9]: np.dot(a, a)

Out[9]:

array([[ 2, 3],

        [ 6, 11]])



np.dot(a, b) NumPy 함수와 a.dot(b)의 배열 메소드의 결과는 동일합니다. 



In [10]: a.dot(a)

Out[10]:

array([[ 2, 3],

        [ 6, 11]])

 




  3. 대각합 (Trace): np.trace(x)


정방행렬의 대각에 위치한 원소를 전부 더해줍니다. 

아래의 2차 정방행렬 예의 대각합은 0+5+10+15 = 30 이 됩니다. (파란색으로 표시함)



In [12]: b = np.arange(16).reshape(4, 4)


In [13]: print(b)

[[ 0 1 2 3]

 [ 4 5 6 7]

 [ 8 9 10 11]

 [12 13 14 15]]


In [14]: np.trace(b)

Out[14]: 30

 



3차원 행렬에 대해서도 대각합을 구할 수 있습니다. 2차원은 대각선 부분의 원소 값을 전부 더하면 되지만 3차원 행렬에서는 대각(diagonal)이 어떻게 되나 좀 헷갈릴 수 있겠습니다. 아래의 3차원 행렬의 대각합을 구하는 예를 살펴보면, [0+12+24, 1+13+25, 2+14+26] = [36, 39, 42] 가 됩니다. 



In [15]: c = np.arange(27).reshape(3, 3, 3)


In [16]: print(c)

[[[ 0 1 2]

  [ 3 4 5]

  [ 6 7 8]]


 [[ 9 10 11]

  [12 13 14]

  [15 16 17]]


 [[18 19 20]

  [21 22 23]

  [24 25 26]]]


In [17]: np.trace(c)

Out[17]: array([36, 39, 42])

 




  4. 행렬식 (Matrix Determinant): np.linalg.det(x)


역행렬이 존재하는지 여부를 확인하는 방법으로 행렬식(determinant, 줄여서 det)이라는 지표를 사용합니다. 이 행렬식이 '0'이 아니면 역행렬이 존재하고, 이 행렬식이 '0'이면 역행렬이 존재하지 않습니다. 


* 참고 링크 : http://rfriend.tistory.com/142


아래의 예에서 array([[1, 2], [3, 4]]) 의 행렬식이 '-2.0'으로서, '0'이 아니므로 역행렬이 존재한다고 판단할 수 있습니다. 



In [18]: d = np.array([[1, 2], [3, 4]])


In [19]: np.linalg.det(a)

Out[19]: -2.0

 




  5. 역행렬 (Inverse of a matrix): np.linalg.inv(x)


역행렬은 n차정방행렬 Amn과의 곱이 항등행렬 또는 단위행렬 In이 되는 n차정방행렬을 말합니다. A*B 와 B*A 모두 순서에 상관없이 곱했을 때 단위행렬이 나오는 n차정방행렬이 있다면 역행렬이 존재하는 것입니다.

역행렬은 가우스 소거법(Gauss-Jordan elimination method), 혹은 여인수(cofactor method)로 풀 수 있습니다. 




In [20]: a = np.array(range(4)).reshape(2, 2)


In [21]: print(a)

[[0 1]

 [2 3]]


In [22]: a_inv = np.linalg.inv(a)


In [23]: a_inv

Out[23]:

array([[-1.5, 0.5],

        [ 1. , 0. ]])




위의 예제에서 np.linalg.inv() 함수를 사용하여 푼 역행렬이 제대로 푼 것인지 확인을 해보겠습니다. 역행렬의 정의에 따라서 원래의 행렬에 역행렬을 곱하면, 즉, a.dot(a_inv) 또는 np.dot(a, a_inv) 를 하면 단위행렬(unit matrix)가 되는지 확인해보겠습니다. 



In [24]: a.dot(a_inv)

Out[24]:

array([[1., 0.],

         [0., 1.]])

 




  6. 고유값 (Eigenvalue), 고유벡터 (Eigenvector): w, v = np.linalg.eig(x)


정방행렬 A에 대하여 Ax = λx  (상수 λ) 가 성립하는 0이 아닌 벡터 x가 존재할 때 상수 λ 를 행렬 A의 고유값 (eigenvalue), x 를 이에 대응하는 고유벡터 (eigenvector) 라고 합니다. 


np.linalg.eig() 함수는 고유값(eigenvalue) w, 고유벡터(eigenvector) v 의 두 개의 객체를 반환합니다. 


In [25]: e = np.array([[4, 2],[3, 5]])


In [26]: print(e)

[[4 2]

[3 5]]


In [27]: w, v = np.linalg.eig(e)


#  w: the eigenvalues lambda

In [28]: print(w)

[2. 7.]


# v: the corresponding eigenvectors, one eigenvector per column

In [29]: print(v)

[[-0.70710678 -0.5547002 ]

[ 0.70710678 -0.83205029]]

 



고유벡터는 배열 인덱싱하는 방법을 사용해서 각 고유값에 대응하는 고유벡터를 선택할 수 있습니다. 



# eigenvector of eigenvalue lambda 2

In [30]: print(v[:, 0]

[-0.70710678 0.70710678]


# eigenvector of eigenvalue labmda 7

In [31]: print(v[:, 1]

[-0.5547002 -0.83205029]

 




  7. 특이값 분해 (Singular Value Decomposition): u, s, vh = np.linalg.svd(A)


특이값 분해는 고유값 분해(eigen decomposition)처럼 행렬을 대각화하는 한 방법으로서, 정방행렬뿐만 아니라 모든 m x n 행렬에 대해 적용 가능합니다. 특이값 분해는 차원축소, 데이터 압축 등에 사용할 수 있습니다. 이론적인 부분은 설명하자면 너무 길기 때문에 이 포스팅에서는 설명하지 않겠으며, 아래의 링크를 참고하시기 바랍니다. 


* 참고 링크 : http://rfriend.tistory.com/185


아래의 np.linalg.svd(A) 예제는 위의 참고 링크에서 사용했던 예제와 동일한 것을 사용하였습니다. 


In [32]: A = np.array([[3,6], [2,3], [0,0], [0,0]])


In [33]: print(A)

[[3 6]

 [2 3]

 [0 0]

 [0 0]]


In [34]: u, s, vh = np.linalg.svd(A)


In [35]: print(u)

[[-0.8816746 -0.47185793 0. 0. ]

 [-0.47185793 0.8816746 0. 0. ]

 [ 0. 0. 1. 0. ]

 [ 0. 0. 0. 1. ]]


In [36]: print(s)

[7.60555128 0.39444872]


In [37]: print(vh)

[[-0.47185793 -0.8816746 ]

 [ 0.8816746 -0.47185793]]

 




  8. 연립방정식 해 풀기 (Solve a linear matrix equation): np.linalg.solve(a, b)


아래의 두 개 연립방정식의 해(x0, x1)를 np.linalg.solve(a, b) 함수를 사용하여 풀어보겠습니다. 



위의 연립방정식을 어떻게 행렬로 입력하고, np.linalg.solve(a, b)에 입력하는지 유심히 살펴보시기 바랍니다. 



In [38]: a = np.array([[4, 3], [3, 2]])


In [39]: b = np.array([23, 16])


In [40]: x = np.linalg.solve(a, b)


In [41]: print(x)

[2. 5.]

 



NumPy 가 제대로 x0, x1의 해를 풀었는지 확인해보겠습니다. x0=2, x1=5 가 해 맞네요!



In [42]: np.allclose(np.dot(a, x), b)

Out[42]: True

 




  9. 최소자승 해 풀기 (Compute the Least-squares solution)

     : m, c = np.linalg.lstsq(A, y, rcond=None)[0]


회귀모형 적합할 때 최소자승법(Least-squares method)으로 잔차 제곱합을 최소화하는 회귀계수를 추정합니다. 


* 참고 링크 : https://docs.scipy.org/doc/numpy/reference/generated/numpy.linalg.lstsq.html



아래의 예에서는 회귀계수 m, y절편 c를 최소자승법을 사용해서 구해보겠습니다. 



In [43]: x = np.array([0, 1, 2, 3])


In [44]: y = np.array([-1, 0.2, 0.9, 2.1])


In [45]: A = np.vstack([x, np.ones(len(x))]).T


In [46]: A

Out[46]:

array([[0., 1.],

        [1., 1.],

        [2., 1.],

        [3., 1.]])


In [47]: m, c = np.linalg.lstsq(A, y, rcond=None)[0]


In [48]: print(m, c)

0.9999999999999999 -0.9499999999999997

 



아래의 그래프에서 점은 원래의 데이터이며, 빨간색 선은 최소자승법으로 추정한 회귀식의 적합선이 되겠습니다. 



In [49]: import matplotlib.pyplot as plt

    ...: plt.plot(x, y, 'o', label='Original data', markersize=10)

    ...: plt.plot(x, m*x + c, 'r', label='Fitted line')

    ...: plt.legend()

    ...: plt.show()




많은 도움이 되었기를 바랍니다. 


Posted by R Friend R_Friend

지난 포스팅에서는 가우스 소거법(Gauss-Jordan elimination method)을 활용한 역행렬 계산방법을 알아보았습니다. (☞ 바로가기)

 

이번 포스팅에서는 여인수(cofactor)를 이용한 역행렬(the inverse of a matrix, invertible matrix) 계산 방법에 대하여 소개하도록 하겠습니다.

 

 

이를 이해하기 위해서는 (1) 소행렬식(minor determinant), (2) 여인수(cofactor), (3) 수반행렬(adjoint matrix)에 대해서 먼저 알아보고 나서, 그 다음에 (4) 여인수를 이용한 역행렬 계산 방법을 소개하겠습니다.

 

 

 

 

(1) 제 (i, j) 소행렬식 (minor determinant)

 

제 (i, j) 소행렬식이란 n차정방행렬의 i행과 j열을 제거하고 만든 부분행렬의 행렬식(determinant)을 말합니다.  i행과 j열이 제거되어서 원래 행렬 A보다 행과 열이 하나씩 작아진 행렬을 가지고 행렬식을구하기 때문에 소행렬식(minor determinant, minor of entry aij)이라고 부릅니다.

 

 

 

아래 3*3 행렬식 A를 예로 들어서 소행렬식을 풀어보겠습니다.

 

 

 

 

위의 9개 소행렬식 중에서 "제(1, 1) 소행렬식"을 어떻게 구했는지에 대해서 이미지로 표시해보면 아래와 같습니다.  아래의 방식을 9개 소행렬식 모두에 차례로 적용한 것입니다.

 

 

R로 행렬식 값 구할 때는 det() 함수를 사용합니다.

 

 
> # determinant : det()
> M11 <- matrix(c(1, 2, 0, 4), byrow = TRUE, nrow = 2)
> det(M11)
[1] 4

 

 

 

참고로, 2차정방행렬과 3차정방행렬의 행렬식(determinant) 구하는 공식은 아래와 같습니다.

 

 

 

(2) 여인수 (cofactor)

 

여인수는 제(i, j) 소행렬식에 (-1)^(i+j)를 곱한 것이며, cofactor의 앞 대문자를 따서 Cij 로 표기합니다.

(Mij 는 소행렬식, minor determinant) 

 

 

[ 여인수 정의 (definition of cofactor) ]

 

 

 

[ 여인수 행렬 (matrix of cofactors) ]

 

아래에 3 by 3 행렬 A의 여인수를 구하는 예를 들어보았습니다.  위에 (1)번에서 구해봤던 소행렬식(minor determinant) Mij에 (-1)^(i+j) 를 곱하면 제(i, j) 여인수가 됩니다.

 

 

 

 

 

 

(3) 수반행렬 (adjoint matrix)

 

수반행렬(adjoint matrix)은 여인수 행렬(matrix of cofactors)의 전치행렬(transpose matrix)를 말하며, adjoint matrix의 앞글자를 따서 adj(A)라고 표기합니다.

 

 

[ 여인수 행렬(matrix of cofactors)과 수반행렬 (adjoint matrix)의 관계 ]

 

 

위의 3 by 3 행렬 A에 대해서 여인수 행렬(matrix of cofactors) Cij를 바로 위에서 풀어보았는데요, 이 여인수행렬의 전치행렬(transpose matrix)인 수반행렬(adjoint matrix) 예시를 아래에 제시해보았습니다.

 

 

 

 

 

(4) 여인수를 활용한 역행렬 계산 (invertible matrix by using cofactors)

 

여인수를 활용한 역행렬 계산 방식은 아래와 같습니다.  아래 공식처럼 역행렬(the inverse of a matrix)은 수반행렬(adjoint matrix)를 행렬식(determinant)으로 나눈 값입니다.  왜 위에서 소행렬식, 여인수, 수반행렬을 먼저 차례로 살펴보았는지 이제야 이해하실 수 있을 것입니다.

 

 

 

 

위에서 줄곧 예시로 들었던 3 by 3 정방행렬 A에 대해 여인수를 활용한 역행렬을 구해보면 아래와 같습니다.

 

 

[ 여인수를 활용한 역행렬 계산 예시

(example of invertible matrix caculation by using cofactor) ]

   

 

 

 

 

위의 역행렬 계산 문제를 R의 MASS패키지 내 ginv() 함수로 풀어보면 아래와 같습니다.

 

 

> # the inverse of a matrix, invertible matrix
> A <- matrix(c(1, 0, 1, 0, 1, 2, -1, 0, 4), byrow = TRUE, nrow = 3)
> A
     [,1] [,2] [,3]
[1,]    1    0    1
[2,]    0    1    2
[3,]   -1    0    4
> library(MASS)
> options(digits=2)
> ginv(A)
     [,1]     [,2] [,3]
[1,]  0.8 -3.3e-16 -0.2
[2,] -0.4  1.0e+00 -0.4
[3,]  0.2  0.0e+00  0.2

 

 

 

R base패키지의 solve() 함수를 이용해서 역행렬을 구해도 결과는 동일합니다.

 

 

> A <- matrix(c(1, 0, 1, 0, 1, 2, -1, 0, 4), byrow = TRUE, nrow = 3)
> A
     [,1] [,2] [,3]
[1,]    1    0    1
[2,]    0    1    2
[3,]   -1    0    4
> solve(A)
     [,1] [,2] [,3]
[1,]  0.8    0 -0.2
[2,] -0.4    1 -0.4
[3,]  0.2    0  0.2

 

 

 

R로 단 1줄이면 풀어지는 문제에 대해서 컴퓨터는 뒤에서 안보이게 위에서 소개했던 절차들, 즉, 소행렬식, 여인수, 수반행렬을 구하고 그 다음에 역행렬을 구하는 과정을 거쳤을 것입니다.  우리 대신 일해주는 컴퓨터가 있어서 얼마나 좋은 세상인지 모르겠습니다. 

 

많은 도움 되었기를 바랍니다. 

 

행렬, 벡터 관련 포스팅은 아래 링크를 걸어놓았습니다.

 

행렬 기본 이해

특수한 형태의 행렬

가우스 소거법을 활용한 역행렬 계산

행렬의 기본 연산 (+, -, *, /, ^, %*%, colMeans(), rowMeans(), colSums(), rowSums()) 

벡터의 기본 이해와 연산 (vector: addition, subtraction, multiplication by scalar)

벡터의 곱 (1) 내적 (inner product, dot product, scalar product, projection product)

벡터의 곱 (2) 외적 (outer product, cross product, vector product, tensor product)

 

 

이번 포스팅이 도움이 되었다면 아래의 공감 ♡ 꾸욱~ 눌러주세요. ^^







Posted by R Friend R_Friend

지난번 포스팅에서는 특수한 형태의 행렬, 제로행렬(zero matrix), 전치행렬 (transpose matrix), 대칭행렬 (symmetric matrix), 상삼각행렬 (upper triangular matrix), 하삼각행렬 (lower triangular matrix), 대각행렬 (diagonal matrix), 항등행렬 또는 단위행렬 (identity matrix, I, or unit matrix, U) 등에 대해서 알아보았습니다.

 

이번 포스팅에서는 역행렬(the inverse of a matrix, invertible matrix)에 대해서 소개하겠습니다.  역행렬은 사용처가 많은 중요한 개념이므로, 아래의 정의, 계산 방법, 존재 여부 확인하는 방벙을 숙지하면 좋겠습니다.

 

 

  • 역행렬 (the inverse of a matrix, invertible matrix)

 

역행렬은 n차정방행렬 Amn과의 곱이 항등행렬 또는 단위행렬 In이 되는 n차정방행렬을 말합니다. A*B 와 B*A 모두 순서에 상관없이 곱했을 때 단위행렬이 나오는 n차정방행렬이 있다면 역행렬이 존재하는 것입니다.

 

 

 

아래에 예를  하나 들어봤습니다.

 

 

역행렬은 (1) 가우스 소거법(Gauss-Jordan elimination method), (2) 여인수(cofactor)를 이용해서 풀 수 있습니다. 여인수를 이용한 방법은 복잡해서 보통 가우스 소거법을 주로 사용하는데요, 이번 포스팅에서는 먼저 가우스 소거법을 소개하고, 다음번 포스팅에서 여인수(cofactor)를 이용한 역행렬 구하는 방법을 알아보겠습니다.

 

가우스 소거법은 기본행연산(elementary row operation)을 이용하여 위의 행렬의 곱의 왼쪽 행렬을 단위행렬로 바꾸어가는 과정이라고 보면 되겠습니다. 



[참고] 기본 행연산 (elementary row operation)


   1. 행렬의 한 행을 상수배한다. 

   2. 행렬의 두 행을 맞바꾼다. 

   3. 한 행을 상수배하여 다른 행에 더한다. 


 

 

[ 가우스 소거법 예시 (Gauss-Jordan elimination method) ]

 

 

 

 

 

R로 역행렬을 풀때는 MASS 패키지의 ginv() 함수를 사용합니다.

 

> # the inverse of a matrix, invertible matrix
> raw_data <- c(1, 2, 3, 4)
> A_1 <- matrix(raw_data, byrow=TRUE, nrow=2)
> A_1
     [,1] [,2]
[1,]    1    2
[2,]    3    4
> library(MASS)
> ginv(A_1)
     [,1] [,2]
[1,] -2.0  1.0
[2,]  1.5 -0.5
> A_1%*%ginv(A_1)
             [,1]          [,2]
[1,] 1.000000e+00 -6.661338e-16
[2,] 8.881784e-16  1.000000e+00

 

 

 

base 패키지의 solve() 함수를 사용해도 동일합니다.

 

> solve(A_1)

      [,1] [,2]

[1,] -2.0  1.0

[2,]  1.5 -0.5



 

 

역행렬이 존재하는 n차정방행렬을 정칙행렬(nonsingular matrix)라고 하며, 역행렬이 존재하지 않는 행렬을 특이행렬(singular matrix)라고 합니다.

 

 

역행렬이 존재하는지 여부를 확인하는 방법으로 행렬식(determinant, 줄여서 det)이라는 지표를 사용하는데요, 이 행렬식이 '0'이 아니면 역행렬이 존재하고, 이 행렬식이 '0'이면 역행렬이 존재하지 않습니다.

 

 

[ 역행렬이 존재하는 조건 : det(A) ≠ 0 ]

 

 

 

 

행렬식의 값은 n값에 따라서 달라지는데요, 2차와 3차정방행렬의 행렬식 구하는 공식만 아래에 소개하도록 하겠습니다.

 

 

[ 2차, 3차정방행렬의 행렬식 공식, SARRUS method ]

 

 

 

 

2차정방행렬의 경우 역행렬이 존재하는지를 확인하고 역행렬을 구하는 간단한 공식이 있는데요, 아래 식을 참고하시기 바랍니다.  아래와 같은 공식은 2차정방행렬에만 존재하므로, 3차 이상의 연립방정식을 풀려면 위에서 소개한 가우스 소거법은 알아두시는게 좋겠습니다.

 

 

 

다음번 포스팅에서는 여인수(cofactor)를 이용한 역행렬 계산 방법(☞ 바로가기) 에 대해서 소개하겠습니다.

 

많은 도움이 되었기를 바랍니다.

 

행렬, 벡터 관련 포스팅은 아래 링크를 걸어놓았습니다.

 

행렬 기본 이해

특수한 형태의 행렬

여인수를 활용한 역행렬 계산

행렬의 기본 연산 (+, -, *, /, ^, %*%, colMeans(), rowMeans(), colSums(), rowSums())

벡터의 기본 이해와 연산 (vector: addition, subtraction, multiplication by scalar)

벡터의 곱 (1) 내적 (inner product, dot product, scalar product, projection product)

벡터의 곱 (2) 외적 (outer product, cross product, vector product, tensor product)


 

이번 포스팅이 도움이 되었다면 아래의 공감 ♡ 꾸욱~ 눌러주세요. ^^


Posted by R Friend R_Friend

지난번 포스팅에서는 행렬의 뜻, 형태, 표기법, R로 입력하는 방법에 대해서 소개하였습니다.

 

이번 포스팅에서는 특수한 형태의 행렬, 제로행렬(zero matrix), 전치행렬 (transpose matrix), 대칭행렬 (symmetric matrix), 상삼각행렬 (upper triangular matrix), 하삼각행렬 (lower triangular matrix), 대각행렬 (diagonal matrix), 항등행렬 또는 단위행렬 (identity matrix, I, or unit matrix, U)의 7가지에 대하여 차례대로 알아보겠습니다.  

 

아래에 소개하는 행렬 형태와 표기법도 잘 기억해두시면 나중에 유용할 거예요. 특히 전치행렬, 대각행렬, 단위행렬, 역행렬은 자주 사용하는 편이니 잘 기억해두면 좋겠습니다.

 

 

 

 

(1) 제로행렬 (zero matrix or null matrix)

 

모든 성분이 '0'인 행렬을 제로행렬, 또는 영행렬이라고 합니다.

 

 

 
> # zero matrix
> A_zero <- matrix(c(0, 0, 0, 0, 0, 0, 0, 0, 0), byrow = TRUE, nrow = 3)
> A_zero
     [,1] [,2] [,3]
[1,]    0    0    0
[2,]    0    0    0
[3,]    0    0    0
> 
> B_zero <- matrix(rep(0, 9), byrow = TRUE, nrow = 3)
> B_zero
     [,1] [,2] [,3]
[1,]    0    0    0
[2,]    0    0    0
[3,]    0    0    0

 

 

 

 

 

(2) 전치행렬 (transpose matrix)

 

행이 m개, 열이 n개인 m * n 행렬 (m by n matrix) 의 행과 열을 서로 바꾼 n * m 행렬 (n by m matrix)를 전치행렬이라고 합니다. 아래에 동그라미로 표시한 행렬의 성분들이 전치를 했을 때 서로 어디로 위치가 바뀌었는지를 유심히 살펴보시기 바랍니다.

 

 

 

 

전치행렬은 행렬 우측 상단에 대문자 'T'를 표기합니다.  아래 표기 예시를 참조하세요.

 

 

 
> # transpose matrix
> A <- matrix(c(1, 2, 3, 4, 5, 6, 7, 8, 9), byrow = TRUE, nrow = 3)
> A
     [,1] [,2] [,3]
[1,]    1    2    3
[2,]    4    5    6
[3,]    7    8    9
> 
> A_t <- t(A)
> A_t
     [,1] [,2] [,3]
[1,]    1    4    7
[2,]    2    5    8
[3,]    3    6    9
> 
> 
> B <- matrix(c(4, 5,  6, 7, 8, 9), nc=3)
> B
     [,1] [,2] [,3]
[1,]    4    6    8
[2,]    5    7    9
> 
> B_t <- t(B)
> B_t
     [,1] [,2]
[1,]    4    5
[2,]    6    7
[3,]    8    9

 

 

 

 

 

 

(3) 대칭행렬 (symmetric matrix)

 

대칭행렬이란 대각성분을 중심으로 대칭인 n차정방행렬로서, 원래 행렬과 전치행렬이 동일한 경우를 의미합니다. (* wikipedia : a symmetric matrix is a square matrix that is equal to its transpose)

 

 

 

 

 

 

> # symmetric matrix
> s <- matrix(c(1:25), 5)
> s
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    6   11   16   21
[2,]    2    7   12   17   22
[3,]    3    8   13   18   23
[4,]    4    9   14   19   24
[5,]    5   10   15   20   25
> 
> lower.tri(s, diag=FALSE)
      [,1]  [,2]  [,3]  [,4]  [,5]
[1,] FALSE FALSE FALSE FALSE FALSE
[2,]  TRUE FALSE FALSE FALSE FALSE
[3,]  TRUE  TRUE FALSE FALSE FALSE
[4,]  TRUE  TRUE  TRUE FALSE FALSE
[5,]  TRUE  TRUE  TRUE  TRUE FALSE
> s[lower.tri(s, diag=FALSE)]
 [1]  2  3  4  5  8  9 10 14 15 20
> t(s)[lower.tri(s, diag=FALSE)]
 [1]  6 11 16 21 12 17 22 18 23 24
> 
> s[lower.tri(s, diag=FALSE)] = t(s)[lower.tri(s, diag=FALSE)]
> s
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    6   11   16   21
[2,]    6    7   12   17   22
[3,]   11   12   13   18   23
[4,]   16   17   18   19   24
[5,]   21   22   23   24   25

 

 

 

 

 

(4) 상삼각행렬 (upper triangular matrix)

 

 상삼각행렬은 대각성분 아래의 성분이 모두 '0'인 n차정방행렬입니다.  아래의 색깔 칠해놓은 행렬 예를 보면 금방 이해할 수 있을 거예요.

 

 

R의 base패키지 내 lower.tri(x, diag=FALSE) 함수를 이용하여 상삼각행렬(upper triangular matrix)를 아래에 만들어보았습니다.

 

 

> # upper triangular matrix
> (m_upper <- matrix(1:20, 4, 4))
     [,1] [,2] [,3] [,4]
[1,]    1    5    9   13
[2,]    2    6   10   14
[3,]    3    7   11   15
[4,]    4    8   12   16
> 
> lower.tri(m_upper, diag=FALSE)
      [,1]  [,2]  [,3]  [,4]
[1,] FALSE FALSE FALSE FALSE
[2,]  TRUE FALSE FALSE FALSE
[3,]  TRUE  TRUE FALSE FALSE
[4,]  TRUE  TRUE  TRUE FALSE
> m_upper[lower.tri(m_upper, diag=FALSE)] <- c(0)
> m_upper
     [,1] [,2] [,3] [,4]
[1,]    1    5    9   13
[2,]    0    6   10   14
[3,]    0    0   11   15
[4,]    0    0    0   16

 

 

 

 

 

(5) 하삼각행렬 (lower triangular matrix)

 

하삼각행렬은 대각성분 위의 성분이 모두 '0'인 n차정방행렬로서, 상삼각행렬과 '0'이 있는 위치가 대각선으로 반대임을 알 수 있습니다.

 

 

R의 base패키지 내 upper.tri(x, diag=FALSE) 함수를 이용하여 하삼각행렬(lower triangular matrix)를 아래에 만들어보았습니다. 

 

 
> # lower triangular matrix
> (m_lower <- matrix(1:20, 4, 4))
     [,1] [,2] [,3] [,4]
[1,]    1    5    9   13
[2,]    2    6   10   14
[3,]    3    7   11   15
[4,]    4    8   12   16
> 
> upper.tri(m_lower, diag=FALSE)
      [,1]  [,2]  [,3]  [,4]
[1,] FALSE  TRUE  TRUE  TRUE
[2,] FALSE FALSE  TRUE  TRUE
[3,] FALSE FALSE FALSE  TRUE
[4,] FALSE FALSE FALSE FALSE
> m_lower[upper.tri(m_lower, diag=FALSE)] <- c(0)
> m_lower
     [,1] [,2] [,3] [,4]
[1,]    1    0    0    0
[2,]    2    6    0    0
[3,]    3    7   11    0
[4,]    4    8   12   16

 

 

 

 

 

(6) 대각행렬 (diagonal matrix)

 

대각행렬은 대각성분 이외의 모든 성분이 모두 '0'인 n차정방행렬을 말하며, 아래 예의 대각행렬의 경우 대각성분만을 따다가 diag(1, 2, 3, 4)로 표기합니다.

(* wikipedia : a diagonal matrix is a matrix (usually a square matrix) in which the entries outside the main diagonal (↘) are all zero. The diagonal entries themselves may or may not be zero.)

 

 

 

위에서 소개했던 제로행렬(zero matrix)과 바로 아래에 소개할 단위행렬(unit matrix) 또는 항등행렬(identity matrix)도 대각행렬(diagonal matrix)에 속한다고 할 수 있겠습니다.

 

그리고 대각행렬은 상삼각행렬(upper triangular matrix) 또는 하삼각행렬(lower triangular matrix)에 속한다고도 할 수 있겠습니다.

 

 

R의 diag(A) 함수를 사용해서 위의 diag(1, 2, 3, 4) 대각행렬을 만들어보겠습니다.

 

 

 

> # diagonal matrix
> A <- c(1, 2, 3, 4)
> diag(A)
     [,1] [,2] [,3] [,4]
[1,]    1    0    0    0
[2,]    0    2    0    0
[3,]    0    0    3    0
[4,]    0    0    0    4
 

 

 

 

대각행렬의 곱셉, P승은 아래와 같이 각 성분의 P승이 되는 재미있는, 유용한 특성을 가지고 있습니다.

 

 

 

 

 

(7) 항등행렬 또는 단위행렬 (identity matrix, I, or unit matrix, U)

 

항등행렬 또는 단위행렬은 대각성분이 모두 '1'이고 그 이외의 모든 성분은 '0'인 n차정방행렬을 말하며, identity matrix 의 첫 대문자를 따서 'I' 로 표기하거나 unit matrix의 첫 대문자를 따서 'U'로 표기합니다. (일부 수학책에서는 독일어 Einheits matrix의 첫 대문자를 따서 'E'로 표기하기도 함)

 

(* wikipedia : the identity matrix or unit matrix of size n is the n × n square matrix with ones on the main diagonal and zeros elsewhere)

 

 

 

항등행렬 또는 단위행렬 In을 행렬 Amn 에 곱하면 그대로 Amn이 됩니다.  어떤 수에 '1'을 곱하면 그대로 원래의 수가 되기 때문입니다.

 

 

 

 

R의 diag(k) 함수로 k by 항등행렬 또는 단위행렬을 만들 수 있습니다.

 

 

> # identity matrix or unit matrix : diag(k) > 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

> 

> diag(6) [,1] [,2] [,3] [,4] [,5] [,6] [1,] 1 0 0 0 0 0 [2,] 0 1 0 0 0 0 [3,] 0 0 1 0 0 0 [4,] 0 0 0 1 0 0 [5,] 0 0 0 0 1 0 [6,] 0 0 0 0 0 1

 

 

 

 

항등행렬 또는 단위행렬의 역행렬(inverse matrix, 바로 아래에 설명)은 단위행렬입니다.  단위행렬과 역행렬은 매우 중요한 행렬이므로 꼭 잘 이해를 해두시는게 좋습니다.

 

 

다음번 포스팅에서는 역행렬(the inverse of a matrix, invertible matrix)에 대해서 소개하겠습니다.

 

많은 도움이 되었기를 바랍니다.

 

행렬, 벡터 관련 이전 포스팅은 아래 링크를 걸어놓았습니다.

 

행렬 기본 이해

가우스 소거법을 활용한 역행렬 계산

여인수를 활용한 역행렬 계산

행렬의 기본 연산 (+, -, *, /, ^, %*%, colMeans(), rowMeans(), colSums(), rowSums())

벡터의 기본 이해와 연산 (vector: addition, subtraction, multiplication by scalar)

벡터의 곱 (1) 내적 (inner product, dot product, scalar product, projection product)

벡터의 곱 (2) 외적 (outer product, cross product, vector product, tensor product)


 

이번 포스팅이 도움이 되었다면 아래의 공감 ♡ 꾸욱~ 눌러주세요. ^^

 

Posted by R Friend R_Friend