[인공지능 수학] 역행렬, 특수행렬, LU분해와 치환 완전 정복 (feat. SageMath 실습)
📌 오늘의 학습 목표
행렬을 배웠다면, 이제 그 행렬을 가지고 마법을 부릴 차례임! 숫자 나누셈처럼 행렬도 나눌 수 있을까? 데이터를 예쁘게 분해하거나 특수한 모양의 행렬을 만들면 인공지능 연산이 얼마나 빨라질까?
- 가역과 역행렬: 행렬의 “나눗셈” 역할을 하는 역행렬의 개념과 존재 여부(행렬식)를 파악함.
- 특수행렬과 대칭행렬: 단위행렬, 영행렬, 대각행렬, 그리고 (반)대칭행렬의 성질을 이해함.
- 역행렬을 이용한 방정식 해법: $Ax = B$를 $x = A^{-1}B$로 한 방에 풀어내는 마법을 배움.
- LU 분해: 복잡한 행렬을 두 개의 쉬운 삼각형 모양으로 쪼개는 기법을 실습함.
- 치환(Permutation)과 짝/홀 치환: 행렬식을 구하는 밑바탕인 치환의 반전(Inversion) 개념을 정립함.
- SageMath 실습: 위 모든 개념을 파이썬 코드로 자동 계산해 보는 예제(5, 6, 8, 9, 10, 11, 15)를 수행함.
1. 가역행렬과 역행렬 (Invertibility and Inverse Matrix)
초등학교 때 우리는 숫자 곱셈의 반대되는 개념으로 ‘역수’를 배웠음. 예를 들어 숫자 $3$에 그 역수인 $1/3$을 곱하면 아무 의미 없는 기본 숫자 $1$이 됨.
행렬의 세계에서도 똑같은 치트키가 존재함! 똑같은 크기의 네모난 표(행렬) 두 개를 곱했는데, 아무 효과가 없는 투명 망토 같은 단위행렬($I$) (대각선에만 1이 있고 나머지는 0인 표)이 튀어나온다면?
이때 곱해준 행렬을 원래 행렬의 “역행렬(Inverse Matrix)” 이라고 부름 ($A^{-1}$로 표기함). 그리고 이렇게 짝꿍 역행렬을 가진, 뒤집기가 가능한 행렬을 “가역행렬(Invertible Matrix)” 이라고 함.
하지만 주의할 점! 숫자 0에는 역수가 없듯이, 모든 행렬이 역행렬을 가질 수 있는 건 아님. 이 행렬이 역행렬이 존재하는지 아닌지를 단번에 판별해 주는 판독기가 바로 “행렬식(Determinant, $det$)” 임. 행렬식 값이 0이 아니면 무조건 역행렬이 존재함!
🧮 [예제 5, 6] 가역 여부 체크 및 역행렬 구하기 실습 (in SageMath)
손으로 3x3 표의 역행렬을 구하려면 수십 번의 덧셈 뺄셈 곱셈을 하다가 지쳐 쓰러짐. 하지만 컴퓨터는 클릭 한 번으로 가역성(Invertibility) 판독부터, 실제 역행렬을 구하는 것까지 끝내버림.
# SageMath 환경에서 실행
# 3x3 크기의 임의의 행렬 A를 만듦
A = matrix(QQ, [
[ 1, 2, 3],
[ 2, 5, 3],
[ 1, 0, 8]
])
print("--- 원본 행렬 A ---")
print(A)
# [예제 5] 행렬 A가 가역(역행렬이 존재하는지)인지 체크함!
# 방법 1: 내장 함수 is_invertible() 사용
is_inv = A.is_invertible()
# 방법 2: 행렬식(Determinant)이 0인지 아닌지 확인
det_A = A.det()
print(f"\nA의 행렬식 값: {det_A}")
if is_inv:
print("결과: 행렬식이 0이 아니므로 역행렬이 존재함! (가역행렬)")
else:
print("결과: 행렬식이 0이므로 역행렬이 없음! (특이행렬)")
# [예제 6] 역행렬 구하기 실습
if is_inv:
# 역행렬을 구하는 마법의 명령어 .inverse()
A_inv = A.inverse()
print("\n--- A의 역행렬 (A^-1) ---")
print(A_inv)
# 정말 역행렬이 맞는지 확인해보기 (A와 A_inv를 곱함)
# 곱하면 대각선만 1인 '단위행렬'이 나와야 함!
print("\n--- 검증: A * A^-1 (단위행렬이 나와야 함) ---")
print(A * A_inv)
💡 결과 직관적 이해
- 행렬식을 계산해 보니 값이
-1(즉 0이 아님)이 나옴. 따라서 역수가 존재하는 멀쩡한 행렬임! - 만들어진
A_inv를 원래A와 곱해 보면[[1,0,0], [0,1,0], [0,0,1]]이라는 깔끔한 투명 망토 투명행렬(단위행렬)로 싹 정화되는 것을 볼 수 있음.
(아래는 행렬을 곱해 찌그러진 공간을, 역행렬을 곱해서 다시 원래의 반듯한 격자 공간으로 완벽히 복구시키는 마법을 시각화한 것임)

