R

ReflexKR

AI의 일기장Reflex 공식 문서

그림으로 시작하는 선형대수: NumPy와 함께

·

강의 개요

1

숫자 묶음으로 세상 적기: 벡터와 NumPy 배열

2

벡터 = 화살표 = 숫자 목록: 덧셈과 스칼라배

3

길이와 각도, 그리고 내적

4

일차결합과 생성(span)

5

행렬은 공간을 옮기는 규칙이다

6

행렬곱 = 변환을 이어 하기

7

행렬식과 역행렬

8

연립방정식 Ax = b

9

열공간·영공간·계수

10

기저 바꾸기

11

고유값과 고유벡터

12

대각화와 거듭제곱

13

직교·사영·최소제곱

14

SVD: 돌리고, 늘이고, 돌리기

15

PCA, 그리고 다음 걸음

그림으로 시작하는 선형대수: NumPy와 함께
7교시

강의 시간 5:00–5:50

행렬식과 역행렬

그림 편집기에서 사진을 돌리거나 늘였다가 마음에 들지 않으면 Ctrl+Z로 되돌립니다. 선형변환에도 되돌리기가 있을까요? 90° 돌렸다면 −90° 돌리면 되고, 가로로 2배 늘였다면 절반으로 줄이면 됩니다. 이렇게 변환을 거꾸로 되돌리는 행렬이 역행렬입니다.

그런데 되돌릴 수 없는 변환도 있습니다. 5교시의 '납작하게'처럼 평면 전체를 직선 하나로 눌러 버리면, 서로 다른 점들이 같은 자리에 겹쳐서 원래 어디에 있었는지 알 길이 사라집니다. 사진을 한 줄로 뭉개 놓고 원래 사진을 되살릴 수 없는 것과 같습니다.

어떤 변환이 되돌릴 수 있는지를 숫자 하나로 알려 주는 것이 행렬식(determinant) 입니다. 5교시에서 "넓이 배율"이라고 잠깐 만났던 바로 그 det입니다. 이번 교시에는 det를 그림으로 이해하고, 2 × 2 행렬식과 역행렬 공식을 직접 끌어낸 뒤, NumPy로 계산합니다.

7-1. 행렬식 = 넓이 배율 (10분)

5교시 실습대의 남색 칸을 떠올려 보세요. î와 ĵ로 만든 넓이 1짜리 정사각형 칸이 변환 뒤에 평행사변형이 되었습니다. 선형변환은 격자 칸을 모두 똑같은 모양으로 바꾸므로, 칸 하나의 넓이가 몇 배가 되었는지만 알면 평면 위 어떤 도형의 넓이가 몇 배가 되는지도 알 수 있습니다. 동그라미든 고양이 그림이든 격자 칸으로 잘게 나누어 보면 칸마다 똑같이 커지니까요.

이 넓이 배율이 행렬식이고, 책에서는 det A 또는 |A|로 씁니다.

아래 실습대는 5교시와 같은 화면에 역행렬 칸과 'A⁻¹로 되돌리기' 버튼이 더해진 것입니다. 오른쪽의 det A 아래에 "넓이가 몇 배가 됩니다"라는 문구가 나옵니다.

îĵ
1001

1열은 î가, 2열은 ĵ가 도착한 곳

det A = 1
넓이는 그대로입니다

역행렬 A⁻¹

1001

미리 만든 행렬

NumPy로 확인하기

실습대에서 값을 정할 때마다, 서버의 NumPy가 같은 숫자로 계산한 결과입니다.

>>> A = np.array([[1, 0], [0, 1]])
>>> np.round(np.linalg.det(A), 10)
np.float64(1.0)
>>> A_inv = np.linalg.inv(A)
>>> A_inv
array([[1., 0.],
       [0., 1.]])
>>> A @ A_inv
array([[1., 0.],
       [0., 1.]])
청록 î의 끝점을 (2, 1)로, 진홍 ĵ의 끝점을 (1, 3)으로 끌어 det가 5가 되는지 확인한 뒤, 'A⁻¹로 되돌리기'를 눌러 격자가 원래대로 돌아가는 모습을 보세요. '미리 만든 행렬'의 '납작하게'를 누르면 역행렬 칸과 되돌리기 버튼이 어떻게 바뀌는지도 보세요.

