[Linear algebra] 3.2 좌표와 변환

JKH·약 8시간 전
0

선형대수

목록 보기
5/5

데이터 사이언스 스쿨 에서 공부한 내용입니다.

3.2 좌표와 변환

이 절에서는 공간상에서 좌표를 정의하기 위해 필요한 개념을 살펴본다. 우선 벡터의 선형독립과 랭크의 개념을 알아보고 기저벡터와 좌표변환이 선형대수와 어떻게 연관이 있는지 공부한다. 좌표변환은 이미지 처리 작업뿐 아니라 다변수 확률변수를 분석하는데도 사용된다.

선형종속과 선형독립

벡터 집합 x1,x2,,xNx_1, x_2, \ldots, x_N을 이루는 벡터의 선형조합이 영벡터가 되도록 하는 스칼라 계수 c1,c2,,cNc_1, c_2, \ldots, c_N이 존재하면 이 벡터들이 선형종속(linearly dependent) 이라고 한다. 단 c1=c2==cN=0c_1 = c_2 = \cdots = c_N = 0 으로 계수가 모두 0인 경우는 제외한다.

c1x1+c2x2++cNxN=0(3.2.1)c_1 x_1 + c_2 x_2 + \cdots + c_N x_N = 0 \tag{3.2.1}

반대로 벡터들의 선형조합이 0이 되면서 모두 0은 아닌 계수들이 존재하지 않으면 그 벡터들은 선형독립(linearly independent) 이라고 한다.

선형독립을 논리 기호로 나타내면 다음과 같다.

c1x1++cNxN=0        c1==cN=0(3.2.2)c_1 x_1 + \cdots + c_N x_N = 0 \;\; \rightarrow \;\; c_1 = \cdots = c_N = 0 \tag{3.2.2}

왼쪽에서 오른쪽 방향 화살표의 의미는 벡터들의 선형조합이 0이면 반드시 계수들이 모두 0이라는 뜻이다.

선형독립을 다음처럼 표현하기도 한다.

c1x1++cNxN=0        c1==cN=0(3.2.3)c_1 x_1 + \cdots + c_N x_N = 0 \;\; \leftrightarrow \;\; c_1 = \cdots = c_N = 0 \tag{3.2.3}

오른쪽에서 왼쪽 방향 화살표의 의미는 모든 계수가 0일 때 선형조합이 0이 된다는 뜻이다. 이는 꼭 선형독립이 아니더라도 당연하게 성립한다.

예제

다음 벡터 x1,x2x_1, x_2는 선형독립이다.

x1=[12],    x2=[33](3.2.4)x_1 = \begin{bmatrix} 1 \\ 2 \end{bmatrix}, \;\; x_2 = \begin{bmatrix} 3 \\ 3 \end{bmatrix} \tag{3.2.4}

벡터 x1x_1은 두 원소의 크기가 다른데, 벡터 x2x_2는 두 원소의 크기가 같기 때문에 어떤 계수를 사용해도 c1x1+c2x2=0c_1x_1 + c_2x_2 = 0을 만들 수 없다.

예제

다음 벡터 x1,x2,x3x_1, x_2, x_3는 선형종속이다.

x1=[12],    x2=[33],    x3=[57](3.2.5)x_1 = \begin{bmatrix} 1 \\ 2 \end{bmatrix}, \;\; x_2 = \begin{bmatrix} 3 \\ 3 \end{bmatrix}, \;\; x_3 = \begin{bmatrix} 5 \\ 7 \end{bmatrix} \tag{3.2.5}

이는 다음과 같은 식으로 증명할 수 있다.

2x1+x2x3=0(3.2.6)2x_1 + x_2 - x_3 = 0 \tag{3.2.6}

파이썬으로 계산한 결과도 영벡터이다.

import numpy as np

x1 = np.array([1, 2])
x2 = np.array([3, 3])
x3 = np.array([10, 14])
2 * x1 + x2 - 0.5 * x3
array([0., 0.])

연습 문제 3.2.1

다음 벡터들이 선형독립인지 선형종속인지 판별하라. 선형종속이면 영벡터를 만드는 계수값을 찾아라.

(1)

x1=[10],    x2=[01](3.2.7)x_1 = \begin{bmatrix}1 \\ 0\end{bmatrix} ,\;\; x_2 = \begin{bmatrix}0 \\ 1\end{bmatrix} \tag{3.2.7}

✒️
선형독립

(2)

x1=[10],    x2=[11](3.2.8)x_1 = \begin{bmatrix}1 \\ 0\end{bmatrix} ,\;\; x_2 = \begin{bmatrix}-1 \\ 1\end{bmatrix} \tag{3.2.8}

✒️
선형독립

(3)

x1=[12],    x2=[24](3.2.9)x_1 = \begin{bmatrix}1 \\ 2\end{bmatrix} ,\;\; x_2 = \begin{bmatrix}2 \\ 4\end{bmatrix} \tag{3.2.9}

✒️
선형종속
-2, 1

연습 문제 3.2.2

서로 직교하는 영벡터가 아닌 NN개의 벡터 v1,v2,,vNv_1, v_2, \cdots, v_N은 선형독립임을 증명하라.

viTvj=0      (ij)(3.2.10)v_i^T v_j = 0 \;\;\; (i \neq j) \tag{3.2.10}

✒️
선형종속이라고 가정하면 c1v1 + c2v2 + ,,,+cnvn = 0 을 만족시키는 0이 아닌 c가 최소 2개 있어야한다. ci cj 가 0이 아니라고 할 때 civi를 우변으로 넘기고 양변에 vi와의 내적을 취하면
각 벡터가 서로 수직이므로 좌변은 0이 되고, 우변은 -civi놈^으로 0이 될 수 없는 값이다.
즉 가정으로 부터 모순을 얻었으므로 가정은 거짓이고 따라서 선형독립이다.

연습 문제 3.2.3

(1) 선형독립인 2개의 2차원 벡터의 예를 들어라.
✒️
(1,0), (0,1)

(2) 선형독립인 2개의 3차원 벡터의 예를 들어라.
✒️
(1,0,0), (0,1,0)

(3) 선형독립인 3개의 2차원 벡터의 예를 들어라. 이러한 벡터들이 존재하는가?
✒️
존재하지 않는다. (1)의 2개의 벡터의 선형결합으로 2차원 벡터 전체집합을 생성할 수 있다.

(4) 선형독립인 3개의 3차원 벡터의 예를 들어라. 이러한 벡터들이 존재하는가?
✒️
존재한다. (1,0,0), (0,1,0), (0,0,1)

