[chapter 4] 행렬, 파트 1 : 행렬과 행렬의 기본 연산
4-1
3 x 4 행렬 생성 후, 두 번째 행 네 번째 열의 원소 추출하기.
A = np.arange(12).reshape(3,4)
a = 1
b = 3
print(f'The matrix element at index ({a+1}, {b+1}) is {A[a, b]}')
4-2
그림 4-6의 왼쪽 행렬 C를 만들고 파이썬의 슬라이싱을 사용해 처음 5개의 행과 5개의 열로 이루어진 하위 행렬 추출하기.
이 행렬을 $C_1$이라 부른다.
A = np.arange(100).reshape(10,10)
C1 = A[0:5:1, 0:5:1]
print(C1)
#[[ 0 1 2 3 4]
# [10 11 12 13 14]
# [20 21 22 23 24]
# [30 31 32 33 34]
# [40 41 42 43 44]]
4-3
4-2에서 추출한 행렬을 확장해 다른 4개의 5x5 블록을 추출하기.
그리고 그림 4-7처럼 블록들을 재구성해 새로운 행렬을 만들기.
A = np.arange(100).reshape(10,10)
C1 = A[0:5:1, 0:5:1]
C2 = A[5:10:1, 0:5:1]
C3 = A[0:5:1, 5:10:1]
C4 = A[5:10:1, 5:10:1]
newMatrix = np.vstack( (np.hstack((C4,C2)), # np.hstack((A, B)) : 가로로 붙임. row 개수가 같아야 함
np.hstack((C3,C1))) ) # np.vstack((A, B)) : 세로로 붙임. col 개수가 같아야 함
print(newMatrix)
#[[55 56 57 58 59 50 51 52 53 54]
# [65 66 67 68 69 60 61 62 63 64]
# [75 76 77 78 79 70 71 72 73 74]
# [85 86 87 88 89 80 81 82 83 84]
# [95 96 97 98 99 90 91 92 93 94]
# [ 5 6 7 8 9 0 1 2 3 4]
# [15 16 17 18 19 10 11 12 13 14]
# [25 26 27 28 29 20 21 22 23 24]
# [35 36 37 38 39 30 31 32 33 34]
# [45 46 47 48 49 40 41 42 43 44]]
4-4
행과 열에 대해 for 루프 사용해서 원소별 행렬 덧셈 구현하기. 크기가 일치하지 않는 행렬을 더하면 어떻게 될까
A = np.zeros((6,4))
B = np.ones((6,4))
C = np.zeros(A.shape)
for i in range(A.shape[0]):
for j in range(A.shape[1]):
C[i,j] = A[i,j] + B[i,j]
print(C)
# 크기가 일치하지 않는 행렬을 더하면 IndexError가 발생한다.
4-5
3 x 4 크기의 두 개의 난수 행렬과 난수 스칼라를 만들고, 아래를 증명하기.
$$ \sigma(A+B) = \sigma A + \sigma B = A \sigma + B \sigma $$
x = np.random.rand()
A = np.random.rand(3,4)
B = np.random.rand(3,4)
left = x*(A+B)
center = x*A + x*B
right = A*x + B*x
print(np.round(2*left - center-right, 8))
#[[ 0. 0. 0. 0.]
# [ 0. 0. -0. 0.]
# [ 0. 0. -0. 0.]]
# = 세 개의 결과가 모두 같다.
4-6
for 루프 사용해 행렬 곱셈 코딩한 뒤, NumPy @ 연산자를 활용해 결과를 비교하기.
A = np.random.randn(4,3)
B = np.random.randn(3,4)
C1 = np.zeros((4,4))
for i in range(A.shape[0]):
for j in range(B.shape[1]):
C1[i,j] = np.dot(A[i,:], B[:,j])
C2 = A@B
print(C1)
print(C2) # 두 결과가 같다
4-7
다음의 5단계를 활용하여 LIVE EVIL 규칙을 확인하기.
- 네 개의 난수 행렬 L,I,V,E를 생성하기. 각각 크기는 2x6, 6x3, 3x5, 5x2
- 이 네 개의 행렬을 곱한 다음 전치
- 각 행렬을 전치한 뒤, 순서를 바꾸지 않고 모두 곱함
- 각 행렬을 전치한 뒤, LIVE EVIL 규칙에 따라 역순으로 모두 곱함
2단계의 결과가 3, 4단계와 일치하는지 확인하기.
# 난수 행렬 생성
L = np.random.randn(2,6)
I = np.random.randn(6,3)
V = np.random.randn(3,5)
E = np.random.randn(5,2)
# 이 네 개의 행렬을 곱한 다음 전치
A1 = np.transpose(L@I@V@E)
# 각 행렬을 전치한 뒤, 순서를 바꾸지 않고 모두 곱함
# A2 = L.T @ I.T @ V.T @ E.T - 에러남
# 각 행렬을 전치한 뒤, LIVE EVIL 규칙에 따라 역순으로 모두 곱함
A3 = E.T @ V.T @ I.T @ L.T
print(A1)
print(A3) # 두 결과가 같다.
4-8
행렬의 대칭 여부를 확인하는 파이썬 함수 작성하기.
행렬을 입력받고 그 행렬이 대칭이면 True, 행렬이 비대칭이면 False를 출력해야 한다.
def isMatrixSymmetric(S):
# S가 대칭행렬이면 D는 모든 원소가 0인 행렬이 된다.
D = S-S.T
# D의 모든 항을 제곱해서 더한다 → 오차의 합(SSE)
# 완전 대칭행렬이면 D = 0 → SSE = 0
sse = np.sum(D**2)
# 부동소수점 연산에는 항상 아주 작은 오차가 있을 수 있어서 완전히 0인지 확인하면 안 됨
# 거의 0에 가까우면 대칭이라고 인정
return sse < 10**-15
4-9
비대칭 사각 행렬로부터 대칭 행렬을 만들기 위해서는 행렬을 자신의 전치로 평균화하면 된다.
파이썬에서 이를 구현하고, 결과가 대칭인지 확인하기.
A = np.random.randn(4,4)
AtA = (A + A.T) / 2
a = isMatrixSymmetric(AtA)
print(a)
4-10
연습문제 2-3의 두 번째 부분을 다시 구현하는데, 이번에는 스칼라-벡터 곱셈 대신 행렬-벡터 곱셈을 사용하기.
# 3차원 벡터 2개
# v1 = np.array([ 3,5,1 ])
# v2 = np.array([ 0,2,2 ])
# 연습문제 2-3에서 사용했던 위 벡터 2개 말고 행렬 사용
A = np.array( [ [3,0],
[5,2],
[1,2] ] )
xlim = [-4,4]
scalars = np.random.uniform(low=xlim[0],high=xlim[1],size=(100,2))
points = np.zeros((100,3))
for i in range(len(scalars)):
points[i,:] = A@scalars[i] # 행렬-벡터 곱셈
# draw the dots in the figure
fig = go.Figure( data=[go.Scatter3d(x=points[:,0], y=points[:,1], z=points[:,2], mode='markers')])
fig.show()
4-11
대각행렬의 속성 두가지는 아래와 같다.
- 대각 행렬을 왼쪽에서 곱하면 오른쪽 행렬의 행이 해당 대각 원소 크기만큼 조정된다.
- 대각 행렬을 오른쪽에서 곱하면 왼쪽 행렬의 열이 행 대각 원소 크기만큼 조정된다.
세 개의 4x4 행렬을 만드는데, 모든 원소가 1인 행렬, 대각 원소가 1, 4, 9, 16인 대각 행렬, 이전 대각 행렬의 원소의 제곱근으로 이루어진 대각행렬이다.
첫 번째 대각 행렬을 모든 원소가 1인 행렬의 앞과 뒤에서 각각 곱한 행렬을 출력하면 다음과 같다.
# 대각 행렬을 왼쪽에서 곱함
[
[1. 1. 1. 1.]
[4. 4. 4. 4.]
[9. 9. 9. 9.]
[16. 16. 16. 16]
]
# 대각 행렬을 오른쪽에서 곱함
[
[1. 4. 9. 16.]
[1. 4. 9. 16.]
[1. 4. 9. 16.]
[1. 4. 9. 16.]
]
제곱근한 대각 행렬을 모든 원소가 1인 행렬의 앞과 뒤에서 곱하면 다음과 같은 결과가 나온다.
# 제곱근한 대각 행렬을 앞과 뒤에서 곱함
[
[1. 2. 3. 4.]
[2. 3. 6. 8.]
[3. 6. 9. 12.]
[4. 8. 12. 16.]
]
즉, 결과 행렬의 (i,j) 번째 원소가 대각 행렬의 i번째와 j번째 원소의 곱만큼 증가하도록 행과 열의 크기가 조정된다.
4-12
대각 행렬 곱셈은 아다마르곱과 같다.
두 개의 3x3 대각 행렬에 대해 파이썬 코드로 작성하기.
# Create two diagonal matrices
N = 5
D1 = np.diag( np.random.randn(N) )
D2 = np.diag( np.random.randn(N) )
# two forms of multiplication
hadamard = D1*D2
standard = D1@D2
# compare them
hadamard - standard'수학 > 선형대수' 카테고리의 다른 글
| [개발자를 위한 실전 선형대수학] 5.3 계수, 5.4 계수 응용, 5.5 행렬식 (0) | 2025.12.11 |
|---|---|
| [개발자를 위한 실전 선형대수학] 5.1 행렬 노름, 5.2 행렬 공간 (0) | 2025.12.10 |
| [개발자를 위한 실전 선형대수학] 4.3 표준 행렬 곱셈, 4.4 행렬 연산: 전치, 4.5 행렬 연산: LIVE EVIL(연산 순서), 4.6 대칭 행렬 (0) | 2025.12.05 |
| [개발자를 위한 실전 선형대수학] 4.1 NumPy에서 행렬 생성과 시각, 4.2 행렬 수학:덧셈, 스칼라 곱셈, 아다마르곱 (0) | 2025.12.02 |
| [개발자를 위한 실전 선형대수학] Chapter 3 연습문제 (0) | 2025.11.27 |