인공지능을 위한 기초 수학 - 행렬

Soogyung Gwon·2026년 3월 9일

구름을잡아라

목록 보기
30/60

행렬연산

행렬의 합

행렬 덧셈이 정의되려면 두 행렬의 크기가 같아야 한다.

A = matrix([[1, 2, -4], [-2, 1, 3]])
B = matrix([[0, 1, 4], [-1, 3, 1]])
C = matrix([[1,1], [2, 2]])
print( "A + B = " )
print( A + B )
print()
print( "2*A =" )
print( 2*A )
print()
print( "(-1)*C =" )
print( (-1)*C )

A + B = 
[ 1  3  0]
[-3  4  4]

2*A =
[ 2  4 -8]
[-4  2  6]

(-1)*C =
[-1 -1]
[-2 -2]

행렬의 곱

행렬곱은 벡터 변환을 올바르게 합성하기 위해 만들어진 연산
그렇기 때문에 행과 열을 곱한다.

A = matrix([[1, 2, -1], [3, 1, 0]])
B = matrix([[-2, 1], [0, -3], [2, 1]])
print(A*B)

[-4 -6]
[-6  0]

행렬의 곱을 이용한 선형연립방정식의 표현

영행렬, 대각선행렬, 단위행렬, 거듭제곱, 전치행렬

영행렬

성분이 모두 0인 행렬

SageMath에서 영행렬 만들기

matrix(행 개수, 열 개수, 값)
matrix(nrows, ncols, data)

  • 첫 번째: 행의 개수
  • 두 번째: 열의 개수
  • 세 번째: 초기값 또는 데이터

세번째 인자를 0으로 지정하면 영행렬이 된다.

대각선 행렬

diagonal matrix

  • 주대각선 성분 이외의 모든 성분이 0인 정사각행렬

단위행렬

단위행렬은 1과 같은 역할을 하는 행렬로 주대각성분이 모두 1이고 나머지 성분은 모두 0인 n차의 정사각행렬이다.

  • 어떤 행렬에 곱해도 행렬이 그대로 유지됨 (벡터를 그대로 유지)
  • 단위행렬은 역행렬의 기준
  • 역행렬 계산에 사용

스칼라 행렬

scalar matrix

거듭제곱

A가 n차의 정사각행렬일 때 A의 거듭제곱은:

  • A0은 영행렬이 아니라 단위행렬이다! (숫자의 경우도 0제곱은 1)

전치행렬

행과 열을 바꾸는 것

sagemath 실습 - 전치행렬

A = matrix([[1, -2, 3], [4, 5, 0]])
B = matrix([[1, 2, -4], [3, -1, 2], [0, 5, 3]])
C = matrix([[5, 4], [-3, 2], [2, 1]])
D = matrix([[3, 0, 1]])
print("A^T =")
print(A.transpose()) # 행렬의 전치행렬
print("B^T =")
print(B.transpose())

Share
A^T =
[ 1  4]
[-2  5]
[ 3  0]
B^T =
[ 1  3  0]
[ 2 -1  5]
[-4  2  3]

sagemath 실습 - 임의로 행렬 생성 후 전치행렬 구하기

A = random_matrix(ZZ, 7, 12) # 임의의 7x12 정수(ZZ) 행렬 A를 생성!
print( "A =" )
print( A )
print()
print("A^T=" )
print( A.transpose() ) # 생성한 행렬 A의 전치행렬 A.transpose() 구하기

Share
A =
[ -1  -2   1   1 -33  -2  -1   3  -1   0   0   1]
[ -4   1  -1   2   2  -2  -1   1   1  -1   8  -1]
[  0   1  -1  -1  -2  -1  -1  -1  -2  -3  -1  -7]
[ -1  -1   2   0   5   4   1   1   1   1  -1  -6]
[ -2   1  -3   1   1  -5 -24  -1   1  -1  -1   3]
[-15 -15  -3  -5  -1   0  -1  -1  -1   0  -3   1]
[  2  -1   0  -3  -1   0   0   0  -2   1   0 -45]