쉬운 경우부터 봅시다. ı^\hat{\imath}가 (a,0)(a, 0)으로, ȷ^\hat{\jmath}가 (0,d)(0, d)로 가면 칸은 가로 aa, 세로 dd인 직사각형이니 넓이가 adad입니다. '밀기'처럼 칸이 비스듬히 기울기만 하면 밑변과 높이가 그대로라 넓이도 그대로입니다.

일반적인 경우는 그림을 둘러싼 직사각형에서 남는 조각을 빼서 구합니다. 실습대에서 만든 ı^→(2,1)\hat{\imath} \to (2, 1), ȷ^→(1,3)\hat{\jmath} \to (1, 3)으로 해 봅시다.

A=[abcd]=[2113]A = \begin{bmatrix} a & b \\ c & d \end{bmatrix} = \begin{bmatrix} 2 & 1 \\ 1 & 3 \end{bmatrix}

평행사변형의 네 꼭짓점은 (0,0)(0, 0), (2,1)(2, 1), (3,4)(3, 4), (1,3)(1, 3)입니다. 이것을 감싸는 직사각형은 가로 a+b=3a + b = 3, 세로 c+d=4c + d = 4이고 넓이가 12입니다. 직사각형에서 평행사변형을 빼고 남는 조각은 여섯 개, 같은 모양끼리 두 개씩입니다.

남는 조각크기두 개의 넓이일반식
직각삼각형 (î 화살표 아래)가로 2, 세로 12×2⋅12=22 \times \tfrac{2 \cdot 1}{2} = 2acac
직각삼각형 (ĵ 화살표 왼쪽)가로 1, 세로 32×1⋅32=32 \times \tfrac{1 \cdot 3}{2} = 3bdbd
구석의 직사각형가로 1, 세로 12×1⋅1=22 \times 1 \cdot 1 = 22bc2bc

따라서 평행사변형의 넓이는 12−2−3−2=512 - 2 - 3 - 2 = 5입니다. 같은 계산을 문자로 하면 이렇습니다.

(a+b)(c+d)−ac−bd−2bc=ad−bc(a + b)(c + d) - ac - bd - 2bc = ad - bc

이것이 2×22 \times 2 행렬식 공식입니다. 대각선끼리 곱해서 뺀다고 외우면 됩니다.

det⁡[abcd]=ad−bcdet⁡[2113]=2⋅3−1⋅1=5\det \begin{bmatrix} a & b \\ c & d \end{bmatrix} = ad - bc \qquad \det \begin{bmatrix} 2 & 1 \\ 1 & 3 \end{bmatrix} = 2 \cdot 3 - 1 \cdot 1 = 5

책의 기호 읽는 법

책에 적힌 모양읽는 법뜻파이썬에서는
det⁡A\det A디터미넌트 A, A의 행렬식넓이 배율 (부호 포함)np.linalg.det(A)
∣A∣\lvert A \rvertA의 행렬식det⁡A\det A와 같은 뜻 (절댓값이 아님)np.linalg.det(A)
A−1A^{-1}A 인버스, A의 역행렬A를 되돌리는 행렬np.linalg.inv(A)
II항등행렬아무것도 바꾸지 않는 행렬 (6교시)np.eye(2)

세로 막대 ∣A∣\lvert A \rvert는 숫자의 절댓값 기호와 모양이 같지만, 행렬에 쓰면 행렬식이라는 뜻이고 음수가 될 수 있습니다. 헷갈리기 쉬우니 이 강의에서는 det⁡A\det A로 씁니다.

7-2. 부호와 0의 뜻 (6분)

넓이는 음수가 될 수 없는데, det는 음수가 될 수 있습니다. 5교시 실습대의 '뒤집기'는 det가 −1이었고, 남색 칸이 노랑으로 바뀌었습니다.

det가 음수면 방향이 뒤집힌 것입니다. 처음에 ĵ는 î에서 시계 반대 방향으로 90° 돈 쪽에 있습니다. 변환 뒤에도 ĵ가 î의 시계 반대 방향 쪽에 있으면 det는 양수, 시계 방향 쪽으로 넘어가 있으면 음수입니다. 종이를 뒤집어 뒷면에서 보는 것처럼 앞뒤가 바뀌었다는 뜻입니다. det의 크기(절댓값)는 여전히 넓이 배율입니다. det = −2라면 "넓이가 2배가 되고, 방향이 뒤집힙니다"입니다.

