안녕하세요. 지난 포스팅의 넘파이 알고 쓰자 - 아인슈타인 표기법에서는 벡터 및 행렬 간 곱셈을 수행하는 다른 방법에 대해서 알아보았습니다. 오늘 포스팅에서는 행렬로부터 고윳값과 고유벡터를 추출하는 함수에 대해서 소개해드리도록 하겠습니다. 오늘 중점적으로 확인해보실것은 추출하는 함수에 대해서만 보시고 고윳값과 고유벡터에 대한 성질은 나중에 선형대수학을 정리하면 다루도록 하겠습니다.
먼저 가장 간단한 고윳값과 고유벡터를 추출하는 방법은 $\text{det}\left(A - \lambda I\right) = 0$을 만족하는 고윳값 $\lambda$를 구한 뒤 고윳값 $\lambda$에 대응되는 고유벡터 $\nu$는 $A\nu = \lambda \nu$를 만족하는 벡터를 찾으면 됩니다. 그런데 이 계산법은 기본적으로 계산성능이 많이 떨어지기 때문에 넘파이 내부적으로 schur 분해를 이용하여 고윳값과 고유벡터를 찾게 됩니다. schur 분해는 $A = QTQ^{*}$로 분해해주는 방법입니다. 이때, 상삼각행렬인 $T$의 대각성분에는 $A$의 고윳값이 존재하기 때문에 빠르게 계산을 할 수 있습니다.
1. numpy.linalg.eig(a), numpy.linalg.eigvals(a)
eig 함수는 정사각형 행렬 $a$로부터 고윳값과 크기가 1로 정규화된 고유벡터를 반환합니다.
a = np.diag((10, 5, 7))
np.linalg.eig(a)
# (array([10., 5., 7.]),
# array([[1., 0., 0.],
# [0., 1., 0.],
# [0., 0., 1.]]))
위 코드에서 np.diag는 대각행렬을 선언하는 함수입니다. 대각행렬의 좋은 점은 고윳값을 계산할 때 방금처럼 행렬식이나 schur 분해를 할 필요없이 그냥 대각성분이 고윳값이 됩니다. 아주 간단하죠. 그 결과가 출력의 첫번째인 고윳값 배열에 저장됩니다. 각 고윳값에 대응되는 고유벡터는 두번째 출력으로 고유벡터 배열에 저장됩니다.
하지만, eigvals 함수는 정사각형 행렬 $a$를 입력으로 받는 것은 동일하지만 다른 점은 고유벡터는 반환하지 않는 다는 것입니다. 방금과 동일한 예제를 통해 확인해보도록 하겠습니다.
a = np.diag((10, 5, 7))
np.linalg.eigvals(a)
# array([10., 5., 7.])
2. numpy.linalg.eigh(a, UPLO='L'), numpy.linalg.eigvalsh(a, UPLO='L')
이번에는 복소수 에리미트 행렬 $a$, 또는 실수 대칭행렬인 $a$를 계산할 때 유용한 함수입니다. 결론적으로 이 함수 역시 고윳값과 고유벡터를 추출하는 함수라고 보시면 됩니다. eigh 함수와 eigvalsh함수의 차이점은 바로 이전의 eig, eigvals 함수와 동일하게 고유벡터의 반환여부입니다.
a = np.array([[1, -2j], [2j, 5]])
np.linalg.eigh(a)
# (array([0.17157288, 5.82842712]),
# array([[-0.92387953-0.j , -0.38268343+0.j ],
# [ 0. +0.38268343j, 0. -0.92387953j]]))
np.linalg.eigvalsh(a)
# array([0.17157288, 5.82842712])
'Programming > Python' 카테고리의 다른 글
Sympy 알고 쓰자 - 기본 연산 (0) | 2020.11.29 |
---|---|
Sympy 알고 쓰자 - 소개 (0) | 2020.11.27 |
넘파이 알고 쓰자 - Linear Algebra Library 2 : 아인슈타인 표기법 (0) | 2020.11.20 |
넘파이 알고 쓰자 - Linear Algebra Library 1 : Matrix&Vector Product (0) | 2020.11.16 |
넘파이 알고 쓰자 - 덧셈, 곱셈, 뺄셈(Sums, products, differences) (0) | 2020.11.12 |