다운로드
작성자: admin 작성일시: 2018-09-02 19:20:48 조회수: 2682 다운로드: 175
카테고리: 기타 태그목록:

좌표와 변환

선형종속과 선형독립

벡터 $x_1, x_2, \ldots, x_N$들의 선형조합이 영벡터가 되도록 하는 계수 $c_1, c_2, \ldots, c_N$이 존재하면 선형종속(linearly dependent)이라고 한다. 단 $c_1 = c_2 = \cdots = c_N = 0$ 으로 계수가 모두 0인 경우는 제외한다.

$$ c_1 x_1 + c_2 x_2 + \cdots + c_N x_N = 0 $$

반대로 벡터들의 선형조합이 0이 되는, 모두 0은 아닌 계수가 존재하지 않으면 그 벡터들은 선형독립(linearly independent)이라고 한다. 즉 "벡터 $x_1, x_2, \ldots, x_N$들의 선형조합이 영벡터이면 반드시 모든 계수가 모두 0일 수 밖에 없는 경우"를 선형독립이라고 한다.

$$ c_1 x_1 + \cdots + c_N x_N = 0 \;\;\;\; \leftrightarrow \;\;\;\; c_1 = \cdots = c_N = 0 $$

역으로 모든 계수가 0이면 선형독립이 아니더라도 선형조합은 영벡터가 된다.

예를 들어 다음 벡터 $x_1, x_2$는 선형독립이다.

$$ x_1 = \begin{bmatrix} 1 \\ 2 \end{bmatrix}, \;\; x_2 = \begin{bmatrix} 3 \\ 3 \end{bmatrix} $$

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

하지만 다음 벡터 $x_1, x_2, x_3$는 선형종속이다.

$$ x_1 = \begin{bmatrix} 1 \\ 2 \end{bmatrix}, \;\; x_2 = \begin{bmatrix} 3 \\ 3 \end{bmatrix}, \;\; x_3 = \begin{bmatrix} 5 \\ 7 \end{bmatrix} $$

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

$$ 2x_1 + x_2 - x_3 = 0 $$
In [1]:
x1 = np.array([1, 2])
x2 = np.array([3, 3])
x3 = np.array([10, 14])
2 * x1 + x2 - 0.5 * x3
Out:
array([0., 0.])

연습 문제 5.3.12

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

1. $$ x_1 = \begin{bmatrix}1 \\ 0\end{bmatrix} ,\;\; x_2 = \begin{bmatrix}0 \\ 1\end{bmatrix} $$

2. $$ x_1 = \begin{bmatrix}1 \\ 0\end{bmatrix} ,\;\; x_2 = \begin{bmatrix}-1 \\ 1\end{bmatrix} $$

3. $$ x_1 = \begin{bmatrix}1 \\ 2\end{bmatrix} ,\;\; x_2 = \begin{bmatrix}2 \\ 4\end{bmatrix} $$

연습 문제 5.3.13

서로 직교하는 0벡터가 아닌 $N$개의 벡터 $v_1, v_2, \cdots, v_N$은 선형독립임을 증명하라.

$$ x_i^T x_j = 0 \;\;\; (i \neq j) $$

연습 문제 5.3.14

  1. 선형독립인 2개의 2차원 벡터의 예를 들어라.

  2. 선형독립인 2개의 3차원 벡터의 예를 들어라.

  3. 선형독립인 3개의 2차원 벡터의 예를 들어라. 이러한 벡터들이 존재하는가?

  4. 선형독립인 3개의 3차원 벡터의 예를 들어라. 이러한 벡터들이 존재하는가?

  5. 선형독립인 4개의 3차원 벡터의 예를 들어라. 이러한 벡터들이 존재하는가?

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

벡터의 선형조합은 다음과 같이 두 벡터의 내적으로 표기할 수도 있다. 이 식에서 $c_i$는 가중치 계수이고 $c$는 가중치 벡터이며, $X$는 열벡터 $x_i$를 합쳐서(concatenate) 만든 행렬이다.