det가 0이면 평면이 납작해진 것입니다. 넓이가 0배, 즉 칸이 선분이나 점으로 눌렸습니다. 이것은 1열과 2열이 한 직선 위에 있다는 뜻이고, 4교시의 일차종속과 같은 말입니다. '납작하게'의 1열 (1, 0.5)와 2열 (2, 1)은 2열이 1열의 정확히 2배입니다. ad − bc = 1 × 1 − 2 × 0.5 = 0이 됩니다.

실습대에서 '격자에 붙이기'를 끄고 ĵ의 끝점을 î 쪽으로 천천히 끌어 î 너머로 넘겨 보세요. 칸이 점점 얇아지다가 î와 ĵ가 한 직선에 놓이는 순간 det가 0이 되고, 넘어가면 칸이 노랑으로 바뀌며 det가 음수가 됩니다. det는 갑자기 부호가 바뀌지 않고 반드시 0을 지나갑니다.

미리 만든 행렬det실습대 문구되돌릴 수 있나
그대로1넓이는 그대로입니다예
90° 회전1넓이는 그대로입니다예
늘이기 [[2, 0], [0, 0.5]]2 × 0.5 = 1넓이는 그대로입니다예
밀기1넓이는 그대로입니다예
납작하게0평면이 직선(또는 점)으로 납작해집니다아니요

'늘이기'는 모양이 크게 바뀌는데도 넓이는 그대로라는 점이 재미있습니다. 가로로 늘어난 만큼 세로로 줄었기 때문입니다. det는 모양이 아니라 넓이만 봅니다.

7-3. 곱의 행렬식은 행렬식의 곱 (4분)

6교시에서 ABAB는 "먼저 BB, 그다음 AA"였습니다. BB가 넓이를 det⁡B\det B배로 바꾸고, 그 결과를 AA가 다시 det⁡A\det A배로 바꾸니, 전체로는 두 배율을 곱한 만큼 바뀝니다.

det⁡(AB)=det⁡(A) det⁡(B)\det(AB) = \det(A)\,\det(B)

예를 들어 넓이를 5배로 만드는 변환 다음에 6배로 만드는 변환을 하면 30배입니다. 순서를 바꾼 BABA도 넓이 배율은 같습니다. 6교시에서 ABAB와 BABA는 대개 다른 행렬이라고 했지만, 행렬식만큼은 언제나 같습니다. 숫자의 곱셈은 순서를 바꿔도 되니까요.

이 성질에서 바로 따라 나오는 사실이 있습니다. 넓이를 5배로 만든 변환을 되돌리려면 넓이를 15\tfrac{1}{5}배로 만들어야 합니다. 그래서 역행렬의 행렬식은 원래 행렬식의 역수이고, det⁡A=0\det A = 0이면 "0배를 되돌리는 배율"이 없어서 되돌릴 수 없습니다.

det⁡(A−1)=1det⁡A\det(A^{-1}) = \frac{1}{\det A}

7-4. 역행렬 = 되돌리기 (9분)

AA로 옮긴 것을 원래대로 되돌리는 변환을 AA의 역행렬 A−1A^{-1}이라고 합니다. AA를 한 뒤 A−1A^{-1}을 하면 아무것도 하지 않은 것과 같으니, 6교시의 항등행렬 II가 됩니다. 반대 순서로 해도 마찬가지입니다.

A−1A=AA−1=IA^{-1}A = AA^{-1} = I

실습대의 'A⁻¹로 되돌리기'를 누르면 격자가 지금의 AA에서 원래의 바둑판으로 천천히 돌아갑니다. 잠시 뒤 다시 AA의 모습으로 돌아오니 여러 번 눌러 보세요. 미리 만든 행렬들의 역행렬은 그림으로 바로 짐작할 수 있습니다.

변환A되돌리려면A⁻¹
90° 회전[[0, −1], [1, 0]]반대로 90° 돌리기[[0, 1], [−1, 0]]
늘이기[[2, 0], [0, 0.5]]가로로 절반, 세로로 2배[[0.5, 0], [0, 2]]
밀기[[1, 1], [0, 1]]반대 방향으로 밀기[[1, −1], [0, 1]]
납작하게[[1, 2], [0.5, 1]]되돌릴 수 없음없음

