다운로드
작성자: admin 작성일시: 2017-02-05 11:57:12 조회수: 7913 다운로드: 310
카테고리: 기초 수학 태그목록:

벡터와 행렬의 연산

벡터와 행렬도 숫자처럼 덧셈, 뺄셈, 곱셈 등의 연산을 할 수 있다. 행렬의 연산을 이용하면 대량의 데이터에 대한 계산을 간단한 수식으로 나타낼 수 있다. 물론 행렬에 대한 연산은 숫자의 사칙 연산과는 몇 가지 다른 점이 있으므로 이러한 차이를 잘 알아야 한다.

벡터와 행렬의 덧셈과 뺄셈

같은 크기를 가진 두 개의 벡터나 행렬은 덧셈과 뺄셈을 할 수 있다. 두 벡터와 행렬에서 같은 위치에 있는 원소끼리 덧셈과 뺄셈을 하면 된다. 이러한 연산을 요소별(element-wise) 연산이라고 한다. 예를 들어 벡터 x와 y가 다음과 같으면,

예를 들어 벡터 $x$와 $y$가 다음과 같으면,

$$ x= \begin{bmatrix} 10 \\ 11 \\ 12 \\ 13 \\ 14 \\ \end{bmatrix} $$
$$ y= \begin{bmatrix} 0 \\ 1 \\ 2 \\ 3 \\ 4 \\ \end{bmatrix} $$

벡터 $x$와 $y$의 덧셈 $x+y$와 뺄셈 $x-y$는 다음과 같다.

$$ x + y = \begin{bmatrix} 10 \\ 11 \\ 12 \\ 13 \\ 14 \\ \end{bmatrix} + \begin{bmatrix} 0 \\ 1 \\ 2 \\ 3 \\ 4 \\ \end{bmatrix} = \begin{bmatrix} 10 + 0 \\ 11 + 1 \\ 12 + 2 \\ 13 + 3 \\ 14 + 4 \\ \end{bmatrix} = \begin{bmatrix} 10 \\ 12 \\ 14 \\ 16 \\ 18 \\ \end{bmatrix} $$
$$ x - y = \begin{bmatrix} 10 \\ 11 \\ 12 \\ 13 \\ 14 \\ \end{bmatrix} - \begin{bmatrix} 0 \\ 1 \\ 2 \\ 3 \\ 4 \\ \end{bmatrix} = \begin{bmatrix} 10 - 0 \\ 11 - 1 \\ 12 - 2 \\ 13 - 3 \\ 14 - 4 \\ \end{bmatrix} = \begin{bmatrix} 10 \\ 10 \\ 10 \\ 10 \\ 10 \\ \end{bmatrix} $$

이를 NumPy로 계산하면 다음과 같다. 여기에서는 편의상 1차원 배열로 벡터를 표시하였다.

In:
x = np.array([10, 11, 12, 13, 14])
x
Out:
array([10, 11, 12, 13, 14])
In:
y = np.array([0, 1, 2, 3, 4])
y
Out:
array([0, 1, 2, 3, 4])
In:
x + y
Out:
array([10, 12, 14, 16, 18])
In:
x - y
Out:
array([10, 10, 10, 10, 10])

행렬도 마찬가지 방법으로 덧셈과 뺄셈을 할 수 있다.

$$ \begin{bmatrix} 5 & 6 \\ 7 & 8 \end{bmatrix} + \begin{bmatrix} 10 & 20 \\ 30 & 40 \\ \end{bmatrix} - \begin{bmatrix} 1 & 2 \\ 3 & 4 \end{bmatrix} = \begin{bmatrix} 14 & 24 \\ 34 & 44 \end{bmatrix} $$
In:
np.array([[5, 6], [7, 8]]) + np.array([[10, 20], [30, 40]]) - np.array([[1, 2], [3, 4]])
Out:
array([[14, 24],
       [34, 44]])

벡터와 스칼라의 덧셈, 뺄셈

원래 덧셈과 뺄셈은 크기(차원)가 같은 두 벡터에 대해서만 할 수 있다. 하지만 벡터와 스칼라의 경우에는 관례적으로 다음처럼 1-벡터를 사용하여 스칼라를 벡터로 변환한 연산을 허용한다. 이를 브로드캐스팅(broadcasting)이라고 한다.

$$ \begin{bmatrix} 10 \\ 11 \\ 12 \\ 13 \\ 14 \\ \end{bmatrix} - 10 = \begin{bmatrix} 10 \\ 11 \\ 12 \\ 13 \\ 14 \\ \end{bmatrix} - 10\cdot \mathbf{1} = \begin{bmatrix} 10 \\ 11 \\ 12 \\ 13 \\ 14 \\ \end{bmatrix} - \begin{bmatrix} 10 \\ 10 \\ 10 \\ 10 \\ 10 \\ \end{bmatrix} $$

데이터 분석에서는 원래의 데이터 벡터가 아니라 그 데이터 벡터의 각 원소의 평균값을 뺀 평균 제거 데이터 혹은 0-평균(zero-mean) 데이터를 사용하는 경우가 많다.

$$ x = \begin{bmatrix} x_1 \\ x_2 \\ \vdots \\ x_N \end{bmatrix} \;\; \rightarrow \;\; \bar{x} = \begin{bmatrix} x_1 - m\\ x_2 - m \\ \vdots \\ x_N - m \end{bmatrix} $$

위 식에서 $m$은 다음처럼 계산하는 샘플 평균이다.

$$ m = \dfrac{1}{N}\sum_{i=1}^N x_i $$

스칼라와 벡터/행렬의 곱셈