$$ 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 $$

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

$$ Xc=0 $$

만약 $X$ 행렬의 역행렬이 존재하면 으로 0벡터가 유일한 해가 되어 모든 계수가 0일 수 밖에 없기 때문에 선형독립이다.

$$ c = X^{-1}0 = 0 $$

행렬 $X$의 행의 갯수보다 열의 갯수가 많으면 미지수의 수가 방정식의 수보다 커서 해가 무한히 많기 때문에 영벡터가 아닌 해 $c$도 존재한다. 따라서 선형종속이다. 다른말로 벡터가 $N$차원이면(행의 갯수가 $N$이면), 벡터의 갯수가 $N$보다 많을 때(열의 갯수가 $N+1$이상이면)는 반드시 선형종속이다.

만대로 행의 갯수가 열의 갯수와 같거나 작으면 대부분 선형독립이다. 우리가 분석할 대부분의 데이터는 특징의 종류보다 데이터의 수가 많기 때문에 여기에 해당한다. 하지만 경우에 따라 같은 열이 중복되거나 어떤 열이 다른 열의 값으로 계산된다면 선형종속일 수도 있다. 만약 특징행렬 $X$가 선형종속이거나 선형종속에 가까우 면 데이터 분석이 어려워질 수 있으므로 이러한 경우는 피하거나 또다른 데이터 처리가 필요하다. 이러한 경우를 다중공선성(multicollinearity)이라고 부른다. 이 경우의 문제점과 처리 방법에 대해서는 나중에 선형회귀에서 공부하게 된다.

랭크

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

예를 들어 다음 행렬 $X_1$의 두 열벡터는 선형독립이기 때문에 열랭크는 2이다.

$$ X_1 = \begin{bmatrix} 1 & 3 \\ 2 & 3 \end{bmatrix} $$

다음 행렬 $X_2$의 세 열벡터는 선형종속이므로 열랭크는 3보다 작아야 한다. 그런데 위에서 설명한 것처럼 이 열벡터 중 앞의 두개는 서로 독립이므로 $X_2$의 랭크는 2이다.

$$ X_1 = \begin{bmatrix} 1 & 3 & 5 \\ 2 & 3 & 7 \end{bmatrix} $$

행랭크와 열랭크에 대해서는 다음 성질이 성립한다. (증명은 생략한다.)

행랭크와 열랭크는 항상 같다.

따라서 행 랭크나 열 랭크를 그냥 랭크(rank)라고 하기도 한다. 행랭크는 행의 갯수보다 커질 수 없고 열랭크는 열의 갯수보다 커질 수 없기 때문에 행렬의 랭크는 열의 갯수와 행의 갯수 중 작은 값보다 커질 수 없다.

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

연습 문제 5.3.15

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

1. $$ A = \begin{bmatrix} 1 & 5 & 6 \\ 2 & 6 & 8 \\ 3 & 11 & 14\\ 1 & 4 & 5 \end{bmatrix} $$

2. $$ B = \begin{bmatrix} 1 & 5 & 6 \\ 2 & 6 & 8 \\ 3 & 11 & 14\\ 1 & 4 & 8 \end{bmatrix} $$

numpy의 linalg 서브 패키지의 matrix_rank 명령으로 랭크를 계산할 수 있다.

In [2]:
A = np.array([[1, 5, 6], [2, 6, 8], [3, 11, 14], [1, 4, 5]])
np.linalg.matrix_rank(A)
Out:
2
In [3]:
B = np.array([[1, 5, 6], [2, 6, 8], [3, 11, 14], [1, 4, 8]])
np.linalg.matrix_rank(B)
Out:
3

랭크와 역행렬

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

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

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

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

정방행렬이 풀랭크라는 것은 그 행렬의 열벡터 $x_1, \cdots, x_N$을 선형조합하는 가중치 $c_1, \cdots, c_N$가 영 벡터가 아니고서는 선형조합이 0이 될 수 없다는 뜻이다. 따라서 다음과 같이 쓸 수 있다.