(5) 선형독립인 4개의 3차원 벡터의 예를 들어라. 이러한 벡터들이 존재하는가?
✒️
존재하지 않는다. (4)의 3개의 벡터의 선형결합으로 3차원 벡터 전체집합을 생성할 수 있다.

선형독립과 선형 연립방정식

선형독립 관계를 행렬과 벡터의 곱으로 나타낼 수도 있다. 다음 식에서 cic_ixix_i에 대한 가중치 계수이고 cccic_i를 원소로 가지는 가중치 벡터이다. XX는 열벡터 x1,x2,,xNx_1, x_2, \ldots, x_N를 열로 가지는 행렬이다. 이제부터는 벡터의 집합으로 모두 이런 식으로 행렬로 표시하겠다.

c1x1++cNxN=[x1x2xN][c1c2cN]=Xc(3.2.11)c_1 x_1 + \cdots + c_N x_N = \begin{bmatrix} x_1 & x_2 & \cdots & x_N \end{bmatrix} \begin{bmatrix} c_1 \\ c_2 \\ \vdots \\ c_N \end{bmatrix} = X c \tag{3.2.11}

따라서 어떤 벡터들이 선형독립인지 아닌지를 알아내는 문제는 선형 연립방정식을 푸는 문제와 같다.

Xc=0(3.2.12)Xc=0 \tag{3.2.12}

이 연립방정식의 해가 영벡터밖에 없으면 선형독립이다. 만약 영벡터가 아닌 해가 존재하면 선형종속이다. 해가 무한히 많은 경우에는 그 중에 영벡터가 아닌 해가 반드시 존재하므로 선형 종속이다.

벡터 x1,x2,,xNx_1, x_2, \ldots, x_N이 선형독립이라는 것을 논리기호로 나타내면 다음과 같다.

Xc=0        c=0(3.2.13)Xc = 0 \;\; \rightarrow \;\; c=0 \tag{3.2.13}

c=0c=0이면 Xc=0Xc = 0은 당연히 성립하므로 위 식 대신 다음처럼 쓰기도 한다.

Xc=0        c=0(3.2.14)Xc = 0 \;\; \leftrightarrow \;\; c=0 \tag{3.2.14}

선형종속인 경우

벡터가 선형종속이 되는 대표적인 세 경우를 알아보자. 예측모형을 만들기 위한 특징행렬 XX의 열벡터들이 선형종속이거나 선형종속에 가까운 현상을 다중공선성(multicollinearity) 이라고 부른다. 다중공선성이 발생하면 예측의 성능이 나빠지므로 되도록 이러한 경우가 발생하지 않도록 주의해야 한다.

경우 1: 벡터의 개수가 벡터의 차원보다 크면 선형종속이다.

벡터의 차원보다 벡터의 수가 많으면 그 벡터를 행으로 가지는 행렬 XX의 행의 개수보다 열의 개수가 많다. 따라서 이 행렬이 표현하는 연립방정식을 고려하면 미지수의 수가 방정식의 수보다 커서 해가 무한히 많다. 해가 무한히 많다는 것은 영벡터가 아닌 해 cc도 존재한다는 뜻이다. 따라서 그 벡터들은 선형종속이다.

반대로 행의 개수가 열의 개수와 같거나 크면 대부분 선형독립이다. 우리가 분석할 대부분의 데이터는 데이터(행)의 수가 특징(열)의 수보다 많기 때문에 여기에 해당한다.

경우 2: 값이 같은 벡터가 있으면 반드시 선형종속이다.

만약 ii번째 벡터 xjx_jjj번째 벡터 xjx_j가 같으면 cj=cic_j = -c_i로 놓고 다른 cc값은 모두 0으로 하면

0x1++cixi++cjxj++0xN=0x1++cixi++(ci)xj++0xN=0(3.2.15)\begin{aligned} & 0 \cdot x_1 + \cdots + c_i \cdot x_i +\cdots + c_j \cdot x_j + \cdots + 0 \cdot x_N \\ &= 0 \cdot x_1 + \cdots + c_i \cdot x_i +\cdots + (-c_i) \cdot x_j + \cdots + 0 \cdot x_N \\ &= 0 \end{aligned} \tag{3.2.15}

따라서 다음처럼 중복된 데이터가 있으면 선형종속이다.

[151363464](3.2.16)\begin{bmatrix} 1 & 5 & 1 \\ 3 & 6 & 3 \\ 4 & 6 & 4 \end{bmatrix} \tag{3.2.16}

벡터 xjx_j가 벡터 xix_i의 실수배인 경우도 마찬가지이다.

예측 모형을 위한 특징행렬을 만들 때 실수로 위와 같은 행렬을 만드는 경우가 종종 있다. 우리가 실무에서 다루게 되는 데이터는 그 양이 크기 때문에 엑셀 등으로 한 눈에 볼 수 없는 경우가 많아서 위와 같은 실수를 하는 경우에도 빨리 발견하기 어렵다.

경우 3: 어떤 벡터가 다른 벡터의 선형조합이면 반드시 선형종속이다.

예를 들어 벡터 x1x_1과 다른 벡터 x2,x3x_2, x_3 사이에 다음 관계가 성립한다고 하자.

x1=2x23x3(3.2.17)x_1 = 2 x_2 - 3 x_3 \tag{3.2.17}

그러면 c1=1,c2=2c3=3c_1=-1, c_2=2 c_3=-3일 때

1x1+2x23x3=0(3.2.18)-1\cdot x_1 + 2 x_2 - 3 x_3 = 0 \tag{3.2.18}

이므로 선형종속이다.

이 경우도 데이터 분석에서 흔히 하는 실수이다. 예를 들어 국어, 영어, 수학 점수를 각각 별도의 데이터로 포함하면서 이 세 점수에 의존하는 총점수나 평균을 다시 데이터로 포함하면 선형종속이 된다.

랭크

행렬의 열벡터 중 서로 독립인 열벡터의 최대 개수를 열랭크(column rank) 라고 하고

행벡터 중 서로 독립인 행벡터의 최대 개수를 행랭크(row rank) 라고 한다.

행랭크와 열랭크에 대해서는 다음 정리가 성립한다.

[정리] 행랭크와 열랭크는 항상 같다.

따라서 행 랭크나 열 랭크를 그냥 랭크(rank) 라고 하기도 한다.

행렬 AA의 랭크는 기호로 rankA\text{rank}A와 같이 표시한다.

행랭크는 행의 개수보다 커질 수 없고 열랭크는 열의 개수보다 커질 수 없기 때문에 행의 개수가 NN이고 열의 갯수가 MM인 행렬의 랭크는 행의 개수 NN과 열의 개수 MM 중 작은 값보다 커질 수 없다.