벡터 $x$ 또는 행렬 $A$에 스칼라 값 $c$를 곱하는 것은 벡터 $x$ 또는 행렬 $A$의 모든 원소에 $c$를 곱하는 것과 같다.

$$ c \begin{bmatrix} x_1 \\ x_2 \end{bmatrix} = \begin{bmatrix} cx_1 \\ cx_2 \end{bmatrix} $$$$ c \begin{bmatrix} a_{11} & a_{12} \\ a_{21} & a_{22} \end{bmatrix} = \begin{bmatrix} ca_{11} & ca_{12} \\ ca_{21} & ca_{22} \end{bmatrix} $$

선형 조합

벡터/행렬에 다음처럼 스칼라 값을 곱한 후 더하거나 뺀 것을 벡터/행렬의 선형 조합(linear combination)이라고 한다. 벡터나 행렬을 선형 조합해도 크기는 변하지 않는다.

$$c_1x_1 + c_2x_2 + c_2x_2 + \cdots + c_Lx_L = x$$$$c_1A_1 + c_2A_2 + c_2A_2 + \cdots + c_LA_L = A$$$$ c_1, c_2, \ldots, c_L \in \mathbf{R} $$$$ x_1, x_2, \ldots, x_L, x \in \mathbf{R}^M $$$$ A_1, A_2, \ldots, A_L, A \in \mathbf{R}^{M \times N} $$

벡터와 벡터의 곱셈

행렬의 곱셈을 정의하기 전에 우선 두 벡터의 곱셈을 알아보자. 벡터를 곱셈하는 방법은 내적(inner product)외적(outer product) 등 여러 가지가 있다. 여기서는 내적에 대해서만 다룰 것이므로 그냥 곱셈이라고 하면 내적이라고 생각하면 된다. 벡터 $x$와 벡터 $y$의 내적은 다음처럼 앞에 오는 벡터를 행벡터로 변환한 다음 뒤에 곱하는 벡터는 붙여쓴다.

$$ x^T y $$

내적은 다음처럼 점(dot)으로 표기하는 경우도 있어서 dot product라고도 부르고 < $x,y$ > 기호로 나타낼 수도 있다.

$$ x \cdot y = \, < x, y > \, = x^T y $$

두 벡터의 곱셈을 하려면 다음과 같은 조건이 만족되어야 한다.

  1. 우선 두 벡터의 길이가 같아야 한다.
  2. 앞의 벡터가 행 벡터이고 뒤의 벡터가 열 벡터여야 한다.

이때 두 벡터의 곱은 다음처럼 정의한다. 우선 같은 위치에 있는 원소들을 각각 곱한 다음에 그 값들을 다시 모두 더해서 하나의 스칼라값으로 만든다.

$$ x^T y = \begin{bmatrix} x_{1} & x_{2} & \cdots & x_{N} \end{bmatrix} \begin{bmatrix} y_{1} \\ y_{2} \\ \vdots \\ y_{N} \\ \end{bmatrix} = x_1 y_1 + \cdots + x_N y_N = \sum_{i=1}^N x_i y_i $$

각각의 벡터의 크기를 표시하면 다음과 같다.

$$ x \in \mathbf{R}^{N \times 1} , \; y \in \mathbf{R}^{N \times 1} \; \rightarrow \; x^T y \in \mathbf{R} $$

왜 벡터의 곱셈은 덧셈이나 뺄셈과 달리 이렇게 복잡하게 정의된 것일까. 왜냐하면, 실제로 데이터 분석을 할 때 이러한 연산을 사용하는 경우가 많기 때문이다. 벡터의 곱셈을 사용하여 데이터를 분석하는 몇 가지 예를 살펴보자.

가중합

가중합(weighted sum)이란 복수의 데이터를 단순히 합하는 것이 아니라 각각의 수에 어떤 가중치 값을 곱한 후 이 곱셈 결과들을 다시 합한 것을 말한다.

만약 데이터가 $x=[x_1, \cdots, x_N]^T$ 이고 가중치가 $w=[w_1, \cdots, w_N]^T$ 이면 가중합은 다음과 같다.

$$ w_1 x_1 + \cdots + w_N x_N = \sum_{i=1}^N w_i x_i $$

이 값을 벡터 $x$와 $w$의 곱으로 나타내면 다음과 같이 $w^Tx$ 또는 $x^Tw$ 라는 간단한 수식으로 표시할 수 있다.

$$ \sum_{i=1}^N w_i x_i $$
$$ = \begin{bmatrix} w_{1} && w_{2} && \cdots && w_{N} \end{bmatrix} \begin{bmatrix} x_1 \\ x_2 \\ \vdots \\ x_N \end{bmatrix} = w^Tx $$
$$ = \begin{bmatrix} x_{1} && x_{2} && \cdots && x_{N} \end{bmatrix} \begin{bmatrix} w_1 \\ w_2 \\ \vdots \\ w_N \end{bmatrix} = x^Tw $$

NumPy에서 벡터와 행렬의 곱은 dot이라는 명령으로 계산한다. 2차원 배열로 표시한 벡터의 경우에는 결과값이 스칼라가 아닌 2차원 배열이라는 점에 유의한다.

다음은 두 벡터의 곱셈의 예이다.

$$ x = \begin{bmatrix} 1 \\ 2 \\ 3 \\ \end{bmatrix} ,\;\;\; y = \begin{bmatrix} 4 \\ 5 \\ 6 \\ \end{bmatrix} $$
$$ x^T y = \begin{bmatrix} 1 & 2 & 3 \end{bmatrix} \begin{bmatrix} 4 \\ 5 \\ 6 \\ \end{bmatrix} = 1 \cdot 4 + 2 \cdot 5 + 3 \cdot 6 = 32 $$