$$ Xc = 0 \; \leftrightarrow \; c=0 $$

즉, $Xc = 0$ 이면 $c=0$ 이고 역으로 $c=0$ 이면 $Xc=0$ 이다.

이 사실은 $X$의 역행렬 $X^{-1}$이 존재한다는 것과 같다. 왜냐 하면 역행렬 $X^{-1}$이 존재하면 다음처럼 $c=0$이 되기 때문이다.

$$ \text{좌변} = X^{-1}Xc = c $$$$ \text{우변} = X^{-1}0 = 0 $$

따라서, $$ c = 0 $$

따라서 화살표의 왼쪽이 성립하면 오른쪽도 성립한다는 것을 증명할 수 있다. $c=0$이면 항상 $Xc=0$이므로 반대의 경우는 쉽게 증명할 수 있다.

연습 문제 5.3.16

예측모형을 만들기 위해 다음과 같은 특징행렬 데이터를 수집하였다. 각 특징행렬의 역행렬이 존재하는가?

  1. 특징행렬에 중복된 데이터가 있다. $$ \begin{bmatrix} 1 & 5 & 6 \\ 2 & 6 & 8 \\ 2 & 6 & 8 \end{bmatrix} $$

  2. 어떤 열은 다른 열들의 선형조합이다. 예를 들어 어떤 특징은 다른 특징들의 가중합이다. $$ \begin{bmatrix} 3 & 1 & 5 & 7 \\ 3 & 2 & 6 & 10 \\ 1& 3 & 11 & 17\\ 9 & 1 & 4 & 6 \end{bmatrix} $$

위와 같은 특징 데이터 집합은 데이터분석에 나쁜 영향을 미친다. 자세한 내용은 고유분해에서 다루게 된다.

로우-랭크 행렬

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

$$ xx^T \in \mathbf{R}^{N \times N} $$

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

$$ \begin{eqnarray} 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{eqnarray} $$

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

$$ \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 $$

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

만약 $M$개의 $N$차원 벡터 $x_1, x_2, \cdots, x_M$을 이용하면 랭크-M 행렬(rank-M matrix)이 된다.

$$ \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 $$

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

벡터공간과 기저벡터

여러개의 벡터를 선형조합을 하면 다른 벡터를 만들 수 있다. 벡터 N개가 서로 선형독립일 경우, 이 벡터들을 선형조합하여 만들어지는 모든 벡터의 집합을 벡터공간(vector space)라고 이 벡터공간의 차원은 $N$이라고 한다. 그리고 그 벡터들을 벡터공간의 기저벡터(basis vector)라고 한다. 벡터공간의 차원(dimension)이 벡터의 차원(길이)가 아니라 기저벡터의 갯수로 정의된다는 점에 유의해야 한다.

만약 $N$차원 벡터 $N$개 $x_1, x_2, \cdots, x_N$이 선형독립이어서 기저벡터를 이룬다면 이 기저벡터를 선형조합하여 모든 $N$차원 벡터를 만들 수 있다.

임의의 벡터 $x$가 있다고 하자. 기저벡터 $x_1, x_2, \cdots, x_N$와 이 벡터 $x$를 열벡터로 사용하여 만든 행렬

$$ X = \left[ x_1, x_2, \cdots, x_N, x \right] $$

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

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

$$ x_1 = \begin{bmatrix} 1 \\ 2 \end{bmatrix}, \;\; x_2 = \begin{bmatrix} 2 \\ 1 \end{bmatrix} $$

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

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

$$ x_1 = \begin{bmatrix} 1 \\ 2 \end{bmatrix}, \;\; x_2 = \begin{bmatrix} 2 \\ 1 \end{bmatrix}, \;\; x_3 = \begin{bmatrix} 5 \\ 7 \end{bmatrix} $$

다음 벡터의 집합은 선형독립이므로 벡터공간의 기저벡터이다. 하지만 이 벡터공간은 3차원 벡터공간이 아니라 2차원 벡터공간이다.