rankAmin(M,N)(3.2.19)\text{rank} A \leq \min(M, N) \tag{3.2.19}
ARN×M(3.2.20)A \in \mathbf{R}^{N \times M} \tag{3.2.20}

예제

다음 행렬 X1X_1의 두 열벡터는 선형독립이기 때문에 열랭크는 2다.

X1=[1323](3.2.21)X_1 = \begin{bmatrix} 1 & 3 \\ 2 & 3 \end{bmatrix} \tag{3.2.21}

예제

다음 행렬 X2X_2의 세 열벡터는 선형종속이므로 열랭크는 3보다는 작다. 그런데 이 열벡터 중 앞의 두 개는 서로 독립이므로 X2X_2의 랭크는 2다.

X2=[135237](3.2.22)X_2 = \begin{bmatrix} 1 & 3 & 5 \\ 2 & 3 & 7 \end{bmatrix} \tag{3.2.22}

넘파이 linalg 서브 패키지의 matrix_rank() 함수로 행렬의 랭크를 계산할 수 있다.

X1 = np.array([[1, 3], [2, 4]])
np.linalg.matrix_rank(X1)
2
X2 = np.array([[1, 3, 5], [2, 3, 7]])
np.linalg.matrix_rank(X2)
2

풀랭크

위에서 예로 든 행렬 X1X_1X2X_2처럼 랭크가 행의 개수와 열의 개수 중 작은 값과 같으면 풀랭크(full rank) 라고 한다.

rankA=min(M,N)(3.2.23)\text{rank}A = \min(M, N) \tag{3.2.23}

선형독립인 벡터들을 행 또는 열로 가지는 행렬을 만들면 정의에 의해 항상 풀랭크다.

연습 문제 3.2.4

다음 행렬의 랭크를 구하고 풀랭크인지 아닌지 말하라.

(1)

A=[15626831114145](3.2.24)A = \begin{bmatrix} 1 & 5 & 6 \\ 2 & 6 & 8 \\ 3 & 11 & 14\\ 1 & 4 & 5 \end{bmatrix} \tag{3.2.24}

(2)

B=[15626831114148](3.2.25)B = \begin{bmatrix} 1 & 5 & 6 \\ 2 & 6 & 8 \\ 3 & 11 & 14\\ 1 & 4 & 8 \end{bmatrix} \tag{3.2.25}
import numpy as np
A = np.array([1,2,3,1,5,6,11,4,6,8,14,5]).reshape(3,4).T
B = np.array([1,2,3,1,5,6,11,4,6,8,14,8]).reshape(3,4).T
np.linalg.matrix_rank(A), np.linalg.matrix_rank(B) # (2,3)

✒️
행이 4개, 열이 3개이므로 열이 선형독립이면 풀랭크다.
(1)의 경우 첫번째 컬럼과 두번째 컬럼의 합이 세번째 컬럼이다. 랭크는 2이며 풀랭크가 아니다.
(2)의 경우 세 컬럼이 선형독립이다. 풀랭크다.

로우-랭크 행렬

NN차원 벡터 xx 하나를 이용하여 만들어지는 다음과 같은 행렬을 랭크-1 행렬(rank-1 matrix) 이라고 한다.

xxTRN×N(3.2.26)xx^T \in \mathbf{R}^{N \times N} \tag{3.2.26}

이 행렬의 열벡터들은 xx라고 하는 하나의 벡터를 x1x_1배, x2x_2배, ... xnx_n배한 벡터이므로 독립적인 열벡터는 1개다. 따라서 랭크-1 행렬의 랭크는 1이다.

xxT=x[x1x2xn]=[x1xx2xxnx](3.2.27)\begin{aligned} xx^T &= x \begin{bmatrix} x_1 & x_2 & \cdots & x_n \end{bmatrix} \\ &= \begin{bmatrix} x_1x & x_2x & \cdots & x_nx \end{bmatrix} \end{aligned} \tag{3.2.27}

선형독립인 두 개의 NN차원 벡터 x1,x2x_1, x_2를 이용하여 만든 다음과 같은 행렬은 랭크-2 행렬(rank-2 matrix) 이라고 한다.

[x1x2][x1Tx2T]=x1x1T+x2x2T(3.2.28)\begin{bmatrix} x_1 & x_2 \end{bmatrix} \begin{bmatrix} x_1^T \\ x_2^T \end{bmatrix} = x_1x_1^T + x_2x_2^T \tag{3.2.28}

앞서와 비슷한 방법으로 랭크-2 행렬의 랭크는 2임을 보일 수 있다.

만약 MM개의 NN차원 벡터 x1,x2,,xMx_1, x_2, \cdots, x_M을 이용하면 랭크-M 행렬(rank-M matrix) 이 된다.

[x1x2xM][x1Tx2TxMT]=x1x1T+x2x2T++xMxMT=i=1MxixiT(3.2.29)\begin{bmatrix} x_1 & x_2 & \cdots & x_M \end{bmatrix} \begin{bmatrix} x_1^T \\ x_2^T \\ \vdots \\ x_M^T \end{bmatrix} = x_1x_1^T + x_2x_2^T + \cdots + x_Mx_M^T = \sum_{i=1}^M x_ix_i^T \tag{3.2.29}

이러한 행렬들을 가리켜 로우-랭크 행렬(low-rank matrix) 이라고 한다. 로우-랭크 행렬은 나중에 특이분해(singular value decomposition)와 PCA(principal component analysis)에서 사용된다.

연습 문제 3.2.5

(1) 다음 벡터로 랭크-1 행렬을 만들고 NumPy로 랭크를 계산하여 실제로 1이 나오는지 확인하라.

x1=[11](3.2.30)x_1 = \begin{bmatrix} 1 \\ 1 \end{bmatrix} \tag{3.2.30}

(2) 다음 두 개의 벡터로 랭크-2 행렬을 만들고 NumPy로 랭크를 계산하여 실제로 2가 나오는지 확인하라.

x1=[11],    x2=[11](3.2.31)x_1 = \begin{bmatrix} 1 \\ 1 \end{bmatrix} ,\;\; x_2 = \begin{bmatrix} 1 \\ -1 \end{bmatrix} \tag{3.2.31}
import numpy as np
A = np.array([1,1,1,1,1,1,1,1]).reshape(2,4)
B = np.array([1,1,1,-1,2,0,0,2]).reshape(2,4)
np.linalg.matrix_rank(A), np.linalg.matrix_rank(B) # (1, 2)

벡터공간과 기저벡터