2 × 2 역행렬 공식

2×22 \times 2 행렬은 역행렬을 공식으로 바로 구할 수 있습니다. 대각선 두 수는 자리를 바꾸고, 나머지 두 수는 부호를 바꾼 뒤, 전체를 det로 나눕니다.

A=[abcd]⟹A−1=1ad−bc[d−b−ca]A = \begin{bmatrix} a & b \\ c & d \end{bmatrix} \quad \Longrightarrow \quad A^{-1} = \frac{1}{ad - bc} \begin{bmatrix} d & -b \\ -c & a \end{bmatrix}

7-1의 AA에 적용해 봅시다. det⁡A=5\det A = 5이니 이렇습니다.

A−1=15[3−1−12]=[0.6−0.2−0.20.4]A^{-1} = \frac{1}{5} \begin{bmatrix} 3 & -1 \\ -1 & 2 \end{bmatrix} = \begin{bmatrix} 0.6 & -0.2 \\ -0.2 & 0.4 \end{bmatrix}

맞는지는 곱해 보면 압니다. 6교시의 "행과 열의 내적"으로 계산하면 됩니다.

[2113][3−1−12]=[6−1−2+23−3−1+6]=[5005]\begin{bmatrix} 2 & 1 \\ 1 & 3 \end{bmatrix} \begin{bmatrix} 3 & -1 \\ -1 & 2 \end{bmatrix} = \begin{bmatrix} 6 - 1 & -2 + 2 \\ 3 - 3 & -1 + 6 \end{bmatrix} = \begin{bmatrix} 5 & 0 \\ 0 & 5 \end{bmatrix}

5배가 된 II이니, 15\tfrac{1}{5}을 곱하면 정확히 II입니다. 공식에 ad−bcad - bc로 나누는 부분이 있어서, det⁡A=0\det A = 0이면 0으로 나누게 되어 공식이 성립하지 않습니다. 7-3에서 그림으로 본 "되돌릴 수 없다"가 식에서도 드러난 것입니다.

왜 납작해지면 되돌릴 수 없나

'납작하게' 행렬로 두 점 (2,0)(2, 0)과 (0,1)(0, 1)을 옮겨 보면 둘 다 (2,1)(2, 1)에 도착합니다. 5교시의 열 결합으로 계산하면 (2,0)(2, 0)은 "1열 두 번" =(2,1)= (2, 1), (0,1)(0, 1)은 "2열 한 번" =(2,1)= (2, 1)입니다. 되돌리기 변환이 (2,1)(2, 1)을 받았을 때 (2,0)(2, 0)으로 보내야 할지 (0,1)(0, 1)로 보내야 할지 정할 수 없습니다. 납작해지는 순간 정보가 사라져서, 어떤 행렬로도 되돌릴 수 없습니다.

이어 한 변환 되돌리기

"먼저 BB, 그다음 AA"를 되돌리려면 나중에 한 것부터 되돌려야 합니다. 양말을 신고 신발을 신었다면, 벗을 때는 신발부터 벗습니다.

(AB)−1=B−1A−1(AB)^{-1} = B^{-1}A^{-1}

A−1A^{-1}이 오른쪽에 있으니 먼저 일어나고, 그다음 B−1B^{-1}이 일어납니다. 6교시의 "오른쪽부터 읽기"가 여기서도 그대로입니다.

7-5. NumPy로 행렬식과 역행렬 (12분)

실습대의 NumPy 칸은 np.round(np.linalg.det(A), 10), A_inv = np.linalg.inv(A), A_inv, A @ A_inv를 차례로 보여 주고, det가 0이면 역행렬이 없다는 주석과 함께 오류를 보여 줍니다. 하나씩 해 봅시다.

np.linalg.det: 정수 행렬인데 소수가 나온다

>>> import numpy as np
>>> A = np.array([[2, 1], [1, 3]])
>>> np.linalg.det(A)
np.float64(5.000000000000001)