이를 NumPy로 계산하면 다음과 같다. 이 때 NumPy에서는 결과 값이 스칼라가 아니라 1x1 크기의 2차원 배열 즉, 행렬로 표시되는 점에 주의한다.

In:
x = np.array([[1], [2], [3]])
y = np.array([[4], [5], [6]])
np.dot(x.T, y)[0, 0]
Out:
32

원래 내적은 크기가 같은 행 벡터와 열 벡터에 대해 정의되지만 NumPy에서는 1차원 배열끼리도 곱할 수 있다. 이 때는 NumPy가 자동적으로 앞의 벡터는 행 벡터이고 뒤의 벡터는 열 벡터라고 가정한다.

In:
x = np.array([1, 2, 3])
y = np.array([4, 5, 6])
np.dot(x, y)
Out:
32

연습 문제 1

A, B, C 세 회사의 주식은 각각 100만원, 80만원, 50만원이다. 이 주식을 각각 3주, 4주, 5주를 매수할 때 필요한 금액을 구하고자 한다.

  1. 주식의 가격과 수량을 각각 $p$ 벡터, $n$ 벡터로 표시하고 NumPy로 코딩한다.
  2. 주시을 매수할 때 필요한 금액을 곱셈으로 표시하고 NumPy 연산으로 그 값을 계산한다.

가중평균

가중합의 가중치값을 전체 가중치값의 합으로 나누면 가중평균(weighted average)이 된다. 가중평균은 대학교의 평균 성적 계산 등에 사용할 수 있다.

예를 들어 고등학교에서는 국어, 영어, 두 과목의 평균 점수를 구할 때 단순히 두 과목의 점수(숫자)를 더한 후 2으로 나눈다. 그러나 대학교에서는 중요한 과목과 중요하지 않는 과목을 구분하는 학점(credit)이라는 숫자가 있다. 일주일에 한 시간만 수업하는 과목은 1학점짜리 과목이고 일주일에 세 시간씩 수업하는 중요한 과목은 3학점짜리 과목이다. 1학점과 3학점 과목의 점수가 각각 100점, 60점이면 학점을 고려한 가중 평균(weighted average) 성적은 다음과 같이 계산한다.

$$ \dfrac{\text{학점과 점수의 가중합}}{\text{학점의 총합}} = \dfrac{1}{1 + 3} \times 100 + \dfrac{3}{1 + 3} \times 60 = 70 $$

벡터로 표현된 $N$개의 데이터의 단순 평균은 다음처럼 생각할 수 있다.

$$ \bar{x} = \dfrac{1}{N}\sum_{i=1}^N x_i = \dfrac{1}{N} \mathbf{1}_N^T x $$

위 수식에서 보인 것처럼 $x$ 데이터의 평균은 보통 $\bar{x}$라는 기호로 표기하고 x bar 라고 읽는다.

다음은 NumPy로 평균을 계산하는 방법이다. mean 이라는 메서드를 사용할 수도 있다.

In:
x = np.arange(10)
x.mean() 
Out:
4.5
In:
N = len(x)
np.dot(np.ones(N), x) / N
Out:
4.5

연습 문제 2

벡터 $x$의 평균 제거 벡터(0-평균) 벡터는 다음과 같이 계산함을 증명하라.

$$ x - \dfrac{1}{N}\mathbf{1}\mathbf{1}^Tx $$

유사도

벡터의 곱셈(내적)은 두 벡터간의 유사도(similarity)를 계산하는데도 이용할 수 있다. 유사도는 두 벡터가 닮은 정도르 수치적으로 나타낸 값으로 많이 닮은 경우에는 값이 커지고 닮지 않은 경우에는 작아지는 특성을 가진다. 유사도를 계산하는 방법도 여러가지가 있지만 내적도 유사도를 계산하는 방법 중의 하나이다.

예를 들어 0부터 1사이의 값을 원소로 가지는 두 벡터에서 같은 위치의 원소(수치)를 서로 곱할 때 두 원소의 값 중 어느 하나라도 0에 가까우면 곱은 0에 가까운 작은 값이 된다. 두 원소의 값이 모두 1에 가까우면 곱은 1에 가까운 큰 값이 된다. 따라서 같은 위치의 값이 크기가 같은 경우가 많을 수록 전체 곱의 합 즉, 내적값이 커지는 경향을 띤다.

추후 선형대수의 기하학적 의미를 공부할 때 이 부분에 대해 다시 살펴볼 것이다.

In:
from sklearn.datasets import load_digits

digits = load_digits()
d0 = digits.images[0]; d1 = digits.images[10]
d2 = digits.images[1]; d3 = digits.images[11]
v0 = d0.reshape(64, 1); v1 = d1.reshape(64, 1)
v2 = d2.reshape(64, 1); v3 = d3.reshape(64, 1)

f, ax = plt.subplots(4, 1, figsize=(12, 2))
ax[0].imshow(v0.T, interpolation='nearest', cmap=plt.cm.bone_r)
ax[0].grid(False); ax[0].set_xticks([]); ax[0].set_yticks([]); ax[0].set_ylabel("0")
ax[1].imshow(v1.T, interpolation='nearest', cmap=plt.cm.bone_r)
ax[1].grid(False); ax[1].set_xticks([]); ax[1].set_yticks([]); ax[1].set_ylabel("0")
ax[2].imshow(v2.T, interpolation='nearest', cmap=plt.cm.bone_r)
ax[2].grid(False); ax[2].set_xticks([]); ax[2].set_yticks([]); ax[2].set_ylabel("1")
ax[3].imshow(v3.T, interpolation='nearest', cmap=plt.cm.bone_r)
ax[3].grid(False); ax[3].set_xticks([]); ax[3].set_yticks([]); ax[3].set_ylabel("1")
plt.tight_layout()
plt.show()
In:
np.dot(v0.T, v1), np.dot(v2.T, v3)  # 같은 숫자 벡터의 내적
Out:
(array([[ 3064.]]), array([[ 3661.]]))
In:
np.dot(v0.T, v2), np.dot(v1.T, v2) # 서로 다른 숫자 벡터의 내적
Out:
(array([[ 1866.]]), array([[ 2421.]]))