여러 벡터를 선형조합을 하면 다른 벡터를 만들 수 있다. 벡터 N개가 서로 선형독립이면 이 벡터들을 선형조합하여 만들어지는 모든 벡터의 집합을 벡터공간(vector space) VV라 하고 이 벡터공간의 차원을 NN이라고 한다. 그리고 그 벡터들을 벡터공간의 기저벡터(basis vector) 라고 한다.

V={c1x1++cNxN    c1,,cNR}(3.2.32)V = \{ c_1x_1 + \cdots + c_Nx_N \; \vert \; c_1, \ldots, c_N \in \mathbf{R} \} \tag{3.2.32}

벡터공간의 차원(dimension)이 벡터의 차원(길이)가 아니라 기저벡터의 개수로 정의된다는 점에 유의해야 한다.

NN차원 벡터 NNx1,x2,,xNx_1, x_2, \cdots, x_N이 선형독립인 경우에는 다음 정리가 성립한다.

[정리] NN개의 NN차원 벡터 x1,x2,,xNx_1, x_2, \cdots, x_N이 선형독립이면 이를 선형조합하여 모든 NN차원 벡터를 만들 수 있다.

다음과 같이 증명한다. 임의의 벡터 xx가 있다고 하자. 기저벡터 x1,x2,,xNx_1, x_2, \cdots, x_N와 이 벡터 xx를 열벡터로 사용하여 만든 행렬

X=[x1,x2,,xN,x](3.2.33)X = \left[ x_1, x_2, \cdots, x_N, x \right] \tag{3.2.33}

는 크기가 N×(N+1)N \times (N+1)이므로 랭크값은 NN보다 커질 수는 없다. 그런데 NN개의 선형독립인 열벡터가 있기 때문에 랭크값은 NN이고 풀랭크다. 따라서 어떠한 NN차원 벡터를 생각하더라도 기저벡터의 조합으로 표현할 수 있다.

예제

다음 벡터의 집합은 선형독립이므로 2차원 벡터공간의 기저벡터이다.

x1=[12],    x2=[21](3.2.34)x_1 = \begin{bmatrix} 1 \\ 2 \end{bmatrix}, \;\; x_2 = \begin{bmatrix} 2 \\ 1 \end{bmatrix} \tag{3.2.34}

따라서 이 기저벡터 {x1,x2}\{x_1, x_2\}를 선형조합하면 어떠한 2차원 벡터도 만들 수 있다.

예제

다음 벡터의 집합은 선형독립이 아니므로 벡터공간의 기저벡터가 되지 않는다.

x1=[12],    x2=[21],    x3=[57](3.2.35)x_1 = \begin{bmatrix} 1 \\ 2 \end{bmatrix}, \;\; x_2 = \begin{bmatrix} 2 \\ 1 \end{bmatrix}, \;\; x_3 = \begin{bmatrix} 5 \\ 7 \end{bmatrix} \tag{3.2.35}

예제

다음 벡터의 집합은 선형독립이므로 벡터공간의 기저벡터이다.

x1=[120],    x2=[210](3.2.36)x_1 = \begin{bmatrix} 1 \\ 2 \\ 0 \end{bmatrix}, \;\; x_2 = \begin{bmatrix} 2 \\ 1 \\ 0 \end{bmatrix} \tag{3.2.36}

하지만 이 벡터공간은 3차원 벡터공간이 아니라 2차원 벡터공간이라고 한다. 예를 들어 이 벡터 x1,x2x_1, x_2를 어떻게 선형조합해도 다음 벡터는 만들 수 없다.

c1x1+c2x2=[001](3.2.37)c_1x_1 + c_2x_2 = \begin{bmatrix} 0 \\ 0 \\ 1 \end{bmatrix} \tag{3.2.37}

벡터공간의 차원을 기저벡터의 차원과 다르게 정의하는 이유는 선형독립인 기저벡터를 선형조합했을 때 이렇게 만들어낼 수 없는 벡터들이 존재하기 때문이다.

연습 문제 3.2.6

(1) 다음 기저벡터 x1,x2x_1, x_2를 선형조합하여 벡터 y1,y2y_1, y_2를 만들어라.

x1=[12],    x2=[21](3.2.38)x_1 = \begin{bmatrix} 1 \\ 2 \end{bmatrix}, \;\; x_2 = \begin{bmatrix} 2 \\ 1 \end{bmatrix} \tag{3.2.38}
y1=[33],    y2=[11](3.2.39)y_1 = \begin{bmatrix} 3 \\ 3 \end{bmatrix}, \;\; y_2 = \begin{bmatrix} -1 \\ -1 \end{bmatrix} \tag{3.2.39}

y1 = x1 + x2
y2 = -1/3( x1 + x2)

(2) 2차원 벡터공간을 만드는 2차원 기저벡터의 또다른 예를 들어라.

(1,0), (0,1)

(3) 2차원 벡터공간을 만드는 3차원 기저벡터의 또다른 예를 들어라.

(1,0,0), (0,1,0)

(4) 3차원 벡터공간을 만드는 3차원 기저벡터의 예를 들어라.

(1,0,0), (0,1,0), (0,0,1)

연습 문제 3.2.7

NN개의 NN차원 벡터 x1,x2,,xNx_1, x_2, \cdots, x_N이 기저벡터이다. 이 벡터 x1,x2,,xNx_1, x_2, \cdots, x_N 각각에 대해 모두 수직인 영벡터가 아닌 벡터 xx가 존재하지 않는다는 것을 증명하라.
✒️
존재한다고 가정하면 기저벡터가 N +1개인 N차원 벡터공간이 되어 모순이므로 존재하지 않는다.

랭크와 역행렬

정방행렬의 랭크와 역행렬 사이에는 다음과 같은 정리가 성립한다.

[정리] 정방행렬이 풀랭크면 역행렬이 존재한다. 역도 성립한다. 즉, 정방행렬의 역행렬이 존재하면 풀랭크다.

따라서 다음 두 문장은 같은 뜻이다.

정방행렬이 풀랭크다 \leftrightarrow 역행렬이 존재한다

다음과 같이 증명한다.

(1)

우선 왼쪽에서 오른쪽 방향 즉, 정방행렬이 풀랭크이면 역행렬이 존재한다는 것을 증명하자. 정방행렬이 풀랭크이면 선형독립이고 기저벡터가 되므로 어떠한 벡터에 대해서도 그 벡터를 만들 수 있는 선형조합을 생각할 수 있다. 예를 들어 다음과 같은 벡터 e1,,eNe_1, \cdots, e_N을 만들기 위한 조합 c1,,cNc_1, \cdots, c_N도 있을 수 있다.