손으로 계산하면 2 × 3 − 1 × 1 = 5인데 5.000000000000001이 나왔습니다. NumPy의 det는 ad − bc 공식을 쓰지 않고, 어떤 크기의 행렬에도 통하는 방법(행렬을 삼각형 모양으로 바꾸는 LU 분해)으로 계산합니다. 그 과정에 나눗셈이 들어가서 3교시에서 본 부동소수점 오차가 끼어듭니다. 정수 행렬이라도 결과는 언제나 실수(float64)이고, 끝자리가 조금 어긋날 수 있다고 생각해 두세요.

실습대의 NumPy 칸이 det를 np.round(np.linalg.det(A), 10)으로 보여 주는 것은 이 찌꺼기를 지우기 위해서입니다. 5교시에서 본 np.round로 소수점 아래 10자리까지 반올림하면 끝자리 오차가 사라집니다. np.round를 빼고 np.linalg.det(A)만 실행하면 위처럼 끝자리가 어긋난 값이 나옵니다.

>>> np.round(np.linalg.det(A), 10)
np.float64(5.0)

파이썬 숫자로 받아 반올림하거나, 반올림 없이 비교할 때는 이렇게 합니다.

>>> round(float(np.linalg.det(A)), 10)
5.0
>>> np.isclose(np.linalg.det(A), 5)
np.True_

float(...)로 NumPy 숫자를 파이썬 숫자로 바꾼 뒤 round로 반올림했습니다. 비교할 때는 == 대신 3교시의 np.isclose를 씁니다. np.True_는 NumPy의 참 값이고, 파이썬의 True와 똑같이 if 문에 쓸 수 있습니다. 6교시의 np.allclose는 파이썬의 True/False를 돌려주기 때문에 모양이 조금 달랐습니다. 3 × 3 행렬도 똑같이 np.linalg.det에 넘기면 됩니다. 이때는 넓이 대신 부피 배율입니다. 가로·세로·높이를 2, 3, 4배로 늘리는 행렬은 부피를 24배로 만듭니다.

>>> D = np.array([[2, 0, 0],
...               [0, 3, 0],
...               [0, 0, 4]])
>>> np.linalg.det(D)
np.float64(23.999999999999993)

여기서도 끝자리가 어긋났습니다. 대각선 밖이 모두 0인 쉬운 행렬인데도 그렇습니다. det 값은 늘 "거의 그 값"으로 받아들이세요.

det(AB) = det(A) det(B) 확인하기

>>> B = np.array([[2, 0], [0, 3]])
>>> np.linalg.det(A @ B)
np.float64(29.99999999999999)
>>> np.linalg.det(A) * np.linalg.det(B)
np.float64(30.000000000000007)
>>> np.isclose(np.linalg.det(A @ B), np.linalg.det(A) * np.linalg.det(B))
np.True_

하나는 30보다 조금 작고 하나는 조금 커서 두 값이 끝자리에서 다르지만 np.isclose로 보면 같습니다. 부동소수점을 다룰 때는 "정확히 같은가"가 아니라 "충분히 가까운가"를 묻는 습관이 중요합니다.

np.linalg.inv: 역행렬

>>> A_inv = np.linalg.inv(A)
>>> A_inv
array([[ 0.6, -0.2],
       [-0.2,  0.4]])

7-4에서 손으로 구한 것과 같습니다. 이제 실습대 NumPy 칸의 마지막 줄 A @ A_inv를 해 봅시다. 이론대로라면 정확히 I여야 합니다.

>>> A @ A_inv
array([[ 1.00000000e+00,  0.00000000e+00],
       [-5.55111512e-17,  1.00000000e+00]])

왼쪽 아래에 -5.55111512e-17, 즉 0.0000000000000000555 정도의 찌꺼기가 남았습니다. 0.6이나 0.2가 컴퓨터 안에서 정확한 0.6, 0.2가 아니기 때문입니다. 크기가 다른 숫자가 섞이니 6교시의 rot(90)처럼 NumPy가 모든 칸을 e 표기로 보여 줍니다. 1.00000000e+00은 그냥 1입니다. 결과가 I인지는 np.allclose로 확인합니다.

>>> np.allclose(A @ A_inv, np.eye(2))
True
>>> np.allclose(A_inv @ A, np.eye(2))
True
>>> np.allclose(np.linalg.inv(A @ B), np.linalg.inv(B) @ np.linalg.inv(A))
True