$$ x_1 = \begin{bmatrix} 1 \\ 2 \\ 0 \end{bmatrix}, \;\; x_2 = \begin{bmatrix} 2 \\ 1 \\ 0 \end{bmatrix} $$

예를 들어 이 벡터 $x_1, x_2$를 어떻게 선형조합해도 다음 벡터는 만들 수 없다.

$$ c_1x_1 + c_2x_2 = \begin{bmatrix} 0 \\ 0 \\ 1 \end{bmatrix} $$

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

연습 문제 5.3.17

  1. 다음 기저벡터 $x_1, x_2$를 선형조합하여 벡터 $y_1, y_2$를 만들어라. $$ x_1 = \begin{bmatrix} 1 \\ 2 \end{bmatrix}, \;\; x_2 = \begin{bmatrix} 2 \\ 1 \end{bmatrix} $$
    $$ y_1 = \begin{bmatrix} 3 \\ 3 \end{bmatrix}, \;\; y_2 = \begin{bmatrix} -1 \\ -1 \end{bmatrix} $$

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

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

연습 문제 5.3.18

$N$개의 $N$차원 벡터 $x_1, x_2, \cdots, x_N$이 기저벡터이다. 이 벡터 $x_1, x_2, \cdots, x_N$ 각각에 대해 모두 수직인 벡터 $x$가 존재하지 않는 다는 것을 증명하라.

벡터공간 투영