Xc1=e1=[100](3.2.40)Xc_1 = e_1 = \begin{bmatrix} 1 \\ 0 \\ \vdots \\ 0 \end{bmatrix} \tag{3.2.40}
Xc2=e2=[010](3.2.41)Xc_2 = e_2 = \begin{bmatrix} 0 \\ 1 \\ \vdots \\ 0 \end{bmatrix} \tag{3.2.41}

이 식들을 모으면 다음과 같아진다.

X[c1c2cN]=XC=I(3.2.42)X \begin{bmatrix} c_1 & c_2 & \cdots & c_N \end{bmatrix} = XC = I \tag{3.2.42}

정방행렬의 경우 XC=IXC=I이면 CX=ICX=I가 성립한다.(연습문제 2.4.4) 따라서

XC=CX=I(3.2.43)XC = CX = I \tag{3.2.43}

인 행렬 CC가 존재한다. 이 행렬이 역행렬이다.

(2) ❗❗❗ 이해 못함 ❗❗❗

다음으로 오른쪽에서 왼쪽 방향 즉, 역행렬이 존재하면 풀랭크라는 것을 증명하자.

역행렬이 존재하는 경우에 다음 식이 성립한다는 것을 증명하면 된다.

Xc=0        c=0(3.2.44)Xc = 0 \;\; \leftrightarrow \;\; c=0 \tag{3.2.44}

(i) 우선 역행렬이 존재하든 말든 c=0c = 0이면 Xc=0Xc=0는 당연하다. 따라서 오른쪽에서 왼쪽 방향은 증명된다.

(ii) 다음으로 역행렬이 존재할 때 Xc=0Xc=0이면

X1Xc=c=0(3.2.45)X^{-1}Xc = c = 0 \tag{3.2.45}

이므로 왼쪽에서 오른쪽 방향도 증명된다. 따라서 역행렬이 존재하면 풀랭크다.

❗❗❗ 이해 못함 ❗❗❗

벡터공간 투영

MM개의 NN차원 기저벡터 v1,v2,,vMv_1, v_2, \cdots, v_M 가 존재한다고 하자. MMNN보다 작다.

이 때 모든 NN차원 벡터 xx에 대해 기저벡터 v1,v2,,vMv_1, v_2, \cdots, v_M를 선형조합하여 만든 벡터 xvx^{\Vert v}와 원래 벡터 xx의 차 xxvx - x^{\Vert v}가 모든 기저벡터에 직교하면 그 벡터 xvx^{\Vert v}v1,v2,,vMv_1, v_2, \cdots, v_M 벡터공간에 대한 투영벡터라 하고 차이 벡터 xxv=xvx - x^{\Vert v} = x^{\perp v}벡터공간에 대한 직교벡터라 한다.

(xxV){v1,v2,,vM}(3.2.46)(x - x^{\Vert V}) \perp \{ v_1, v_2, \cdots, v_M \} \tag{3.2.46}

다음 그림은 N=3,M=2N=3,M=2 즉 3차원 벡터를 2차원 벡터공간에 투영하는 예를 보인 것이다.

정규직교인 기저벡터로 이루어진 벡터공간

만약 기저벡터 v1,v2,,vMv_1, v_2, \cdots, v_M가 정규직교(orthonormal)이면 투영벡터 xvx^{\Vert v}는 각 기저벡터에 대한 내적값으로 표현된다.

xV=(xTv1)v1+(xTv2)v2++(xTvM)vM(3.2.47)x^{\Vert V} = (x^Tv_1)v_1 + (x^Tv_2)v_2 + \cdots + (x^Tv_M)v_M \tag{3.2.47}

그리고 투영벡터의 길이의 제곱은 각 기저벡터와의 내적의 제곱합이다.

xV2=i=1M(xTvi)2(3.2.48)\Vert x^{\Vert V} \Vert^2 = \sum_{i=1}^M (x^Tv_i)^2 \tag{3.2.48}

벡터 xx에서 이 벡터 xVx^{\Vert V}를 뺀 벡터 xxVx - x^{\Vert V}, 즉 직교벡터 xVx^{\perp V}가 기저벡터 v1,v2,,vMv_1, v_2, \cdots, v_M에 모두 직교한다는 것은 다음처럼 증명할 수 있다.

viT(xxv)=viTxviT((xTv1)v1+(xTv2)v2++(xTvM)vM)=viTx((xTv1)viTv1+(xTv2)viTv2++(xTvM)viTvM)=viTxxTvi=0(3.2.49)\begin{aligned} v_i^T(x - x^{\Vert v}) &= v_i^Tx - v_i^T \left( (x^Tv_1)v_1 + (x^Tv_2)v_2 + \cdots + (x^Tv_M)v_M \right) \\ &= v_i^Tx - \left( (x^Tv_1)v_i^Tv_1 + (x^Tv_2)v_i^Tv_2 + \cdots + (x^Tv_M)v_i^Tv_M \right) \\ &= v_i^Tx - x^Tv_i \\ &= 0 \end{aligned} \tag{3.2.49}

따라서 직교벡터 xVx^{\perp V}는 기저벡터 v1,v2,,vMv_1, v_2, \cdots, v_M으로 이루어진 벡터공간의 모든 벡터에 대해 직교한다.

이 사실로부터 벡터 xx의 투영벡터 xVx^{\Vert V}은 기저벡터 v1,v2,,vMv_1, v_2, \cdots, v_M으로 이루어진 벡터공간의 모든 벡터 중에서 가장 벡터 xx와 가까운 벡터라는 것도 알 수 있다.

기저벡터 v1,v2,,vMv_1, v_2, \cdots, v_M으로 이루어진 벡터공간의 어떤 벡터를 yy라고 하자. 그러면 xVx^{\Vert V}yy의 차이 벡터 xvyx^{\Vert v} - yv1,v2,,vMv_1, v_2, \cdots, v_M으로 이루어진 벡터공간에 존재하므로 직교벡터 xVx^{\perp V}와 직교한다.

xy2=xxV+(xVy)2=xV+(xVy)2=xV2+(xVy)2xV2(3.2.50)\begin{aligned} \Vert x - y \Vert^2 &= \Vert x - x^{\Vert V} + (x^{\Vert V} - y) \Vert^2 \\ &= \Vert x^{\perp V} + (x^{\Vert V} - y) \Vert^2 \\ &= \Vert x^{\perp V} \Vert^2 + \Vert (x^{\Vert V} - y) \Vert^2 \\ &\geq \Vert x^{\perp V} \Vert^2 \end{aligned} \tag{3.2.50}

표준기저벡터

기저벡터 중에서도 원소 중 하나만 값이 1이고 다른 값은 0으로 이루어진 다음과 같은 기저벡터를 표준기저벡터(standard basis vector)라고 한다.