2. 역행렬을 대포로 쏴서 선형연립방정식 단번에 풀기
앞선 포스트에서 연립방정식을 풀 때 가우스-조던 소거법(가감법 청소)을 써서 매번 0으로 청소를 해줬음. 하지만 방금 배운 “역행렬”을 무기로 쓰면 훨씬 더 통쾌하고 간결하게 방정식을 박살낼 수 있음.
$Ax = B$ (A: 계수행렬, x: 미지수, B: 결과값)
이 식에서 우리가 궁금한 건 미지수 $x$임. 그럼 양변 앞쪽에 $A$의 천적인 역행렬 $A^{-1}$를 곱해서 $A$를 깔끔하게 없애버리면 됨!
$A^{-1} * A * x = A^{-1} * B$
➡️ 수치 1로 변해서 사라짐: $I * x = A^{-1} * B$
➡️ 최종 공식: $x = A^{-1} * B$
완전 마법의 공식임! 미지수를 찾고 싶으면 결과값 B에 역행렬만 툭 곱해주면 정답이 바로 나옴.
🧮 [예제 8] 역행렬을 이용한 선형연립방정식 풀이 (in SageMath)
# SageMath 환경에서 실행
# 풀고자 하는 연립방정식 체계
# 1x + 2y + 3z = 1
# 2x + 5y + 3z = 6
# 1x + 0y + 8z = -6
# 1. 왼쪽 숫자들만 모은 계수행렬 A
A = matrix(QQ, [
[1, 2, 3],
[2, 5, 3],
[1, 0, 8]
])
# 2. 오른쪽 결과만 세로로 모은 벡터 B
B = vector(QQ, [1, 6, -6])
# 3. 해답 구하기! (x = A^-1 * B)
# A의 역행렬을 구한 뒤 곧바로 B와 곱해버림!
x = A.inverse() * B
print("\n--- 역행렬을 이용해 구한 정답 x, y, z ---")
print(x)
💡 놀라운 점
가우스 소거법으로 add_multiple_of_row를 수십 번 타이핑하던 수고로움 없이, 역행렬 하나 구해서 우변에 딱 한 번 곱해주자마자 미지수 세 개의 정답이 리스트로 툭 튀어나옴! 수학적 우아함의 극치임.
3. 컴퓨터 연산을 날개 달아주는 여러 가지 “특수행렬”
딥러닝 모델에는 1억 개, 10억 개의 숫자가 행렬에 꽉꽉 들어참. 이걸 매번 무식하게 다 연산하려면 슈퍼컴퓨터도 뻗어버림. 그래서 특별한 위치에 0이 가득 차 있는 특수한 모양의 스켈레톤(뼈대) 행렬들을 활용하면, 곱셈을 할 때 0 때문에 연산이 몽땅 무효화되어서 스피드가 미친 듯이 빨라짐.
🧮 [예제 9] 대각행렬, 단위행렬, 영행렬 (in SageMath)
- 대각행렬 (Diagonal Matrix): 정중앙 대각선에만 알맹이(숫자)가 있고 나머지는 싹 다 0으로 비워둔 행렬.
- 단위행렬 (Identity Matrix): 대각행렬 중에서도 대각선 숫자가 무조건 ‘1’인 행렬 (마치 숫자계의 투명 망토 1과 같음).
- 영행렬 (Zero Matrix): 모든 칸이 0으로 가득 찬 행렬 (숫자계의 0과 같음).
# SageMath 환경에서 실행
n = 3 # 3x3 크기 지정
# 1. 영행렬 (세상 쓸모없어 보이지만 초기화할 때 필수임)
Z = zero_matrix(QQ, n)
print("--- 영행렬 ---")
print(Z)
# 2. 단위행렬 (가장 완벽한 투명 망토. 아이덴티티!)
I = identity_matrix(QQ, n)
print("\n--- 단위행렬 ---")
print(I)
# 3. 대각행렬 (대각선에 내가 원하는 숫자만 콕콕 박아둠)
D = diagonal_matrix(QQ, [2, -5, 7])
print("\n--- 대각행렬 ---")
print(D)
4. (반)대칭행렬 (Symmetric / Skew-symmetric Matrix)
표(행렬)의 대각선을 축으로 해서, 마치 데칼코마니(종이접기)하듯 양옆 숫자들이 거울상으로 매칭되는지 확인하는 개념임.
- 대각선을 전치(Transpose, 행과 열 위치를 뒤바꿈) 시켰을 때:
- 아수라 백작처럼 원본 표와 똑같으면: 대칭행렬 (Symmetric, $A = A^T$)
- 원본 표 숫자들에 마이너스(-) 부호만 싹 붙인 거랑 똑같으면: 반대칭행렬 (Skew-symmetric, $A = -A^T$)
🧮 [예제 10] (반)대칭행렬 체크 (in SageMath)
# SageMath 환경에서 실행
# 데칼코마니 대칭행렬 만들기
# 대각선 [1, 5, 9]를 기준으로 위아래 모서리 숫자가 거울처럼 같음!
S = matrix(QQ, [
[1, 2, 3],
[2, 5, -4],
[3, -4, 9]
])
# 반대칭행렬 만들기 (대각선은 무조건 0이어야 거울 반대가 됨!)
# 대각선 기준 거울 너머 방에 부호만 정확히 정반대인 애들이 살고 있음.
K = matrix(QQ, [
[ 0, 2, -3],
[-2, 0, 4],
[ 3, -4, 0]
])
# 전치행렬(.transpose()) 기능으로 변신시켜보고 결과 비교하기!
print("S가 대칭행렬인가? S == S^T :", S == S.transpose())
print("K가 반대칭행렬인가? K == -K^T :", K == -K.transpose())
- 거울에 비친 듯 데이터가 완벽히 균형 잡혀 있는지 확인할 때 유용함 (AI에서는 공분산 행렬(Covariance matrix)이 대표적인 대칭행렬임).
5. 큰 바위를 모래로 쪼갠다, LU 분해 (LU Decomposition)
수만 줄짜리 엄청나게 거대한 연립방정식 행렬을 통째로 풀기엔 너무 하드코어 함. 수학자들은 또 잔머리를 굴려서 복잡한 네모 표 1개를, 비교적 다루기 쉬운 세모 표 2개로 미리 쪼개어 분해해 두는 비법을 고안했음. 이것이 바로 “LU 분해” 임.
- L (Lower triangular): 위쪽은 다
0이고 아래쪽에만 숫자가 모인 하삼각행렬 (밑이 무거운 세모) - U (Upper triangular): 밑쪽은 다
0이고 위쪽에만 숫자가 모인 상삼각행렬 (위가 뚱뚱한 세모)
$A = L * U$ 로 쪼개두면, 무거운 바위($A$)를 들고 역행렬 계산을 꾸역꾸역 안 해도, 가벼운 두 모래 덩어리($L, U$)를 이용해 순식간에 답을 유도해 낼 수 있어 컴퓨터 연산 메모리가 획기적으로 절약됨.
🧮 [예제 11] LU 분해 실습 (in SageMath)
# SageMath 환경에서 실행
# 매우 평범하고 꽉 찬 행렬 A
A = matrix(QQ, [
[ 2, -1, 1],
[ 4, 1, -1],
[ 2, -7, 3]
])
print("--- 원본 꽉 찬 행렬 A ---")
print(A)
# 마법의 명령어 LU 분해 시작! (P, L, U 세 가지를 반환해 줌)
# P는 행 순서를 조정한 순열(Permutation) 행렬의 껍데기인데, 일단 무시해도 좋음.
P, L, U = A.LU()
print("\n--- 아래쪽이 뚱뚱한 L (하삼각행렬) ---")
print(L)
print("\n--- 위쪽이 뚱뚱한 U (상삼각행렬) ---")
print(U)
# 검증: P * L * U 를 다시 곱하면 원래의 A로 부활하는가?
print("\n--- P * L * U 원상복구 체크 ---")
print(P * L * U == A)
(아래는 정육면체를 한 번에 찌그러뜨리는 복잡한 행렬 A 대신, U(오렌지)로 가로축을 먼저 밀고, L(초록)로 세로축을 마저 밀어서 최종적으로 A와 똑같은 결과를 두 번에 나누어 쉽게 달성하는 시각화임)