A^T=
[ -1  -4   0  -1  -2 -15   2]
[ -2   1   1  -1   1 -15  -1]
[  1  -1  -1   2  -3  -3   0]
[  1   2  -1   0   1  -5  -3]
[-33   2  -2   5   1  -1  -1]
[ -2  -2  -1   4  -5   0   0]
[ -1  -1  -1   1 -24  -1   0]
[  3   1  -1   1  -1  -1   0]
[ -1   1  -2   1   1  -1  -2]
[  0  -1  -3   1  -1   0   1]
[  0   8  -1  -1  -1  -3   0]
[  1  -1  -7  -6   3   1 -45]
import numpy as np
A = np.random.randint(5, size=(5, 7)) # 임의의 0~4 사이의 수만으로 이루어진 5x7 자연수 행렬
print( "A=")
print(A)
print( "A^T=")
print(A.transpose())

Share
A=
[[4 3 0 0 3 2 2]
 [0 2 3 1 2 0 1]
 [1 1 2 0 1 3 2]
 [4 4 4 0 0 3 0]
 [2 2 4 3 1 1 2]]
A^T=
[[4 0 1 4 2]
 [3 2 1 4 2]
 [0 3 2 4 4]
 [0 1 0 0 3]
 [3 2 1 0 1]
 [2 0 3 3 1]
 [2 1 2 0 2]]

전치행렬 관련 연산

역행렬

n차의 정사각행렬 A에 대하여 다음을 만족하는 행렬 B가 존재하면 A는 가역(invertible, nonsingular) 라고 한다.

이 때 B를 A의 역행렬(inverse matrix)라고 하며, 이러한 B가 존재하지 않으면 A는 비가역(noninvertible, singular) 라고 한다.

  • A와 B가 서로 역행렬 관계
  • AB = 단위행렬 = BA 가 되는 이유
  • 여기서 A의 역행렬이 B인 것이고, A와 B를 곱하면 서로 B가 변형된 것을 다시 돌려주는 것이 되므로 변화가 없기에 단위행렬이 나온다.

sagemath 실습 - 가역인지 아닌지 알아보기

A = matrix([[1, 4, 3], [2, 5, 6], [0, 0, 0]])
A.is_invertible() #행렬이 가역인지 확인

False

역행렬 정리

sagemath 실습 - 역행렬 구하기

A = matrix(2, 2, [3, 5, 1, 2])
print("A=")
print(A)
print()
print("A.inverse()=")
A.inverse()

A=
[3 5]
[1 2]

A.inverse()=
[ 2 -5]
[-1  3]

기본행렬

위의 경우를 차례로...

  • 단위행렬의 두 행을 교환하여 기본행렬을 만든다.
  • 단위행렬의 한 행에 0 아닌 상수배를 하여 다른 행에 더하여 기본행렬을 만든다.
  • 한 행에 영 아닌 상수배를 하여 기본행렬을 만든다.

sagemath 실습 - 기본행렬

# 주의!! Sage의 index는 0부터 시작한다.
# elementary_matrix(n, row1=i, row2=j): i행과 j행을 교환
E1 = elementary_matrix(4, row1=1, row2=2) # 기본행렬 r2 ↔ r3

# elementary_matrix(n, row1=i, scale=m): i행에 m을 곱한다.
E2 = elementary_matrix(4, row1=2, scale=-3) # 기본행렬 (-3)*r3

# elementary_matrix(n, row1=i, row2=j, scale=m): j행에 m을 곱하여 i행에 더함
E3 = elementary_matrix(4, row1=0, row2=3, scale=7) # 기본행렬 7*r4 + r1


print ( "E1 =" )
print ( E1 )
print ()
print ( "E2 =" )
print ( E2 )
print ()
print ( "E3 =" )
print ( E3 )