e1=[100],    e2=[010],    ,    eN=[001](3.2.51)e_1 = \begin{bmatrix} 1 \\ 0 \\ \vdots \\ 0 \end{bmatrix}, \;\; e_2 = \begin{bmatrix} 0 \\ 1 \\ \vdots \\ 0 \end{bmatrix}, \;\; \cdots, \;\; e_N = \begin{bmatrix} 0 \\ 0 \\ \vdots \\ 1 \end{bmatrix} \tag{3.2.51}

표준기저벡터를 열로 가지는 행렬은 항등행렬이 된다.

[e1e2eN]=IN(3.2.52)\begin{bmatrix} e_1 & e_2 & \cdots & e_N \end{bmatrix} = I_N \tag{3.2.52}

좌표

어떤 벡터의 좌표(coordinate) 는 기저벡터를 선형조합하여 그 벡터를 나타내기 위한 계수벡터를 말한다.

예를 들어 다음처럼 기저벡터 {e1,e2}\{e_1,e_2\}를 선형조합하여 벡터 xx를 나타낼 수 있다고 가정하자.

x=xe1e1+xe2e2(3.2.53)x = x_{e_1} e_1 + x_{e_2} e_2 \tag{3.2.53}

이 때 벡터 xex_e

xe=[xe1xe2](3.2.54)x_e = \begin{bmatrix} x_{e_1} \\ x_{e_2} \end{bmatrix} \tag{3.2.54}

를 벡터 xx의 기저벡터 {e1,e2}\{e_1,e_2\}에 대한 좌표벡터 혹은 간단히 좌표(coordinate) 라고 한다. 벡터와 기저벡터 그리고 좌표의 관계는 다음과 같다.

x=[e1e2][xe1xe2]=[e1e2]  xe(3.2.55)x = [ e_1 e_2 ] \begin{bmatrix} x_{e_1} \\ x_{e_2} \end{bmatrix} = [ e_1 e_2 ] \; x_e \tag{3.2.55}

표준기저벡터를 모아놓은 행렬이 항등행렬이기 때문에 표준기저벡터에 대한 벡터의 좌표 xex_e는 원래 벡터 xx와 같다. 하지만 같은 벡터라도 다른 기저벡터를 사용하면 좌표가 달라진다. 따라서 하나의 벡터도 기저벡터에 따라 여러 좌표를 가질 수 있다.

import matplotlib.pylab as plt

gray = {"facecolor": "gray"}
black = {"facecolor": "black"}
red = {"facecolor": "red"}
green = {"facecolor": "green"}
blue = {"facecolor": "blue"}
lightgreen = {"facecolor": "lightgreen"}
e1 = np.array([1, 0])
e2 = np.array([0, 1])
x = np.array([2, 2])

plt.annotate('', xy=2 * e1, xytext=(0, 0), arrowprops=gray)
plt.annotate('', xy=2 * e2, xytext=(0, 0), arrowprops=gray)
plt.annotate('', xy=e1, xytext=(0, 0), arrowprops=green)
plt.annotate('', xy=e2, xytext=(0, 0), arrowprops=green)
plt.annotate('', xy=x, xytext=(0, 0), arrowprops=gray)

plt.plot(0, 0, 'ro', ms=10)
plt.plot(x[0], x[1], 'ro', ms=10)

plt.text(1.05, 1.35, "$x$", fontdict={"size": 18})
plt.text(-0.3, 0.5, "$e_2$", fontdict={"size": 18})
plt.text(0.5, -0.2, "$e_1$", fontdict={"size": 18})

plt.xticks(np.arange(-2, 4))
plt.yticks(np.arange(-1, 4))
plt.xlim(-1.5, 3.5)
plt.ylim(-0.5, 3)
plt.show()

예제

다음 기저벡터 {g1,g2}\{g_1, g_2\}를 사용하면,

g1=[10],  g2=[11](3.2.56)g_1 = \begin{bmatrix} 1 \\ 0 \end{bmatrix}, \; g_2 = \begin{bmatrix} -1 \\ 1 \end{bmatrix} \tag{3.2.56}

위에 예로 든 벡터 xx는 기저벡터 {g1,g2}\{g_1, g_2\}를 다음처럼 선형조합하여 표현할 수 있다.

x=4g1+2g2=[g1g2][42]=[g1g2]xg(3.2.57)x = 4 g_1 + 2 g_2 = \begin{bmatrix} g_1 & g_2 \end{bmatrix} \begin{bmatrix} 4 \\ 2 \end{bmatrix} = \begin{bmatrix} g_1 & g_2 \end{bmatrix} x_g \tag{3.2.57}

따라서 기저벡터 {g1,g2}\{g_1, g_2\}에 대한 xx의 좌표는 다음과 같다.

xg=[42](3.2.58)x_g = \begin{bmatrix} 4 \\ 2 \end{bmatrix} \tag{3.2.58}
g1 = np.array([1, 0])
g2 = np.array([-1, 1])
x = np.array([2, 2])

plt.annotate('', xy=4 * g1, xytext=(0, 0), arrowprops=lightgreen)
plt.annotate('', xy=2 * g2, xytext=(0, 0), arrowprops=lightgreen)
plt.annotate('', xy=g1, xytext=(0, 0), arrowprops=green)
plt.annotate('', xy=g2, xytext=(0, 0), arrowprops=green)
plt.annotate('', xy=x, xytext=(0, 0), arrowprops=gray)

plt.plot(0, 0, 'ro', ms=10)
plt.plot(x[0], x[1], 'ro', ms=10)

plt.text(1.05, 1.35, "$x$", fontdict={"size": 18})
plt.text(-0.3, 0.5, "$g_2$", fontdict={"size": 18})
plt.text(0.5, -0.5, "$g_1$", fontdict={"size": 18})

plt.xticks(np.arange(-10, 10))
plt.yticks(np.arange(-10, 10))
plt.xlim(-3, 7)
plt.ylim(-2, 5)
plt.show()

변환행렬

원래의 기저벡터가 아닌 새로운 기저벡터가 있다고 하자. 이 새로운 기저벡터들의 기존 기저벡터에 대한 좌표를 열벡터로 보고 이를 행렬로 묶은 행렬 AA를 생각하자.

예를 들어, 기존의 기저벡터가 {e1,e2}\{e_1, e_2\}이고 새로운 기저벡터 {g1,g2}\{g_1, g_2\}간에 다음과 같은 관계가 성립한다면,