연습 문제 3

다음 코드를 실행하면 MNIST digit image 전체 데이터를 모두 벡터로 변환하여 하나의 NumPy 행렬 $X$를 만든다. 이 행렬을 이용하여 다음 문제를 풀어라.

from sklearn.datasets import load_digits
X = load_digits().data
  1. 내적을 이용하여 첫번째 이미지와 10번째 이미지의 유사도를 구하라.
  2. 내적을 이용하여 모든 이미지의 조합에 대해 유사도를 구하라. 어떻게 구현하는 것이 효율적일까? (힌트: 이 문제는 뒤에서 배울 행렬과 행렬의 곱셈을 이용한다.)

선형 회귀 모형

선형 회귀 모형(linear regression model)이란 독립 변수 $x$에서 종속 변수 $y$를 예측하기 위한 방법의 하나로 독립 변수 벡터 $x$ 와 가중치 벡터 $w$와의 가중합으로 ${y}$와 가장 비슷한 값 $\hat{y}$를 계산하는 수식을 말한다.

$$ \hat{y} = w_1 x_1 + \cdots + w_N x_N$$

이 수식에서 기호 ^는 캐럿(caret)이라는 기호이고 $\hat{y}$는 y hat 이라고 읽는다.

이 수식은 벡터의 곱으로 표현 할 수 있다.

$$ \hat{y} = w^Tx$$

여기에서 가장 비슷한 값이라고 한 이유는 우리가 원하는 $y$와 정확히 똑같은 값을 만들어주는 가중치 벡터 $w$를 찾을 수 없는 경우가 많기 때문이다. 이 경우에는 원래의 $y$와 가장 비슷한 $\hat{y}$ 값이라도 계산해 주는 가중치 벡터 $w$로 만족해야 한다.

선형 회귀 모형은 가장 단순하면서도 가장 널리 쓰이는 예측 모형이다.

예를 들어 어떤 아파트 단지의 아파트 가격을 조사하였더니 개별 아파트의 가격은 면적, 층수, 한강이 보이는지의 여부에 의해 달라진다는 사실을 알게 되었다. 이 때 이 단지내의 개별 아파트 가격을 예측하는 예측 모형은 다음과 같이 만들 수 있다.

  • 평균 면적은 80$m^2$이며 해당 아파트 면적과 평균 면적과의 차이를 $x_1$이라고 한다. 그러면 면적이 100$m^2$인 아파트의 경우 $x_1 = 20$이고 면적이 70$m^2$인 아파트의 경우 $x_1 = -10$이다.
  • 층수는 1층부터 20층까지이며 "층수 - 1"의 수를 입력 데이터 $x_2$라고 한다. 10층이면 $x_2 = 10 - 1 = 9$ 이다.
  • 한강이 보이는지의 여부를 입력 데이터 $x_3$라고 하며 한강이 보이면 $x_3 = 1$, 보이지 않으면 $x_3 = 0$이라고 한다.
  • 출력 데이터 $\hat{y}$는 $x_1 = x_2 = x_3 = 0$일 때의 기본 가격(base price)과 해당 아파트의 예측 가격과의 차이이다.

출력과 입력 데이터를 이렇게 다소 복잡하게 인코딩하는 이유는 선형 회귀 모형에서 상수항을 없애기 위해서이다. 이 부분에 대해서는 추후 선형 회귀 부분에서 보다 자세하게 다룬다.

위와 같이 입력 데이터와 출력 데이터를 정의하고 회귀 분석을 한 결과가 다음과 같은 선형 회귀 모형으로 표현할 수 있다고 가정하자.

$$ \hat{y} = 500 x_1 + 200 x_2 + 1000 x_3 $$

이 결과는 다음과 같이 해석할 수 있다.

  • 면적이 1$m^2$ 증가할수록 가격은 500만 원이 증가한다.
  • 층수가 1층 높아질수록 가격은 200만 원이 증가한다.
  • 한강이 보이는 집은 1,000만 원의 웃돈(프리미엄)이 존재한다.

이 식은 다음과 같이 고쳐 쓸 수 있다.

$$ \hat{y} = \begin{bmatrix} 500 & 200 & 1000 \end{bmatrix} \begin{bmatrix} x_1 \\ x_2 \\ x_3 \end{bmatrix} = w^T x $$

즉 이 선형 예측 모형은 다음과 같은 가중치 벡터로 표현할 수 있다.

$$ w^T = \begin{bmatrix} 500 & 200 & 1000 \end{bmatrix} $$

인공 신경망(artificial neural network)에서는 선형회귀 모형을 다음과 같은 그림으로 표현한다. 데이터는 노드(node) 혹은 뉴런(neuron)이라는 동그라미로 표시하고 곱셈은 선분(line)위에 곱할 숫자를 써서 나타낸다. 덧셈은 여러개의 선분이 만나는 것으로 표시한다.

제곱합