E1 =
[1 0 0 0]
[0 0 1 0]
[0 1 0 0]
[0 0 0 1]

E2 =
[ 1  0  0  0]
[ 0  1  0  0]
[ 0  0 -3  0]
[ 0  0  0  1]

E3 =
[1 0 0 7]
[0 1 0 0]
[0 0 1 0]
[0 0 0 1]

역행렬 구하기

역행렬 구하기의 예)



행렬의 가역성과 선형연립방정식의 해 사이의 관계

sagemath 실습 - 선형연립방정식의 해

A = matrix(3, 3, [1, 2, 3, 2, 5, 3, 1, 0, 8])
b = vector([1, 3, -1])
print( "x=", A.inverse()*b) # 역행렬을 이용한 연립방정식의 해 구하기
print()
print( "x=", A.solve_right(b) ) # .solve_right()을 이용하여 구할 수도 있다.

Share
x= (-1, 1, 0)

x= (-1, 1, 0)

sagemath 실습 - 대각선, 단위, 스칼라 행렬 활용 예제

H = diagonal_matrix([-3, -2, 1]) # 대각선행렬
K = identity_matrix(3) #단위행렬
J = matrix(2, 2, 0) # 영행렬
print( "H =")
print( H )
print()
print( "K=")
print( K )
print()
print( "J=")
print( J )
print()


Share
H =
[-3  0  0]
[ 0 -2  0]
[ 0  0  1]

K=
[1 0 0]
[0 1 0]
[0 0 1]

J=
[0 0]
[0 0]

대칭행렬

A = matrix([[1,2,3], [2,4,5], [3,5,6]])
B = matrix([[0,1,-2], [-1,0,3], [2,-3,0]])
print( bool(A == A.transpose()) ) # A가 대칭인지 확인
print( bool(B == -B.transpose()) ) # B가 반대칭인지 확인

True
True

LU 분해

LU 분해(factorization)는 어떤 행렬 A를 두 행렬의 곱으로 나누는 것

정사각행렬 A의 REF는 상삼각행렬 U라 할 때, U는 A에 기본행렬들을 곱함으로써 (가우스 소거법, 기본행렬들을 필요에 따라 곱하여 소거함으로써) 얻어진다.

  • 위의 식은 첫번째 행은 가우스 소거를 행렬로 나타내어 표현한 것을 오른쪽 화살표 이후에 양변에 역행렬을 곱한 것을 보여주는 것
  • 두번째 행은 LU 분해를 통해 연립방정식을 푸는 방법을 보여주는 것

Ei 들은 치환행렬 또는 하삼각행렬이다. 하삼각행렬의 역행렬도 하삼각행렬이다. 따라서 치환행렬이 필요한 경우를 별도로 미리 처리하면, 일반성을 잃지 않고 A를 하삼각행렬 L과 상삼각행렬 U의 곱 A=LU로 쓸 수 있다.

-> Ei는 기본행렬들로 가우스 소거에서 사용하는 기본행렬은 두 종류이다. - 치환행렬, R1 <-> R2, 그리고 하삼각행렬 R2 -> R2 - 3R1. 하삼각행렬의 역행렬이 하삼각행렬인 것은 하삼각행렬의 특징이고, 치환행렬(R1 <-> R2)이 필요한 경우에는 미리 처리한 것으로 치면; 그렇다 할지라도 LU분해의 성질을 해하지 않으므로, A=LU라고 할 수 있다.

A=LU

L: 하삼각행렬 (Lower triangular matrix)
U: 상삼각행렬 (Upper triangular matrix) - U는 가우스 소거법의 결과로 만들어지는 행렬

간단요약:

가우스 소거에 사용되는 기본행렬은 대부분 하삼각행렬이고, 그 역행렬도 하삼각행렬이므로 행 교환만 따로 처리하면 어떤 행렬 A도 A=LU 로 표현할 수 있다.

LU 분해 자세한 버전:



Ly=b는 전진대입법(forward substitution)으로 쉽게 풀 수 있다.