g1=12e1+12e2g2=12e1+12e2(3.2.59)\begin{aligned} g_1 &= \dfrac{1}{\sqrt{2}} e_1 + \dfrac{1}{\sqrt{2}} e_2 \\ g_2 &= -\dfrac{1}{\sqrt{2}} e_1 + \dfrac{1}{\sqrt{2}} e_2 \end{aligned} \tag{3.2.59}

e1e_1, e2e_2에 대한 g1g_1, g2g_2의 좌표벡터는 다음처럼 열벡터로 나타낼 수 있다.

g1e=[1212],    g2e=[1212](3.2.60)g_{1e} = \begin{bmatrix} \dfrac{1}{\sqrt{2}} \\ \dfrac{1}{\sqrt{2}} \end{bmatrix}, \;\; g_{2e} = \begin{bmatrix} -\dfrac{1}{\sqrt{2}} \\ \dfrac{1}{\sqrt{2}} \end{bmatrix} \tag{3.2.60}

두 좌표벡터들을 합쳐서 행렬로 표시하면 다음과 같다.

[g1g2]=[e1e2][g1eg2e]=[e1e2]A(3.2.61)\begin{bmatrix} g_1 & g_2 \end{bmatrix} = \begin{bmatrix} e_1 & e_2 \end{bmatrix} \begin{bmatrix} g_{1e} & g_{2e} \end{bmatrix} = \begin{bmatrix} e_1 & e_2 \end{bmatrix} A \tag{3.2.61}
A=[12121212](3.2.62)A = \begin{bmatrix} \dfrac{1}{\sqrt{2}} & -\dfrac{1}{\sqrt{2}} \\ \dfrac{1}{\sqrt{2}} & \dfrac{1}{\sqrt{2}} \end{bmatrix} \tag{3.2.62}
e1 = np.array([1, 0])
e2 = np.array([0, 1])
a = np.array([2, 2])
g1 = np.array([1, 1]) / np.sqrt(2)
g2 = np.array([-1, 1]) / np.sqrt(2)

plt.annotate('', xy=e1, xytext=(0, 0), arrowprops=green)
plt.annotate('', xy=e2, xytext=(0, 0), arrowprops=green)
plt.annotate('', xy=g1, xytext=(0, 0), arrowprops=red)
plt.annotate('', xy=g2, xytext=(0, 0), arrowprops=red)

plt.text(-0.18, 0.5, "$e_2$", fontdict={"size": 18})
plt.text(0.5, -0.2, "$e_1$", fontdict={"size": 18})
plt.text(0.3, 0.5, "$g_1$", fontdict={"size": 18})
plt.text(-0.45, 0.2, "$g_2$", fontdict={"size": 18})

plt.xticks(np.arange(-2, 4))
plt.yticks(np.arange(-1, 4))
plt.xlim(-1.2, 1.7)
plt.ylim(-0.5, 1.3)
plt.show()

좌표변환

새로운 기저벡터에 대해 좌표를 계산하는 것을 좌표변환(coordinate transform) 이라고 한다.

2차원의 경우를 예로 들어보자. 벡터 xx의 기저벡터 {e1,e2}\{e_1, e_2\}에 대한 좌표 xex_e를 새로운 기저벡터 {g1,g2}\{g_1, g_2\}에 대한 좌표 xgx_g로 변환하고자 한다.

새로운 기저벡터에 대한 좌푯값이 가리키는 실제 위치는 원래의 벡터가 가리키는 실제 위치와 같아야 되므로

x=xe1e1+xe2e2=xg1g1+xg2g2(3.2.63)x = x_{e1}e_1 + x_{e2}e_2 = x_{g1} g_1 + x_{g2} g_2 \tag{3.2.63}
x=[e1e2]xe=[g1g2]xg(3.2.64)x = \begin{bmatrix} e_1 & e_2 \end{bmatrix} x_e = \begin{bmatrix} g_1 & g_2 \end{bmatrix} x_g \tag{3.2.64}

이 식에

[g1g2]=[e1e2]A(3.2.65)\begin{bmatrix} g_1 & g_2 \end{bmatrix} = \begin{bmatrix} e_1 & e_2 \end{bmatrix} A \tag{3.2.65}

를 대입하면

x=[e1e2]xe=[e1e2]Axg(3.2.66)x = \begin{bmatrix} e_1 & e_2 \end{bmatrix} x_e = \begin{bmatrix} e_1 & e_2 \end{bmatrix} A x_g \tag{3.2.66}

이 된다. 이 식으로부터 다음 식이 성립한다.

xe=Axg(3.2.67)x_e = A x_g \tag{3.2.67}
xg=A1xe=Txe(3.2.68)x_g = A^{-1}x_e = Tx_e \tag{3.2.68}

이 때 AA의 역행렬 T=A1T=A^{-1}변환행렬(transform matrix) 이라고 한다.

예를 들어 벡터 xx의 표준기저벡터에 대한 좌표가 다음과 같다고 하자.

x=2e1+2e2=[22]=xe(3.2.69)x = 2 e_1 + 2 e_2= \begin{bmatrix}2 \\ 2\end{bmatrix} = x_e \tag{3.2.69}

표준기저벡터에 대한 새로운 기저벡터의 좌표가 다음과 같다면

g1e=[1212],    g2e=[1212](3.2.70)g_{1e} = \begin{bmatrix} \dfrac{1}{\sqrt{2}} \\ \dfrac{1}{\sqrt{2}} \end{bmatrix} ,\;\; g_{2e} = \begin{bmatrix} -\dfrac{1}{\sqrt{2}} \\ \dfrac{1}{\sqrt{2}} \end{bmatrix} \tag{3.2.70}

새로운 기저벡터에 대한 벡터 aa의 좌표는 위의 공식을 이용하여 다음처럼 계산할 수 있다.

xg=A1xe=[12121212]1[22]=[12121212][22]=[220](3.2.71)x_g = A^{-1}x_e = \begin{bmatrix} \dfrac{1}{\sqrt{2}} & -\dfrac{1}{\sqrt{2}} \\ \dfrac{1}{\sqrt{2}} & \dfrac{1}{\sqrt{2}} \end{bmatrix}^{-1} \begin{bmatrix}2 \\ 2\end{bmatrix} = \begin{bmatrix} \dfrac{1}{\sqrt{2}} & \dfrac{1}{\sqrt{2}} \\ -\dfrac{1}{\sqrt{2}} & \dfrac{1}{\sqrt{2}} \end{bmatrix} \begin{bmatrix}2 \\ 2\end{bmatrix} = \begin{bmatrix}2\sqrt{2}\\0\end{bmatrix} \tag{3.2.71}

다음 그림은 이 변환을 나타낸 것이다.