데이터의 분산(variance)이나 표준 편차(standard deviation)을 구하는 경우에는 각각의 데이터를 제곱한 뒤 이 값을 모두 더한 값 즉 제곱합(sum of squares)을 계산해야 한다. 이 경우에도 벡터의 곱을 사용하여 $x^Tx$로 쓸 수 있다. 분산과 표준 편차에 대해서는 추후 다시 설명한다.

$$ x^T x = \begin{bmatrix} x_{1} & x_{2} & \cdots & x_{N} \end{bmatrix} \begin{bmatrix} x_{1} \\ x_{2} \\ \vdots \\ x_{N} \\ \end{bmatrix} = \sum_{i=1}^{N} x_i^2 $$

행렬과 행렬의 곱셈

벡터의 곱셈을 정의한 후에는 다음과 같이 행렬의 곱셈을 정의할 수 있다.

$A$ 행렬과 $B$ 행렬을 곱한 결과가 $C$ 행렬이 된다고 하자.

$C$의 $i$번째 행, $j$번째 열의 원소 $c_{ij}$의 값은 $A$ 행렬의 $i$번째 행 벡터 $a_i^T$와 $B$ 행렬의 $j$번째 열 벡터 $b_j$의 곱이다.

$$ C = AB \; \rightarrow \; c_{ij} = a_i^T b_j $$

이 정의가 성립하려면 앞의 행렬 $A$의 열의 수가 뒤의 행렬 $B$의 행의 수와 일치해야만 한다.

$$ A \in \mathbf{R}^{N \times L} , \; B \in \mathbf{R}^{L \times M} \; \rightarrow \; AB \in \mathbf{R}^{N \times M} $$

다음은 $$ A \in \mathbf{R}^{4 \times 3} ,\; B \in \mathbf{R}^{3 \times 2} \; \rightarrow \; AB \in \mathbf{R}^{4 \times 2} $$ 인 예이다.

$A$, $B$가

$$ A = \begin{bmatrix} 1 & 2 & 3 \\ 4 & 5 & 6 \end{bmatrix} $$$$ B = \begin{bmatrix} 1 & 2 \\ 3 & 4 \\ 5 & 6 \end{bmatrix} $$

이면 NumPy를 이용하여 다음과 같이 곱을 구할 수 있다.

In:
A = np.array([[1, 2, 3], [4, 5, 6]])
B = np.array([[1, 2], [3, 4], [5, 6]])
In:
C = np.dot(A, B)
C
Out:
array([[22, 28],
       [49, 64]])

연습 문제 4

  1. $A$와 $B$가 위와 같을 때 $AB$를 연습장에 손으로 계산하고 NumPy의 계산결과와 맞는지 확인한다.

  2. 순서를 바꾸어 $BA$를 연습장에 손으로 계산하고 NumPy로도 계산한다. $BA$의 결과가 $AB$와 같은가?

  3. $A$, $B$가 다음과 같을 때, $AB$, $BA$를 (계산이 가능하다면) 손 계산과 NumPy 코드로 구한다. $AB$, $BA$ 모두 계산 가능한가? $$ A = \begin{bmatrix} 1 & 2 & 3 \end{bmatrix} $$ $$ B = \begin{bmatrix} 4 & 7 \\ 5 & 8 \\ 6 & 9 \end{bmatrix} $$

  4. $A$,, $B$가 다음과 같을 때, $AB$, $BA$를 (계산이 가능하다면) 손 계산과 NumPy 코드로 구한다. $AB$, $BA$ 모두 계산 가능한가? $BA$의 결과가 $AB$와 같은가? $$ A = \begin{bmatrix} 1 & 2 \\ 3 & 4 \end{bmatrix} $$ $$ B = \begin{bmatrix} 5 & 6 \\ 7 & 8 \end{bmatrix} $$

  5. $x$가 다음과 같을 때, $x^Tx$와 $xx^T$를 각각 손 계산과 NumPy 코드로 구한다. $x^Tx$와 $xx^T$의 크기에 주목하라. $$ x = \begin{bmatrix} 1 \\ 2 \\ 3 \end{bmatrix} $$

인공 신경망은 내부적으로 다음과 같이 여러 개의 선형회귀 모형을 사용한다. 이 구조는 행렬과 벡터의 곱으로 나타낼 수 있다.

위 그림을 행렬식으로 표현하면 다음과 같다.

$$ \begin{bmatrix} \hat{y}_{1} \\ \hat{y}_{2} \\ \end{bmatrix} = \begin{bmatrix} w_{11} & w_{12} & w_{13} \\ w_{21} & w_{22} & w_{23} \\ \end{bmatrix} \begin{bmatrix} x_{1} \\ x_{2} \\ x_{3} \\ \end{bmatrix} $$$$ \hat{y} = Wx $$

교환 법칙과 분배 법칙

행렬의 곱셈은 곱하는 행렬의 순서를 바꾸는 교환 법칙이 성립하지 않는다. 그러나 덧셈에 대한 분배 법칙은 성립한다.

$$ AB \neq BA $$$$ A(B + C) = AB + AC $$$$ (A + B)C = AC + BC $$

$A$, $B$, $C$가 다음과 같을 때 위 법칙들이 성립하지 않거나 성립하는 것을 NumPy 로 보이면 다음과 같다.

$$ A = \begin{bmatrix} 1 & 2 \\ 3 & 4 \end{bmatrix} $$$$ B = \begin{bmatrix} 5 & 6 \\ 7 & 8 \end{bmatrix} $$$$ C = \begin{bmatrix} 9 & 8 \\ 7 & 6 \end{bmatrix} $$
In:
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])
C = np.array([[9, 8], [7, 6]])