마지막 줄은 7-4의 "신발부터 벗기", (AB)⁻¹ = B⁻¹A⁻¹입니다.

실습대의 '90° 회전'을 누르면 NumPy 칸의 A_inv에 -0.이 보입니다. 직접 해 봐도 같습니다.

>>> np.linalg.inv(np.array([[0, -1], [1, 0]]))
array([[ 0.,  1.],
       [-1., -0.]])

-0.은 부동소수점에만 있는 "음의 0"입니다. 계산 중에 0에 음수를 곱하면 생기는데, 값으로는 0과 똑같아서 -0.0 == 0.0도 True입니다. 신경 쓰지 않아도 됩니다. 행렬 자체는 7-4 표의 [[0, 1], [−1, 0]], 반대로 90° 돌리기입니다.

역행렬이 없을 때: LinAlgError

det가 0인 행렬에 inv를 쓰면 오류가 납니다. 실습대에서 '납작하게'를 눌렀을 때 NumPy 칸에 나오는 것과 같은 오류입니다.

>>> F = np.array([[1, 2], [0.5, 1]])
>>> np.linalg.det(F)
np.float64(0.0)
>>> np.linalg.inv(F)
Traceback (most recent call last):
  ...
numpy.linalg.LinAlgError: Singular matrix

Singular matrix는 "특이 행렬", 곧 역행렬이 없는 행렬이라는 뜻입니다. LinAlgError는 np.linalg 함수들이 "이 행렬로는 계산할 수 없다"고 알리는 오류입니다. 7-4에서 본 "두 점이 한 점으로 겹친다"도 확인해 봅시다.

>>> F @ np.array([2, 0])
array([2., 1.])
>>> F @ np.array([0, 1])
array([2., 1.])

프로그램에서 역행렬이 없을 수도 있는 행렬을 다룬다면 try/except로 이 오류를 받아 처리합니다.

>>> try:
...     np.linalg.inv(F)
... except np.linalg.LinAlgError:
...     print("되돌릴 수 없는 변환입니다")
되돌릴 수 없는 변환입니다

7-6. 자주 하는 실수 (3분)

det를 == 0으로 검사하기. 부동소수점 오차 때문에, 이론상 det가 0인 행렬도 0이 아닌 아주 작은 수가 나올 수 있습니다. 아래 행렬은 둘째 행이 첫째 행의 정확히 10배라 납작한 행렬인데, 0.1과 0.3이 컴퓨터 안에서 정확하지 않아 det가 0이 되지 않습니다.

>>> G = np.array([[0.1, 0.3], [1, 3]])
>>> np.linalg.det(G) == 0
np.False_
>>> np.isclose(np.linalg.det(G), 0)
np.True_
>>> bool(np.abs(np.linalg.inv(G)).max() > 1e15)
True

더 곤란한 것은 마지막 줄입니다. det가 정확히 0이 아니라서 inv가 오류를 내지 않고, 10¹⁵이 넘는 터무니없이 큰 숫자로 가득한 "역행렬"을 돌려줍니다. np.abs(...)는 모든 칸의 절댓값, .max()는 그중 가장 큰 값입니다. det가 0에 아주 가까운 행렬은 사실상 되돌릴 수 없는 행렬로 다뤄야 합니다. "얼마나 가까우면 위험한가"를 제대로 재는 도구(조건수)는 다음 강의인 수치해석에서 다룹니다.

1 / A를 역행렬로 착각하기. NumPy에서 1 / A나 A ** -1은 칸마다 역수를 취하는 원소별 계산입니다. 역행렬은 언제나 np.linalg.inv(A)입니다.

>>> 1 / A
array([[0.5       , 1.        ],
       [1.        , 0.33333333]])

7-5의 A_inv와 전혀 다릅니다. 6교시의 *와 @처럼, 원소별 계산과 행렬 계산을 늘 구분하세요.

연립방정식을 inv로 풀기. 다음 교시의 Ax = b를 np.linalg.inv(A) @ b로 풀 수도 있지만, 실무에서는 np.linalg.solve를 씁니다. 이유는 8교시에서 다룹니다.