어떤 $N$차원 벡터 $x$와 $N$차원 벡터 $M(

이 때 기저벡터$v_1, v_2, \cdots, v_M$가 선형조합하여 만든 벡터 $x^{\Vert v}$와 벡터 $x$의 차 $x - x^{\Vert v}$가 모든 기저벡터에 직교하면 그 벡터 $x^{\Vert v}$를 $v_1, v_2, \cdots, v_M$ 벡터공간에 대한 투영(project)벡터라 하고 차이 벡터 $x - x^{\Vert v} = x^{\perp v}$를 벡터공간에 대한 직교(rejection)벡터라 한다.

$$ (x - x^{\Vert v}) \perp \{ v_1, v_2, \cdots, v_M \} $$

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

만약 기저벡터 $v_1, v_2, \cdots, v_M$가 정규직교(orthonormal)이면 투영벡터 $x^{\Vert v}$의 $i$번째 원소는 $i$번째 기저벡터에 대한 내적이다.

$$ x^{\Vert v} = \begin{bmatrix} x^Tv_1 \\ x^Tv_2 \\ \vdots \\ x^Tv_M \\ \end{bmatrix} = \begin{bmatrix} v_1^T \\ v_2^T \\ \vdots \\ v_M^T \\ \end{bmatrix} x $$

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

$$ \Vert x^{\Vert v} \Vert^2 = \sum_{i=1}^M (x^Tv_i)^2 $$

벡터 $x$에서 이 벡터 $x^{\Vert v}$를 뺀 벡터 $x - x^{\Vert v}$, 즉 직교벡터 $x^{\perp v}$가 기저벡터 $M( $$ \begin{eqnarray} v_i^T(x - x^{\Vert v}) &=& v_i^Tx - v_i^T \begin{bmatrix} v_1^T \\ v_2^T \\ \vdots \\ v_M^T \\ \end{bmatrix} x &=& v_i^Tx - v_i^Tx = 0 \end{eqnarray} $$

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

이 사실로부터 벡터 $x$의 프로젝션 $x^{\Vert v}$은 기저벡터 $v_1, v_2, \cdots, v_M$으로 이루어진 벡터공간의 모든 벡터 중에서 가장 벡터 $x$와 가까운 벡터라는 것도 알 수 있다.

기저벡터 $v_1, v_2, \cdots, v_M$으로 이루어진 벡터공간의 어떤 벡터를 $y$라고 하자. 그러면 $x^{\Vert v}$와 $y$의 차이 벡터 $x^{\Vert v} - y$도 $v_1, v_2, \cdots, v_M$으로 이루어진 벡터공간에 존재하므로 직교벡터 $x^{\perp v}$와 직교한다.

$$ \begin{eqnarray} \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{eqnarray} $$

표준기저벡터

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

$$ 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} $$

좌표

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

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

$$ x = x_{e1} e_1 + x_{e2} e_2 $$

이 때 벡터 $x_e$

$$ x_e = \begin{bmatrix} x_{e1} \\ x_{e1} \end{bmatrix} $$

를 벡터 $x$의 기저벡터 $\{e_1,e_2\}$에 대한 좌표(coordinate)라고 한다. 벡터와 기저벡터 그리고 좌표의 관계는 다음과 같다.

$$ x = [ e_1 e_2 ] \begin{bmatrix} x_{e1} \\ x_{e1} \end{bmatrix} = [ e_1 e_2 ] \; x_e $$

표준기저벡터에 대한 벡터의 좌표는 원래 벡터와 같다. 예를 들어 다음 벡터 $x$의 좌표는 표준기저벡터로 나타내면 원래의 벡터와 같다.

$$ x_e = \begin{bmatrix} 2 \\ 2 \end{bmatrix} $$
In [4]:
e1 = np.array([1, 0])
e2 = np.array([0, 1])
x = np.array([2, 2])

plt.annotate('', xy=2 * e1, xytext=(0, 0),
             arrowprops=dict(facecolor='lightgreen'))
plt.annotate('', xy=2 * e2, xytext=(0, 0),
             arrowprops=dict(facecolor='lightgreen'))
plt.annotate('', xy=e1, xytext=(0, 0), arrowprops=dict(facecolor='green'))
plt.annotate('', xy=e2, xytext=(0, 0), arrowprops=dict(facecolor='green'))
plt.annotate('', xy=x, xytext=(0, 0), arrowprops=dict(facecolor='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()

하지만 같은 벡터라도 다른 기저벡터를 사용하면 좌표가 달라진다. 따라서 하나의 벡터도 기저벡터에 따라 여러가지 좌표를 가질 수 있다.

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

$$ g_1 = \begin{bmatrix} 1 \\ 0 \end{bmatrix}, \; g_2 = \begin{bmatrix} -1 \\ 1 \end{bmatrix} $$

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

$$ x = 4 g_1 + 2 g_2 $$

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

$$ x_g = \begin{bmatrix} 4 \\ 2 \end{bmatrix} $$
In [5]:
g1 = np.array([1, 0])
g2 = np.array([-1, 1])
x = np.array([2, 2])

plt.annotate('', xy=4 * g1, xytext=(0, 0),
             arrowprops=dict(facecolor='lightgreen'))
plt.annotate('', xy=2 * g2, xytext=(0, 0),
             arrowprops=dict(facecolor='lightgreen'))
plt.annotate('', xy=g1, xytext=(0, 0), arrowprops=dict(facecolor='green'))
plt.annotate('', xy=g2, xytext=(0, 0), arrowprops=dict(facecolor='green'))
plt.annotate('', xy=x, xytext=(0, 0), arrowprops=dict(facecolor='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()

변환행렬

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

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

$$ \begin{eqnarray} 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{eqnarray} $$

$e_1$, $e_2$에 대한 $g_1$, $g_2$의 좌표 벡터는 다음처럼 열벡터로 나타낼 수 있다.

$$ 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} $$

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

$$ \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 $$$$ A = \begin{bmatrix} \dfrac{1}{\sqrt{2}} & -\dfrac{1}{\sqrt{2}} \\ \dfrac{1}{\sqrt{2}} & \dfrac{1}{\sqrt{2}} \end{bmatrix} $$
In [6]:
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=dict(facecolor='green'))
plt.annotate('', xy=e2, xytext=(0, 0), arrowprops=dict(facecolor='green'))
plt.annotate('', xy=g1, xytext=(0, 0), arrowprops=dict(facecolor='red'))
plt.annotate('', xy=g2, xytext=(0, 0), arrowprops=dict(facecolor='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차원의 경우를 예로 들어보자. 벡터 $x$의 기저벡터 $\{e_1, e_2\}$에 대한 좌표 $x_e$를 새로운 기저벡터 $\{g_1, g_2\}$에 대한 좌표 $x_g$로 변환하고자 한다.

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

$$ x = x_{e1}e_1 + x_{e2}e_2 = x_{g1} g_1 + x_{g2} g_2 $$$$ x = \begin{bmatrix} e_1 & e_2 \end{bmatrix} x_e = \begin{bmatrix} g_1 & g_2 \end{bmatrix} x_g $$

이 식에

$$ \begin{bmatrix} g_1 & g_2 \end{bmatrix} = \begin{bmatrix} e_1 & e_2 \end{bmatrix} A $$

를 대입하면

$$ x = \begin{bmatrix} e_1 & e_2 \end{bmatrix} x_e = \begin{bmatrix} e_1 & e_2 \end{bmatrix} A x_g $$

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

$$ x_e = A x_g $$$$ x_g = A^{-1}x_e = Tx_e $$

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

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

$$ x = 2 e_1 + 2 e_2= \begin{bmatrix}2 \\ 2\end{bmatrix} = x_e $$

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

$$ 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} $$

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

$$ 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} $$

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

In [7]:
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=dict(facecolor='green'))
plt.annotate('', xy=e2, xytext=(0, 0), arrowprops=dict(facecolor='green'))
plt.annotate('', xy=x, xytext=(0, 0), arrowprops=dict(facecolor='gray'))
plt.annotate('', xy=g1, xytext=(0, 0), arrowprops=dict(facecolor='red'))
plt.annotate('', xy=g2, xytext=(0, 0), arrowprops=dict(facecolor='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를 사용하면 다음처럼 계산할 수 있다.

In [8]:
A = np.vstack([g1, g2]).T
A
Out:
array([[ 0.70710678, -0.70710678],
       [ 0.70710678,  0.70710678]])
In [9]:
Ainv = np.linalg.inv(A)
Ainv
Out:
array([[ 0.70710678,  0.70710678],
       [-0.70710678,  0.70710678]])
In [10]:
Ainv.dot(x)
Out:
array([2.82842712, 0.        ])

즉, 좌표변환은 행렬의 곱셉으로 구할 수 있다.

연습 문제 5.3.19

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

$$ g_1 = \begin{bmatrix} 1 \\ 0.75 \end{bmatrix} ,\;\; g_2 = \begin{bmatrix} -1 \\ 0.75 \end{bmatrix} $$

이미지 변환

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

$$ e_1 = \begin{bmatrix} 0 \\ -1 \end{bmatrix} ,\;\; e_2 = \begin{bmatrix} 1 \\ 0 \end{bmatrix} $$

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

In [11]:
import scipy.misc
import scipy.ndimage

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

e1 = np.array([0, -1])
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

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

plt.subplot(121)
plt.imshow(f, cmap=mpl.cm.bone)
plt.annotate('', xy=500*np.dot(E, g1), xytext=(0, 0),
             arrowprops=dict(facecolor='red'))
plt.annotate('', xy=500*np.dot(E, g2), xytext=(0, 0),
             arrowprops=dict(facecolor='red'))
plt.grid(False)
plt.xlim(-200, 1000)
plt.ylim(800, -500)
plt.title("좌표변환전")
plt.subplot(122)
plt.imshow(f1, cmap=mpl.cm.bone)
plt.annotate('', xy=(0, 500), xytext=(0, 0), arrowprops=dict(facecolor='red'))
plt.annotate('', xy=(500, 0), xytext=(0, 0), arrowprops=dict(facecolor='red'))
plt.grid(False)
plt.xlim(-200, 1000)
plt.ylim(800, -500)
plt.title("좌표변환후")
plt.show()