e1 = np.array([1, 0])
e2 = np.array([0, 1])
x = np.array([2, 2])
g1 = np.array([1, 1]) / np.sqrt(2)
g2 = np.array([-1, 1]) / np.sqrt(2)

plt.annotate('', xy=e1, xytext=(0, 0), arrowprops=green)
plt.annotate('', xy=e2, xytext=(0, 0), arrowprops=green)
plt.annotate('', xy=x, xytext=(0, 0), arrowprops=gray)
plt.annotate('', xy=g1, xytext=(0, 0), arrowprops=red)
plt.annotate('', xy=g2, xytext=(0, 0), arrowprops=red)

plt.plot(0, 0, 'ro', ms=10)
plt.plot(x[0], x[1], 'ro', ms=10)

plt.text(1.05, 1.35, "$x$", fontdict={"size": 18})
plt.text(-0.3, 0.5, "$e_2$", fontdict={"size": 18})
plt.text(0.5, -0.2, "$e_1$", fontdict={"size": 18})
plt.text(0.2, 0.5, "$g_1$", fontdict={"size": 18})
plt.text(-0.6, 0.2, "$g_2$", fontdict={"size": 18})

plt.xticks(np.arange(-2, 4))
plt.yticks(np.arange(-1, 4))
plt.xlim(-1.5, 3.5)
plt.ylim(-0.5, 3)
plt.show()

NumPy를 사용하면 다음처럼 계산할 수 있다.

A = np.vstack([g1, g2]).T
A
array([[ 0.70710678, -0.70710678],
       [ 0.70710678,  0.70710678]])
Ainv = np.linalg.inv(A)
Ainv
array([[ 0.70710678,  0.70710678],
       [-0.70710678,  0.70710678]])
Ainv.dot(x)
array([2.82842712, 0.        ])

즉, 새로운 좌표벡터는 원래의 좌표벡터에 변환행렬을 곱하여 구할 수 있다.

연습 문제 3.2.8

만약 새로운 기저벡터의 좌표가 다음과 같다면 원래의 좌표 (1, 0), (1, 2), (-1, 2)는 각각 어떤 좌푯값이 될지 계산하라.

g1=[10.75],    g2=[10.75](3.2.72)g_1 = \begin{bmatrix} 1 \\ 0.75 \end{bmatrix} ,\;\; g_2 = \begin{bmatrix} -1 \\ 0.75 \end{bmatrix} \tag{3.2.72}
import numpy as np
a = np.array([1,0,1,2,-1,2]).reshape(3,2).T
b = np.array([1, -1, 0.75, 0.75]).reshape(2,2)
print(np.linalg.inv(b) @ a)
[[ 0.5 1.83333333 0.83333333] 
[-0.5 0.83333333 1.83333333]]

이미지 변환

새로운 기저벡터에 대한 좌표변환을 응용하면 이미지를 자유롭게 변환할 수도 있다. 파이썬에서는 scipy.ndimage 패키지의 affine_transform() 명령을 사용한다. 이 명령은 이미지를 이루는 픽셀을 새로운 좌표로 이동시킨다. 인수로는 이미지 데이터와 변환행렬의 역행렬(위에서 AA로 표시한 행렬) 을 받는다. 단 파이썬 이미지에서는 다음과 같은 표준기저벡터를 사용하고 (x1x_1이 아래를 향하는 세로축, x2x_2가 오른쪽을 향하는 가로축) 원점이 왼쪽 상단의 점이라는 점에 유의한다.

e1=[01],    e2=[10](3.2.73)e_1 = \begin{bmatrix} 0 \\ -1 \end{bmatrix} ,\;\; e_2 = \begin{bmatrix} 1 \\ 0 \end{bmatrix} \tag{3.2.73}

다음은 위에서 예로 든 기저벡터 {g1,g2}\{g_1, g_2\}로 이미지 변환한 예다(그림에서 기저벡터의 크기는 설명을 위해 과장하여 크게 표시하였다).

import scipy as sp
import scipy.misc
import scipy.ndimage

f = sp.misc.face(gray=True)

e1 = np.array([0, 1]) # matplotlib의 이미지 좌표규약으로 부호변경 
e2 = np.array([1, 0])
E = np.vstack([e1, e2]).T
g1 = np.array([1, 1]) / np.sqrt(2)
g2 = np.array([-1, 1]) / np.sqrt(2)
A = np.vstack([g1, g2]).T
gc1 = E @ g1
gc2 = E @ g2

plt.subplot(121)
plt.imshow(f, cmap=mpl.cm.bone, alpha=0.9)
plt.annotate('', xy=500*e1, xytext=(0,0), arrowprops=green)
plt.annotate('$e_1$', xy=500*e1, xytext=500*e1 + [-100,0])
plt.annotate('', xy=500*e2, xytext=(0,0), arrowprops=green)
plt.annotate('$e_2$', xy=500*e2, xytext=500*e2 + [0, -50])
plt.annotate('', xy=500*gc1, xytext=(0, 0), arrowprops=red)
plt.annotate('$g_1$', xy=500*gc1, xytext=500*gc1 + [50, -50])
plt.annotate('', xy=500*gc2, xytext=(0, 0), arrowprops=red)
plt.annotate('$g_2$', xy=500*gc2, xytext=500*gc2 + [50, 0])
plt.axis("off")
plt.xlim(-200, 1000)
plt.ylim(800, -500)
plt.title("좌표변환전")

f1 = sp.ndimage.affine_transform(f, A)

plt.subplot(122)
plt.imshow(f1, cmap=mpl.cm.bone, alpha=0.8)
plt.annotate('', xy=500*e1, xytext=(0,0), arrowprops=red)
plt.annotate('$g_1$', xy=500*e1, xytext=500*e1 + [-100,0])
plt.annotate('', xy=500*e2, xytext=(0,0), arrowprops=red)
plt.annotate('$g_2$', xy=500*e2, xytext=500*e2 + [0, -50])
plt.axis("off")
plt.xlim(-200, 1000)
plt.ylim(800, -500)
plt.title("좌표변환후")
plt.show()

연습 문제 3.2.9

다음 기저벡터를 이용하여 앞의 이미지를 변환하라. 변환한 이미지를 만들기 전에 어떤 이미지가 나올지 생각해보자.

g1=[10.75],    g2=[10.75](3.2.74)g_1 = \begin{bmatrix} 1 \\ 0.75 \end{bmatrix} ,\;\; g_2 = \begin{bmatrix} -1 \\ 0.75 \end{bmatrix} \tag{3.2.74}

회전은 비슷하게 되는데 좌우로 살짝 쪼그라들지 않을까 싶다.

profile
AI Learner (Lover)

0개의 댓글