6. 치환(Permutation)과 짝/홀 반전의 마법
행렬의 성질이 가역인지 판별하려면 “행렬식(Determinant)”이라는 최종 합격 점수를 매긴다고 했음. 이 점수를 세부적으로 쪼개고 또 쪼개면 가장 밑바닥에는 자연수들의 위치 자리 바꿈인 치환(Permutation) 이라는 게임 규칙이 숨어있음.
- $1, 2, 3, 4$ 라면 올바른 오름차순(기본 상태)임.
- 그런데 $2, 1, 4, 3$ 처럼 친구들이 자리를 서로 엉뚱하게 바꾸어버린 것을 ‘치환되었다’고 함.
- 이때 앞에 있는 숫자가 자기보다 뒤에 있는 숫자보다 덩치가 크면 “어? 족보가 꼬였는데?” 하고 반칙 스티커를 발부함. 이 반칙 스티커 발부 횟수를 “반전 수(Inversions)” 라고 부름.
- 이 반칙 스티커 개수가 짝수 개면 짝치환(Even permutation), 홀수 개면 홀치환(Odd permutation) 이라 부름!
🧮 [예제 15] 짝/홀 치환 판정 실습 (in SageMath)
# SageMath 환경에서 실행
# [3, 1, 4, 2] 로 자리를 바꾼(치환) 배열을 만듦
# 원래 자리 1, 2, 3, 4 에서 3은 1번으로, 1은 2번으로 갔다는 뜻.
p = Permutation([3, 1, 4, 2])
print(f"현재 치환 배열: {p}")
# 1. 족보가 꼬인 횟수(반전 수 Inversions) 구하기
# 3 > 1 (꼬임) / 3 > 2 (꼬임) / 4 > 2 (꼬임) -> 총 3번 꼬임!
inv_count = p.number_of_inversions()
print(f"족보 파괴(반전) 횟수: {inv_count}")
# 2. 짝치환인가 홀치환인가?
# 반칙 스티커가 3개(홀수) 이므로 홀치환일 것임.
print(f"짝치환(Even) 인가?: {p.is_even()}")
if p.is_even():
print("결론: 반전 횟수가 짝수인 짝치환입니다.")
else:
print("결론: 반전 횟수가 홀수인 홀치환입니다.")
💡 왜 치환을 배울까?
나중에 복잡하고 커다란 수십 칸짜리 행렬의 “행렬식 점수”를 구할 때, 짝치환인 것들은 + 부호를 주고, 홀치환으로 자리가 꼬인 항목들은 - 부호를 줘서 전부 더하게 됨. 즉, 이 족보의 꼬임 횟수가 인공지능이 계산하는 행렬식 플러스/마이너스 룰의 가장 원초적인 규칙임!
🎯 오늘의 요약 (Summary)
- 역행렬: 행렬계의 역수. 특이하게도 행렬식(Determinant)이 0만 아니면 역수를 구할 수 있고, 이를 활용해 연립방정식 덩어리를
x = A의 역행렬 * B로 아주 우아하고 시크하게 한 방에 폭발시켜 답을 잡을 수 있음. - 특수행렬과 (반)대칭: 계산할 때
0을 통해 치명타를 입히거나(영행렬, 대각행렬), 데칼코마니처럼 거울 반사벽을 쳐서(대칭행렬) 인공지능의 계산 메모리와 속도를 비약적으로 혁신시키는 뼈대 기술임. - LU 분해: 엑스칼리버처럼 단단한 큰 표 하나를, 가벼운 하삼각(L)/상삼각(U) 표 두 개로 예쁘게 등분하여 쪼개는 기술임.
- 치환과 꼬임: 자리 바꿈(순열) 속에서 큰 숫자가 작은 숫자보다 앞에 서는 “하극상(반전)”이 몇 번 발생했는지 카운트하여, 나중에 행렬 폭발의 부호(+나 -)를 결정짓는 근원임.
Comments