$AB$ 와 $BA$의 값은 다음처럼 다른 값이 나오므로 교환법칙이 성립하지 않음을 알 수 있다.

In:
np.dot(A, B)
Out:
array([[19, 22],
       [43, 50]])
In:
np.dot(B, A)
Out:
array([[23, 34],
       [31, 46]])

분배법칙은 다음과 같이 성립한다.

In:
np.dot(A, B + C)
Out:
array([[42, 42],
       [98, 98]])
In:
np.dot(A, B) + np.dot(A, C)
Out:
array([[42, 42],
       [98, 98]])
In:
np.dot(A + B, C)
Out:
array([[110,  96],
       [174, 152]])
In:
np.dot(A, C) + np.dot(B, C)
Out:
array([[110,  96],
       [174, 152]])

전치 연산도 마찬가지로 덧셈/뺄셈에 대해 분배 법칙이 성립한다.

$$ (A + B)^T = A^T + B^T $$

전치 연산과 곱셈의 경우에는 분배 법칙이 성립하기는 하지만 전치 연산이 분배되면서 곱셈의 순서가 바뀐다.

$$ (AB)^T = B^T A^T $$$$ (ABC)^T = C^T B^T A^T $$

마찬가지로 NumPy로 이 식이 성립하는지 살펴본다.

In:
(A + B).T
Out:
array([[ 6, 10],
       [ 8, 12]])
In:
A.T + B.T
Out:
array([[ 6, 10],
       [ 8, 12]])
In:
(np.dot(A, B)).T
Out:
array([[19, 43],
       [22, 50]])
In:
np.dot(B.T, A.T)
Out:
array([[19, 43],
       [22, 50]])

연습 문제 5

(1) 행렬 $X \,( X \in \mathbf{R}^{N \times M})$가 있을 때, 이 행렬의 각 열의 평균으로 이루어진 벡터 $\bar{x}\,( \bar{x} \in \mathbf{R}^{M})$가 다음과 같음을 보여라.

$$ \bar{x} = \dfrac{1}{N} X^T \mathbf{1}_N $$

(2) 행렬 $\bar{X}\ ( \bar{X} \in \mathbf{R}^{N \times M})$는 동일한 벡터 $\bar{x}^T$를 $N$개 누적하여 만든 행렬이다. 즉 각 열의 모든 값이 그 열의 평균으로 이루어진 행렬이다.

$$ \bar{X} = \begin{bmatrix} \bar{x}^T \\ \bar{x}^T \\ \vdots\\ \bar{x}^T \\ \end{bmatrix} $$

$\bar{X}$가 다음과 같음을 보여라.

$$ \bar{X} = \dfrac{1}{N} \mathbf{1}_N \mathbf{1}_M^T X $$

(3) 다음 코드를 실행하면 붓꽃 전체 데이터를 모두 벡터로 변환하여 하나의 NumPy 행렬 X 를 만든다.

from sklearn.datasets import load_iris
X = load_iris().data

이 데이터로 행렬 $\bar{X}$의 값을 계산하라

곱셈의 연결

연속된 행렬의 곱셈은 계산 순서를 임의의 순서로 해도 상관없다.

$$ ABC = (AB)C = A(BC) $$$$ ABCD = ((AB)C)D = (AB)(CD) = A(BCD) = A(BC)D $$

연습 문제 6

다음 행렬의 곱셈을 순서를 바꾸어 두 가지 방법으로 해본다.

$$ \begin{bmatrix} 1 & 2 \end{bmatrix} \begin{bmatrix} 1 & 2 \\ 3 & 4 \end{bmatrix} \begin{bmatrix} 5 \\ 6 \end{bmatrix}$$

단위 행렬의 곱셈

어떤 정방 행렬이든 단위 행렬을 곱하면 그 행렬의 값이 변하지 않는다.

$$ AI = IA = A $$

NumPy로 다음과 같아 확인한다.

In:
A = np.array([[1, 2], [3, 4]])
I = np.eye(2)
In:
np.dot(A, I)
Out:
array([[ 1.,  2.],
       [ 3.,  4.]])
In:
np.dot(I, A)
Out:
array([[ 1.,  2.],
       [ 3.,  4.]])

그럼 이러한 행렬의 곱셈은 데이터 분석에서 어떤 경우에 사용될까. 행렬의 곱셈 중 가장 널리 쓰이는 것은 다음과 같은 형태의 행렬 $M$과 벡터 $v$의 곱이다.

$$ Mv $$

위와 같은 행렬과 벡터의 곱을 사용하는 몇가지 예를 살펴보자.

열 벡터의 선형 조합

행렬 $X$와 벡터 $w$의 곱은 행렬을 이루는 각 열(column) 벡터 $c_1, c_2, \ldots, c_M$을 뒤에 오는 벡터 $w$의 각 성분 $w_1, w_2, \ldots, w_M$으로 선형 조합(linear combination)을 한 결과 벡터와 같다.

$$ Xw= \begin{bmatrix} c_1 & c_2 & \cdots & c_M \end{bmatrix} \begin{bmatrix} w_1 \\ w_2 \\ \vdots \\ w_M \end{bmatrix} = w_1 c_1 + w_2 c_2 + \cdots + w_M c_M $$

연습 문제 7

다음 행렬 $X$와 벡터 $w$에 대해 곱 $Xw$가 열벡터 $c_1, c_2, c_3$의 선형조합 $w_1c_1 + w_2c_2 + w_3c_3$가 됨을 실제 계산으로 증명하라.

$$ X = \begin{bmatrix} 1 & 2 & 3 \\ 4 & 5 & 6 \end{bmatrix}, \;\; w = \begin{bmatrix} 2 \\ 3 \\ 4 \end{bmatrix} $$