Ux=y는 후진대입법(backward substitution)으로 쉽게 풀 수 있다.

치환/반전

치환

자연수의 집합 S = {1, 2, ..., n}의 치환(permutation, 순열)이란 S에서 S로의 일대일 대응 함수이다. (모든 원소를 한 번씩만 다른 위치로 재배치하는 것, 순서를 바꾸는 함수)

반전

지환에서 반전(inversion)이란 큰 자연수가 작은 자연수보다 더 왼쪽에 먼저 나타나는 경우를 말함. 예) (1, 4, 2, 3)

치환이 가진 반전의 총 개수가 짝수-> 짝치환(even permutation)
홀수면 -> 홀치환(odd permutation)

sagemath 실습

print( Permutation([5, 1, 2, 4, 3]).inversions() ) #반전이 일어난 부분 찾기
print( Permutation([5, 1, 2, 4, 3]).number_of_inversions() ) #반전의 개수 구하기
print( Permutation([5, 1, 2, 4, 3]).is_even() ) # 짝치환인지 확인

[(1, 2), (1, 3), (1, 4), (1, 5), (4, 5)]
5
False

부호화 함수/행렬식 표현

행렬식(determinmant) = det(A)란

  • 행렬식인 det(A)는 |A|로도 표현
  • 선형변환이 공간의 부피를 얼마나 바꾸는지 나타내는 값

예)

행렬식 det(A) = 1⋅4 − 2⋅3 = −2

det(A)는...

det(A)는 행렬 A가 "다른 벡터나 공간에 어떤 변형을 가하는지"를 측정하는 값이다.

  • 공간을 얼마나 늘리거나
  • 얼마나 줄이거나
  • 뒤집는지
    를 보는 것이고, 공간 변형의 크기와 방향을 알 수 있다.

행렬 A가 다른 벡터에 곱해졌을 때,

  • 벡터 하나는 길이만 바뀜
  • 공간 전체는 면적/부피가 변함

det(A)는 이 공간 변화율

어떤 nxn 행렬 A에 대해 행렬식 det(A)는:

(1) 행이 같으면 0
det(A) = 0
두 행이 같으면 공간이 찢어지지 않기 때문에

2차원 -> 선
3차원 -> 평면

  • 즉 공간이 눌려서 차원이 줄어듦
  • 역행렬이 없고, 정보 손실이 발생

0이 아니면? 선형독립

(2) 행을 바꾸면 부호가 바뀜
(3) 각 행에 대해 선형(linear)

행렬 내부 값들과의 관계

det(A)는 행렬 내부 값들로 계산됨

직관적으로 보면

결국 det(A)는 열벡터들이 만드는 공간의 부피이다.
혹은 선형변환의 부피 변화율 이다.
-> A의 열벡터들이 만드는 평행다각형(또는 평행육면체)의 부피

sagemath 실습 - 부호화 함수, 행렬식

B = matrix([[1, 2, 3], [-4, 5, 6], [7, -8, 9]])
print( B.det() ) # 행렬식 구하기

240

정리

sagemath 실습 - 가역 여부 판단

A = random_matrix(QQ, 3, 3) # QQ - 유리수집합
B = random_matrix(QQ, 3, 3)
AB = A*B
print( "|AB| = |A||B| ?", AB.det() == A.det()*B.det() )
print( "|A| =", A.det())
if A.det() != 0:
    print("Is A invertible ?", A.is_invertible() )
    print("|A^-1| = |A|^-1 ?", 1/A.det() == A.inverse().det() )
else:
    print( "Is A invertible ?", A.is_invertible() )
    
|AB| = |A||B| ? True
|A| = 12
Is A invertible ? True
|A^-1| = |A|^-1 ? True

랜덤 행렬이라 det(A)의 값은 계속 변함

profile
오랜시간 망설였던 코딩을 다시 해보려고 노력하고 있는 사람

0개의 댓글