벡터와 행렬

April 03, 2017

파이썬 Numpy를 활용해서 선형대수학에서 기초가 되는 벡터와 행렬에 대해서 살펴보겠다.

본 포스팅은 제가 공부용으로 작성한 글입니다. 아래의 글을 참고로 작성했으며 일부 유사한 표현이 있을 수 있습니다. 보다 정확한 개념공부를 위해 원 저자의 글을 반드시 읽어주시면 감사하겠습니다.

벡터(Vector)란

이차원 좌표를 가진 V(x,y)에서 벡터의 크기는 원점을 기준으로 대각선의 길이를 의미한다. 선형대수에서는 이를 ‘노름(norm)’이라고 부르고   v   라고 표시를 한다.
\[||(x,y)||=\sqrt{(x-0)^2+(y-0)^2}\]
import numpy as np
import numpy.linalg as liv
x=np.array([1,2,3])
y=np.array([4,5,6])
z=np.array([2,2])
liv.norm(z)
2.8284271247461903

벡터간의 덧셈은 두 좌표를 더 하면 되는데, 두 벡터를 평행이동해서 만든 평행사변형의 대각선의 길이와 일치한다. 뺄셈도 좌표를 빼면 되는 데, 빼려는 벡터가 이동하려는 방향과 반대편 방향으로 이동한 벡터간의 대각선의 길이와 일치한다.

베터의 곱셈은 단순히 상수를 곱하는 “스칼라 곱(Scalar Product)”과 벡터끼리 곱하는 “성분곱(Elementwise multipication)”으로 나뉜다.

\(스칼라곱: \alpha V=(\alpha V_{1},\cdots \alpha V_{d})\) \(성분곱:x \odot y = (x_{1}* y_{1} \cdots x_{i}* y_{i})\)

np.add(x,y),np.subtract(x,y),np.multiply(3,x),np.multiply(x,y)
(array([5, 7, 9]), array([-3, -3, -3]), array([3, 6, 9]), array([ 4, 10, 18]))

벡터의 내적(inner product)는 방향이 있는 두 벡터 간의 연산이다. 값은 스칼라를 환원하며, 평면상 벡터의 합이다.

  1. 좌표값의 각 성분을 곱해서 더한다. $x \cdot y=\sum_{i=1}^d x_iy_i $
  2. 벡터의 크기를 곱할 수 있다. $ x \cdot y * cos\theta $

벡터의 외적(cross product)는 내적과 달리 3차원에서만 의미를 가지며, 스칼라를 변화하는 것이 아닌 두 베턱와 수직인 벡터를 반환한다. 외적의 결과값으로 나온 벡터는 외적의 대상인 두 벡터가 이루는 평행사변형의 넓이다. 또한 벡터의 외적/내적은 행렬의 내적/외적과는 구분되는 개념이다.

  1. 좌표값의 각 성분을 곱해서 더한다.$(x_2y_3 – x_3y_2, x_3y_1 – x_1y_3, x_1y_2 – x_2y_1)$
  2. 벡터의 크기를 곱할 수 있다. $ x \cdot y * sin\theta$

여기서 베터의 외적(cross product)와 행렬의 외적(outer product) 헷갈리면 안된다. Outer product는 두개의 벡터를 가지고 벡터 크기를 행과 열로 만드는 함수이다.

\[\begin{bmatrix} x_1,\cdots x_n \end{bmatrix} \begin{bmatrix} y_1,\\ \vdots \\ y_n \end{bmatrix}= \begin{bmatrix} x_1y_1& &\\ & \ddots & \\ & & x_ny_n \end{bmatrix}\]
np.inner(x,y),np.cross(x,y),np.outer(x,y)
(32, array([-3,  6, -3]), array([[ 4,  5,  6],
        [ 8, 10, 12],
        [12, 15, 18]]))

행렬(Matrix)

행렬이란 벡터의 모임이므로 행렬은 성분은 벡터이다. 행렬의 가로는 행(row),세로는 열(column)이다.

행렬의 곱셉은 크게 아래와 같이 나타낼수 있다.번역이 오히려 헷갈리는 점이 많아서 영어로 쓰겠다.

  1. dot: 행과 열의 곱셈이다. 앞선 행렬의 행의 개수와 뒷 행렬의 열의 개수가 같아야 한다. Dot(mn,nm)=m*m
  2. inner: 행과 행의 곱셈이다. 동일한 행과 열의 행렬이야어야지 가능하다. Inner(mn,nm)=m*m
  3. outer: 벡터 부분에서 설명했으므로 생략
  4. tensor dot: 행렬안 행렬이라고 생각하면 된다. 텐서곱을 취하면, 앞 행렬의 각각 성분이 뒤 행렬에 곱해져서 행렬안의 행렬의 생성한다. 임성빈님은 “텐서는 수학에서 벡터, 행렬을 3차원 이상으로 일반화시킨 개념이다.(벡터는 1차원 텐서, 행렬은 2차원 텐서)”라고 정리를 한다.

\(a \otimes b = \begin{bmatrix} a_{1,1} & a_{1,2} \\ a_{2,1} & a_{2,2} \\ \end{bmatrix} \otimes \begin{bmatrix} b_{1,1} & b_{1,2} \\ b_{2,1} & b_{2,2} \\ \end{bmatrix} =\) \begin{bmatrix} a_{1,1} \begin{bmatrix} b_{1,1} & b_{1,2}
b_{2,1} & b_{2,2}
\end{bmatrix} & a_{1,2} \begin{bmatrix} b_{1,1} & b_{1,2}
b_{2,1} & b_{2,2}
\end{bmatrix}
&
a_{2,1} \begin{bmatrix} b_{1,1} & b_{1,2}
b_{2,1} & b_{2,2}
\end{bmatrix} & a_{2,2} \begin{bmatrix} b_{1,1} & b_{1,2}
b_{2,1} & b_{2,2}
\end{bmatrix}
\end{bmatrix} = \begin{bmatrix} a_{1,1} b_{1,1} & a_{1,1} b_{1,2} & a_{1,2} b_{1,1} & a_{1,2} b_{1,2}
a_{1,1} b_{2,1} & a_{1,1} b_{2,2} & a_{1,2} b_{2,1} & a_{1,2} b_{2,2}
a_{2,1} b_{1,1} & a_{2,1} b_{1,2} & a_{2,2} b_{1,1} & a_{2,2} b_{1,2}
a_{2,1} b_{2,1} & a_{2,1} b_{2,2} & a_{2,2} b_{2,1} & a_{2,2} b_{2,2}
\end{bmatrix} $

x=np.array([[1,2,3],[4,5,6]])
y=np.array([[10,11],[12,13],[14,15]])
np.dot(x,y),np.inner(x,x)
(array([[ 76,  82],
        [184, 199]]), array([[14, 32],
        [32, 77]]))
a=np.array([[1,2],[3,4]])
b=np.array([[5,6],[7,8]])
np.tensordot(a,b,axes=0)
array([[[[ 5,  6],
         [ 7,  8]],

        [[10, 12],
         [14, 16]]],


       [[[15, 18],
         [21, 24]],

        [[20, 24],
         [28, 32]]]])

Numpy tensordot는 axes에 따라 다른 연산을 하니, 참고하기를 바란다.

np.tensordot(a,b,axes=1),np.dot(a,b)
(array([[19, 22],
        [43, 50]]), array([[19, 22],
        [43, 50]]))