벡터의 선형 조합은 다양한 분야에 응용된다. 예를 들어 두 이미지 벡터의 선형 조합은 두 이미지를 섞어놓은 모핑(morhping) 효과를 얻는데 사용할 수 있다.

In:
from sklearn.datasets import fetch_olivetti_faces
faces = fetch_olivetti_faces()

f, ax = plt.subplots(1, 3)
ax[0].imshow(faces.images[0])
ax[0].grid(False)
ax[0].set_title("x1")
ax[1].imshow(faces.images[10])
ax[1].grid(False)
ax[1].set_title("x2")
ax[2].imshow(0.6 * faces.images[0] + 0.4 * faces.images[10])
ax[2].grid(False)
ax[2].set_title("0.6x1 + 0.4x2")
plt.show()

여러개의 벡터에 대한 가중합 동시 계산

벡터 하나의 가중합은 $w^Tx$ 또는 $x^Tw$로 표시할 수 있다는 것을 배웠다. 그런데 만약 이렇게 $w$ 가중치를 사용한 가중합을 하나의 벡터 $x$가 아니라 여러개의 벡터 $x_1, \cdots, x_M$개에 대해서 모두 계산해야 한다면 어떻게 해야 할까? 예를 들어 위와 같이 선형 회귀 모형을 사용하여 여러개의 데이터 $x_1, x_2, x_3, \cdots, x_N$ 개의 데이터 모두에 대해 예측값 $y_1, y_2, y_3, \cdots, y_N$을 한꺼번에 계산하고 싶다면 다음처럼 데이터 행렬 $X$를 사용하여 $\hat{y} = Xw$라는 수식으로 간단하게 표시할 수 있다.

$$ \begin{eqnarray} \hat{y} = \begin{bmatrix} \hat{y}_1 \\ \hat{y}_2 \\ \vdots \\ \hat{y}_M \\ \end{bmatrix} &=& \begin{bmatrix} w_1 x_{1,1} + w_2 x_{1,2} + \cdots + w_N x_{1,N} \\ w_1 x_{2,1} + w_2 x_{2,2} + \cdots + w_N x_{2,N} \\ \vdots \\ w_1 x_{M,1} + w_2 x_{M,2} + \cdots + w_N x_{M,N} \\ \end{bmatrix} \\ &=& \begin{bmatrix} x_{1,1} & x_{1,2} & \cdots & x_{1,N} \\ x_{2,1} & x_{2,2} & \cdots & x_{2,N} \\ \vdots & \vdots & \vdots & \vdots \\ x_{M,1} & x_{M,2} & \cdots & x_{M,N} \\ \end{bmatrix} \begin{bmatrix} w_1 \\ w_2 \\ \vdots \\ w_N \end{bmatrix} \\ &=& \begin{bmatrix} x_1^T \\ x_2^T \\ \vdots \\ x_M^T \\ \end{bmatrix} \begin{bmatrix} w_1 \\ w_2 \\ \vdots \\ w_N \end{bmatrix} \\ &=& X w \end{eqnarray} $$

즉.

$$ \hat{y} = Xw $$

연습 문제 8

$x_1$, $x_2$가 다음과 같을 때, $$ x_1 = \begin{bmatrix} x_{11} \\ x_{21} \\ x_{31} \\ \end{bmatrix} \;\; x_2 = \begin{bmatrix} x_{12} \\ x_{22} \\ x_{32} \\ \end{bmatrix} $$

다음 등식이 성립함을 보인다.

$$ Xw = \begin{bmatrix} x_1^T \\ x_2^T \\ \end{bmatrix} \begin{bmatrix} w_1 \\ w_2 \\ w_3 \end{bmatrix} = \begin{bmatrix} x_1^Tw \\ x_2^Tw \\ \end{bmatrix} $$

잔차

선형 회귀 분석(linear regression)을 한 결과는 가중치 벡터 $w$라는 형태로 나타나고 예측치는 이 가중치 벡터를 사용한 독립 변수 데이터 레코드 즉, 벡터 $x_i$의 가중합 $w^Tx_i$이 된다고 하였다. 예측치와 실제 값(target) $y_{i}$의 차이를 오차(error) 혹은 잔차(residual) $e_i$라고 한다. 이러한 잔차 값을 모든 독립 변수 벡터에 대해 구하면 잔차 벡터 $e$가 된다.

$$ e_i = y_i - \hat{y}_i = y_i - w^Tx_i$$

잔차 벡터는 다음처럼 $y-Xw$로 간단하게 표기할 수 있다.

$$ \begin{eqnarray} e &=& \begin{bmatrix} e_{1} \\ e_{2} \\ \vdots \\ e_{M} \\ \end{bmatrix} \\ &=& \begin{bmatrix} y_{1} \\ y_{2} \\ \vdots \\ y_{M} \\ \end{bmatrix} - \begin{bmatrix} x^T_{1}w \\ x^T_{2}w \\ \vdots \\ x^T_{M}w \\ \end{bmatrix} \\ &=& y - Xw \end{eqnarray} $$
$$ e = y - Xw $$

잔차 제곱합

잔차의 크기는 잔차 벡터의 각 원소를 제곱한 후 더한 잔차 제곱합(RSS: Residual Sum of Squares)을 이용하여 구한다. 이 값은 $e^Te$로 간단하게 쓸 수 있으며 그 값은 다음처럼 계산한다.

$$ \sum_{i=1}^{N} e_i^2 = \sum_{i=1}^{N} (y_i - w^Tx_i)^2 = e^Te = (y - Xw)^T (y - Xw) $$

