본 글은 [장철원 저 - 선형대수와 통계학으로 배우는 머신러닝 with 파이썬]을 읽고, 개인적으로 찾아본 내용을 더해 정리한 글입니다.
본 글에 나오는 소스코드들의 원본은 출판사의 github 레포지토리(https://github.com/bjpublic/LinearAlgebra) 에서 찾아볼 수 있습니다.
까먹었을 때 바로바로 확인하기 위한 용도로 정리하는 것이기에, 제 필요에 따라 생략, 변형 및 추가된 내용이 많습니다.
책의 내용을 그대로 담지 않도록 노력하였으나, 혹여 문제가 있다면 cuffyluv.1@gmail.com으로 연락주시기 바랍니다.
이번 챕터부턴 파이썬 실습은 기록하지 않고 넘파이 실습만 기록할 거임 또는 이마저도 생략할 수 있음(너무 길고 비효율적 + 어차피 책에 있는 데 옮겨적기밖에 되지 않음)
1. 전치 행렬(transposed matrix)
: 기존 행렬의 행과 열을 바꾼 행렬
여담) transpose : (타동사, 격식) (순서를) 뒤바꾸다
- 주의 : (AB)^T = B^T A^T 임에 주의!!
즉, 행렬 A와 B를 행렬곱한 후 전치 행렬을 구하는 건, B와 A 순서로 각각 전치 행렬을 구해 둘을 행렬곱한 것과 같다.
# 전치 행렬 넘파이
A = np.array([[1, 5],[3, 4],[6, 2]])
# 방법 1 : 정석
At = np.transpose(A)
print(At)
# 방법 2 : numpy.ndarray.T 라는 내장 메서드를 사용.
At = A.T
print(At)
'''
numpy.ndarray.T에 대해서는 공식 문서 참고
<https://numpy.org/doc/stable/reference/generated/numpy.ndarray.T.html>
'''
2. 대칭 행렬(symmetric matrix)
: 기존 행렬과 전치 행렬이 동일한 정사각 행렬 (A = A^T)
- 대칭 행렬의 성질
→ 대칭 행렬끼리 더하거나 빼도 대칭 행렬
→ 대칭 행렬끼리 행렬곱한 건 반드시 대칭 행렬은 아님.
→ 대칭 행렬의 거듭제곱도 대칭 행렬
→ 임의의 행렬에 대해 A곱A^T를 하면 무조건 대칭 행렬.
- 여담) 파이썬에서 두 객체의 주소값이 같으면 무조건 같은 객체인거임!!!
→ 두 리스트를 ‘==’로 비교하면 ‘동일한 요소’와 ‘동일한 순서’를 가지고 있을 때 True를 반환!!
→ 기본적으로 ‘==’는 값 비교, ‘is’는 동일한 객체인지 비교(즉, 주소값 비교).
# gpt 답변
== 연산자 동작 방식
== 연산자는 리스트의 모든 요소를 비교하며,
리스트의 각 요소가 또 다른 리스트일 경우(즉, 다차원 리스트),
해당 리스트의 내부 요소까지 비교합니다. 이 비교는 재귀적으로 이루어집니다.
각 단계에서 다음을 확인합니다:
1. 두 리스트의 길이가 같은지.
2. 각 인덱스의 요소가 같은지. 요소가 리스트라면, 그 리스트의 내부 요소까지 계속 비교합니다.
3차원 리스트의 비교는 1차원, 2차원 리스트와 동일한 방식으로 작동하며,
모든 차원의 요소를 재귀적으로 비교합니다.
이 방법은 리스트의 구조와 요소가 완전히 동일한지를 확인하는 데 사용됩니다.
== 연산자를 사용하면 파이썬은 이 과정을 자동으로 처리하므로,
다차원 리스트의 비교도 간단히 수행할 수 있습니다.
→ 결론) 리스트가 몇 차원이건간에, ‘==’ 연산자가 알아서 재귀적으로 맨 밑 리스트까지 쭉 훑어 비교해주니까, (2차원 리스트로 정의된) 행렬 비교가 필요하다면 우리는 신경쓰지말고 그냥 가져다 쓰면 OK~!~!!
# 대칭 행렬 성질 연습 넘파이
A = np.array([[1,0,2],[0,2,1],[2,1,1]])
print(A)
At = np.transpose(A)
print(At)
A == At # 대칭 행렬은 기존 행렬을 전치해도 동일함.
''' 결과
array([[ True, True, True],
[ True, True, True],
[ True, True, True]])
'''
AA = A # 대칭 행렬은 거듭제곱 해도 대칭 행렬
for i in range(0, 9):
AA = np.matmul(AA, A)
print("행렬 A의 ", i+2, "제곱은 ")
print(AA)
print("==================")
A = np.array([[1,0,3], [2,1,4], [0, 1, 1]])
print(A)
At = np.transpose(A)
print(At)
np.matmul(A, At)
np.matmul(At, A)
# 임의의 행렬 A에 대해 기존 행렬과 전치 행렬을 곱한 결과는 대칭 행렬임.
- 정리) 대칭 행렬의 성질 (대칭행렬 A, B에 대해)
- 대칭 행렬은 ‘기존 행렬과 전치 행렬이 동일한 정사각 행렬’을 의미함. (A = A^T)
- 대칭 행렬끼리 더하거나 빼도 대칭 행렬 (A + B = 대칭 행렬)
- 대칭 행렬끼리 행렬곱을 한 결과는 반드시 대칭 행렬이진 않음. (A곱B = 대칭 행렬인지 여부 모름)
- 대칭 행렬의 거듭제곱은 대칭 행렬 (A^n = 대칭 행렬)
- 임의의 행렬 A에 대해 기존 행렬과 전치 행렬을 곱한 결과는 대칭 행렬임. (A곱A^T = 대칭 행렬)
3. 대각 행렬(diagonal matrix)
: 행렬의 주 대각 원소가 아닌 → 원소가 / 0인 정사각 행렬
- 대각 행렬의 역행렬은 주 대각 원소가 역수인 대각 행렬
- 대각 행렬의 거듭제곱은 주 대각 원소가 거듭제곱인 대각 행렬.
- **어떤 행렬에 대해, 대각 행렬을 오른쪽에 곱하면 기존 행렬의 열 값이 배수가 되며, 왼 쪽에 곱하면 행 값이 배수가 됨.
→ 이거 헷갈리면 책 보고 예시 다시 풀어보기 or 결과만 이해해도 될듯 일단?
# 대각 행렬 넘파이 실습
A = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
D = np.diag(A)
print(D)
'''
[1 5 9] -> 주 대각 원소를 추출줌
'''
print(np.diag(D))
'''
[[1 0 0] -> 그 주 대각 원소들를 주 대각 원소로 가지는 대각 행렬을 구성해줌
[0 5 0]
[0 0 9]] '''
A = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
D = np.diag([1,3,4])
print(A)
print(D)
'''
[[1 2 3]
[4 5 6]
[7 8 9]]
[[1 0 0]
[0 3 0]
[0 0 4]] '''
'''
여기서, numpy.diag 메서드는
1. 매개변수로 2차원 ndarray, 즉 '행렬'을 받았을 때
: 그 행렬의 주 대각 원소를 추출해 1차원 ndarray로 반환해줌.
(즉, 매개변수로 입력되는 행렬은 정사각 행렬이어야 함.)
2. 매개면수로 1차원 ndarray, 즉 '주 대각 원소'를 받았을 때
: 그 주 대각 원소들을 주 대각 원소로 가지는 대각행렬을 구성해 반환해줌.
공식 document 참고 : <https://numpy.org/doc/stable/reference/generated/numpy.diag.html>
'''
4. 단위 행렬 또는 항등 행렬(identity matrix)
: 주 대각 원소가 1이고 나머지 원소는 모두 0인 대각 행렬, 대문자 I로 표기
- 기존 행렬에 당위 행렬을 행렬곱해도 값은 변하지 않음.
→ 즉, A곱I = A, I곱A = A
→ 계산의 편의성을 위해 행렬 A가 주어졌을 때 AI로 바꾸어 표현하기도 함.
# 단위 행렬 넘파이 실습
I = np.identity(5)
print(I)
'''
[[1. 0. 0. 0. 0.]
[0. 1. 0. 0. 0.]
[0. 0. 1. 0. 0.]
[0. 0. 0. 1. 0.]
[0. 0. 0. 0. 1.]]
'''
5. 영 행렬(zero matrix)
: 행렬의 구성 원소가 모두 0인 행렬
Z = np.zeros((3,2))
print(Z)
'''
[[0. 0.]
[0. 0.]
[0. 0.]]
'''
6. 삼각 행렬(triangular matrix)
: 행렬의 구성 원소가 삼각형 형태를 나타내는 정사각 행렬
- 상 삼각 행렬(upper triangular matrix) : 주 대각 원소 아래쪽에 있는 모든 원소가 0인 정사각 행렬
- 하 삼각 행렬(lower triangular matrix) : 주 대각 원소 위쪽에 있는 모든 원소가 0인 정사각 행렬
- 상 삼각 행렬간의 덧셈, 뺄셈, 행렬 곱의 결과도 상 삼각 행렬
- 상 삼각 행렬의 전치 행렬은 하 삼각 행렬
- 상 삼각 행렬의 역행렬은 상 삼각 행렬
# 상 삼각 행렬 넘파이
A = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
Au = np.triu(A)
print(Au)
# 하 삼각 행렬 넘파이
A = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
Al = np.tril(A)
print(Al)
7. 토플리츠 행렬(toeplitz matrix)
: 행렬의 어떤 요소가 왼쪽 위 요소와 같은 형태의 행렬
- 시계열 데이터를 행렬 형태로 변환할 때 자주 사용.
# 토플리츠 행렬 사이파이 실습(넘파이는 토플리츠 행렬 함수 제공x)
from scipy.linalg import toeplitz
A = toeplitz([1,0,-2,-4], [1,3,5,7,9])
print(A)
'''
[[ 1 3 5 7 9]
[ 0 1 3 5 7]
[-2 0 1 3 5]
[-4 -2 0 1 3]]
'''
8. 이중 대각 행렬(bidiagonal matrix)
: 주 대각 원소뿐만 아니라 주 대각 원소의 바로 위쪽 혹은 아래쪽 원소가 0이 아닌 정사각 행렬.
- 상 이중 대각 행렬(upper bidiagonal matrix) : 주 대각 원소의 바로 위에 위치한 원소가 0이 아닌 이중 대각 행렬
- 하 이중 대각 행렬(lower bidiagonal matrix) : 주 대각 원소의 바로 아래에 위치한 원소가 0이 아닌 이중 대각 행렬
# 넘파이 이중 대각 행렬 실습
# 넘파이에선 이중 대각 행렬을 한 번에 구현하는 함수는 x -> 돌아가야함
A = np.array([[1,2,1,3], [5,3,4,1], [2,1,7,9], [2,8,1,3]])
diag_ele = np.diag(A)
print(diag_ele)
'''
[1 3 7 3]
'''
np.diag(diag_ele)
'''
array([[1, 0, 0, 0],
[0, 3, 0, 0],
[0, 0, 7, 0],
[0, 0, 0, 3]])
'''
u_diag_ele = np.diag(A, k=1)
print(u_diag_ele)
'''
[2 4 9]
'''
np.diag(u_diag_ele, k=1)
'''
array([[0, 2, 0, 0],
[0, 0, 4, 0],
[0, 0, 0, 9],
[0, 0, 0, 0]])
'''
u_diag = np.diag(diag_ele) + np.diag(u_diag_ele, k=1)
print(u_diag)
'''
[[1 2 0 0]
[0 3 4 0]
[0 0 7 9]
[0 0 0 3]]
'''
# 이 때, numpy.diag는 optional parameter로 int형 변수 k의 값을 지정해 줄 수 있는데,
# k의 기본값은 0이며, 이 값을 통해 어느 대각 성분을 다룰지 지정할 수 있음.
9. 하우스홀더 행렬(householder matrix)
: H = I - 2*(V곱V^T/V^T곱V) 을 만족하는 행렬 H를 의미.
(이때, V곱V^T는 벡터의 외적, V^T곱V는 벡터의 내적임.)
- 정사각 행렬이며 모든 열이 정규 직교(orthonomal)함. -> 추후 다시 배운다함
# 넘파이 이중 대각 행렬 실습
# 넘파이에선 하우스홀더 행렬을 한 번에 구현하는 함수는 x -> 돌아가야함
v = np.array([1,0,2,3])
n = len(v)
outer_mat = np.outer(v, v)
print(outer_mat) # 외적 구함
inner_val = np.inner(v,v)
print(inner_val) # 내적 구함
I = np.identity(n)
print(I) # 항등행렬 구함
H = I - (2/inner_val)*outer_mat
print(H) # 하우스홀더 행렬 공식 사용하면 끝!!
'Mathematics > 선형대수학' 카테고리의 다른 글
[선형대수학] 7장 - 역행렬 <알고리즘 구현으로 배우는 선형대수 with 파이썬> (0) | 2024.08.19 |
---|---|
[선형대수학] 6장 - 행렬 <알고리즘 구현으로 배우는 선형대수 with 파이썬> (0) | 2024.08.19 |
[선형대수학] 가우스 소거법에서 pivot은 1이어야 하는가? NO! (0) | 2024.08.19 |
[선형대수학] 5장 - 선형 시스템 <알고리즘 구현으로 배우는 선형대수 with 파이썬> (0) | 2024.08.19 |
[선형대수학] 3장 - 행렬 <알고리즘 구현으로 배우는 선형대수 with 파이썬> (0) | 2024.08.16 |