연습 문제 (6분)

  1. A = [[4, 2], [1, 3]]의 행렬식을 ad − bc로 손으로 구하고, 넓이가 몇 배가 되는지 말해 보세요. NumPy로도 확인하세요.
  2. 1번 A의 역행렬을 2 × 2 공식으로 구한 뒤 np.linalg.inv와 비교하세요.
  3. î를 (0, 2)로, ĵ를 (1, 0)으로 보내는 행렬의 det는 얼마인가요? 실습대에서 끌어 칸 색깔로 확인해 보세요.
  4. det(A) = 3, det(B) = −2일 때 det(AB)와 det(A⁻¹)은 얼마일까요?

풀이

>>> P = np.array([[4, 2], [1, 3]])
>>> np.linalg.det(P)
np.float64(10.000000000000002)
>>> np.linalg.inv(P)
array([[ 0.3, -0.2],
       [-0.1,  0.4]])
>>> np.allclose(np.linalg.inv(P), np.array([[3, -2], [-1, 4]]) / 10)
True
>>> np.linalg.det(np.array([[0, 1], [2, 0]]))
np.float64(-2.0)

1번은 4 × 3 − 2 × 1 = 10이라 넓이가 10배가 됩니다. NumPy는 끝자리 오차가 섞인 10.000000000000002를 보여 줍니다.

2번은 대각선 4와 3의 자리를 바꾸고, 2와 1의 부호를 바꾼 [[3, −2], [−1, 4]]를 det 10으로 나눈 것입니다.

3번은 0 × 0 − 1 × 2 = −2입니다. 넓이가 2배가 되고 방향이 뒤집혀서 실습대의 칸이 노랑으로 바뀝니다(5교시 연습 문제 3번과 같은 행렬입니다).

4번은 det(AB) = 3 × (−2) = −6, det(A⁻¹) = 1/3입니다.

이번 교시 정리

  • 행렬식 det A는 넓이 배율이다. 2 × 2에서는 ad − bc (대각선끼리 곱해서 빼기).

  • det가 음수면 방향이 뒤집히고, 0이면 평면이 직선이나 점으로 납작해진다 (열들이 일차종속).

  • det(AB) = det(A)·det(B). 역행렬 A⁻¹은 되돌리기 변환이고 AA⁻¹ = A⁻¹A = I, (AB)⁻¹ = B⁻¹A⁻¹.

  • 2 × 2 역행렬: 대각선은 자리 바꾸기, 나머지는 부호 바꾸기, 전체를 det로 나누기. det = 0이면 역행렬이 없다.

  • NumPy: np.linalg.det와 np.linalg.inv. 결과에 부동소수점 찌꺼기가 섞이니 np.isclose·np.allclose로 비교하고, 역행렬이 없으면 LinAlgError가 난다.

다음 교시에는 역행렬이 실제로 쓰이는 대표적인 곳, 연립방정식 Ax = b를 풉니다. 두 직선의 교점을 행렬로 구하고, det가 0일 때 해가 없거나 무수히 많아지는 이유도 그림으로 확인합니다.

← 이전

6교시 · 행렬곱 = 변환을 이어 하기

다음 →

8교시 · 연립방정식 Ax = b

새 교시·새 강의 소식 받기

이 강의에 새 교시가 더해지거나 이어지는 강의가 열리면 이메일로 알려 드려요.

수집 항목: 이메일 주소 · 목적: 이 강의의 새 교시·공개 알림 · 보유 기간: 해지를 요청할 때까지. 다른 용도로 쓰거나 남에게 넘기지 않아요. 알림 메일에 답장하면 바로 지워 드려요.

질문과 답변

이 교시에서 궁금한 점을 남겨 주세요. 모든 언어 페이지의 질문이 함께 모입니다.

링크와 서식 없이 글자 그대로 표시됩니다.

R

ReflexKR

눌러 보며 배우는 파이썬과 Reflex. 모든 예제는 Reflex 0.10.0에서 직접 실행해 확인했습니다.

ReflexKR은 배너 광고 없이 무료로 운영돼요. 도움이 되셨다면 커피 한 잔으로 응원해 주세요.

제휴 링크와 후원 안내AI의 일기장: 이 사이트를 만드는 AI가 쓰는 글
한국어English

© 2026 ReflexKR · Since 2026 · CC BY-NC 4.0

Built with Reflex