연습 문제 9

분배 법칙을 사용하여 위 식 $(y - Xw)^T (y - Xw)$을 풀어쓰면 다음과 같아짐을 보인다.

$$ y^Ty - w^TX^Ty - y^TXw + w^TX^TXw $$

이차 형식

위의 연습 문제에서 마지막 항은 $w^TX^TXw$라는 형태이다. 이 식에서 $X^TX$는 정방 행렬이 되므로 이 정방 행렬을 $A$라고 이름 붙이면 마지막 항은 $w^TAw$와 같은 형태가 된다.

벡터의 이차 형식(Quadratic Form)이란 이처럼 어떤 벡터와 정방 행렬이 "행벡터 x 정방 행렬 x 열벡터" 의 형식으로 되어 있는 것을 말한다.

이 수식을 풀면 $i=1,\ldots,N, j=1,\ldots,N$ 에 대해 가능한 모든 $i,j$ 쌍의 조합을 구한 다음 $i$, $j$에 해당하는 원소 $x_i$, $x_j$를 가중치 $a_{i,j}$와 같이 곱한 값 $a_{i,j}x_ix_j$의 총합이 된다.

$$ \begin{eqnarray} x^T A x &=& \begin{bmatrix} x_{1} & x_{2} & \cdots & x_{N} \end{bmatrix} \begin{bmatrix} a_{1,1} & a_{1,2} & \cdots & a_{1,N} \\ a_{2,1} & a_{2,2} & \cdots & a_{2,N} \\ \vdots & \vdots & \ddots & \vdots \\ a_{N,1} & a_{N,2} & \cdots & a_{N,N} \\ \end{bmatrix} \begin{bmatrix} x_{1} \\ x_{2} \\ \vdots \\ x_{N} \\ \end{bmatrix} \end{eqnarray} $$$$ \begin{eqnarray} &=& \sum_{i=1}^{N} \sum_{j=1}^{N} a_{i,j} x_i x_j \end{eqnarray} $$

연습 문제 10

3차원 벡터와 행렬에 대해 위 등식이 성립함을 보여라.

$$ x = \begin{bmatrix} x_1 \\ x_2 \\ x_3 \end{bmatrix} $$$$ A = \begin{bmatrix} a_{11} & a_{12} & a_{13} \\ a_{21} & a_{22} & a_{23} \\ a_{31} & a_{32} & a_{33} \\ \end{bmatrix} $$

예를 들어 $ x = [1, 2, 3]^T $ 이고 A가 다음과 같다면

$$ A = \begin{bmatrix} 1 & 2 & 3 \\ 4 & 5 & 6 \\ 7 & 8 & 9 \\ \end{bmatrix} $$

NumPy 에서 벡터의 이차 형식은 다음처럼 계산한다.

In:
x = np.array([1,2,3])
x
Out:
array([1, 2, 3])
In:
A = np.arange(1, 10).reshape(3,3)
A
Out:
array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]])
In:
np.dot(np.dot(x, A), x)
Out:
228

연습 문제 11

다음 식이 성립함을 증명하라.

$$ x^TAx = \dfrac{1}{2}x^T(A + A^T)x $$

질문/덧글

dot연산된 2차원 배열 벡터 hamj*** 2017년 3월 24일 9:42 오후

안녕하세요. numpy 관련 문서를 찾다가 압도적인 튜토리얼을 발견했네요 ! 요새 딥러닝관련 문서들을 보는데, 문꽈 출신으로 첩첩산중이라 애로사항이 참 많슴다...
위에서 2차원 벡터의 dot 연산된 "결과값이 스칼라가 아닌 2차원 배열이라는 점에 유의한다."
array([[32]])
이게 무슨 의미인지 이해하기가 힘듭니다. 얼마 전에 본 수학교과서에서는 "내적(inner product = dot product)연산은 결과값이 스칼라이므로 scalar product라고도 부른다"라고 봤거든요. 외적은 결과값도 벡터이므로 벡터곱이라고 부른다고 하구요.
수학적인 결과값은 스칼라이지만, 파이썬의 자료형으로 2차원 배열이라는 의미인지요 ?

답변: dot연산된 2차원 배열 벡터 관리자 2017년 3월 27일 8:29 오후

네, 말씀하신대로 수학적인 결과값은 스칼라이지만, 파이썬의 자료형으로 2차원 배열이라는 의미입니다.

본문의 평균 부분 beom*** 2017년 9월 3일 8:22 오후

본문의 평균 부분에서 N = len(x) np.dot(np.ones(N), x) / N 아래에 나오는 결과값이 잘못 된 것 같습니다. x.mean()의 결과값과 동일하게 4.5로 수정되어야 할 것 같습니다.

답변: 본문의 평균 부분 관리자 2017년 9월 4일 1:38 오후

수정하였습니다. 지적 감사드립니다.

본문의 문장 '벡터로 표현된 N 개의 데이터의 단순 평균은 가중치값이 모두 1/N 인 가중 평균과 같다'에서 가중 평균이 가중 합으로 바뀌어하는게 아닌지요? beom*** 2017년 9월 8일 4:25 오후

답변: 본문의 문장 '벡터로 표현된 N 개의 데이터의 단순 평균은 가중치값이 모두 1/N 인 가중 평균과 같다'에서 가중 평균이 가중 합으로 바뀌어하는게 아닌지요? 관리자 2017년 9월 8일 5:56 오후

수정하였습니다. 지적 감사드립니다.

사용자에 의해 삭제되었습니다. eddy*** 2017년 9월 23일 8:12 오후

사용자에 의해 삭제되었습니다.