벡터
스칼라와 벡터
그림 1은 무엇을 나타낸 것일까요?
import numpy as np import numpy.linalg as la import sympy as sp import matplotlib.pyplot as plt
d={'r':(-2, -4), 'g':(3, -4), 'b':(5, 3), 'k':(-3, 5)} col=['black','red','green','navy'] plt.figure(dpi=100) plt.scatter(0, 0, label="A(0,0)") for i, j in enumerate(d.keys()): plt.scatter(d[j][0], d[j][1], color=col[i], label=f"{j}{d[j]}") plt.annotate(j, xy=d[j], xytext=(0,0), arrowprops=dict(facecolor=col[i])) plt.legend(loc="best") plt.axhline(0) plt.axvline(0) di={'south':(0.1,-3), 'easth':(3,-0.5), 'west':(-3,-0.5), 'north':(0.1,3) } di2={'south':'y-', 'easth':'x+', 'west':'x-', 'north':'y+' } n=0 for i, j in zip(di.keys(), di2.keys()): plt.text(di[i][0], di[i][1], (di2[j], j), color=col[n], weight='bold') n +=1 plt.show()
그림 1.1의 수치는 동서남북 방향 등의 의미 외에 다양한 의미를 부여할 수 있을 것입니다. 어떠한 해석이든지 우리는 다음의 2가지를 추출할 수 있습니다.
- x축과 y축은 각각 동-서와 남-북을 기준으로 합니다. r
- 각 축을 기준으로 4개 지점의 위치와 거리를 나타냅니다.
각 점의 크기와 방향은 점 A를 기준 계산할 수 있습니다. 예를 들어 b점의 경우 (5, 3)에 위치하며 A로부터의 직선거리는 4입니다. 이 직선거리는 다음 그림과 같은 직각삼각형에 적용되는 피카고라스 정리(식 1)를 사용하여 계산할 수 있습니다.
plt.figure(dpi=100) cd={'b':(1, 0),'a':(0, 1)} for i in cd.keys(): plt.arrow(0, 0, cd[i][0], cd[i][1]) plt.arrow(1, 0, -1, 1) plt.xticks([]) plt.yticks([]) plt.text(0.5, 0.01, "b", fontsize="13", weight="bold", color="navy") plt.text(0.01, 0.5, "a", fontsize="13", weight="bold", color="red") plt.text(0.5, 0.5, "c", fontsize="13", weight="bold", color="green") plt.text(0.01, 0.01, r"$\mathbf{\theta=90^{\circ}}$", fontsize="13", weight="bold") plt.show()$$\begin{equation}\tag{1}c^2=a^2+b^2 \rightarrow c=\sqrt{a^2+b^2}\end{equation}$$
ab=(5**2+3**2)**0.5 # √(52+32) round(ab,2)
5.83
위와 같이 원점을 기준으로 각 점을 계산하면 다음과 같습니다.
point=np.array([[5,3],[3,-4],[-2,-4],[-3,5]]) point
array([[ 5, 3], [ 3, -4], [-2, -4], [-3, 5]])
위 결과를 표로 나타내면 다음과 같습니다.
x | y | distance | |
---|---|---|---|
b | 5.0 | 3.0 | 5.830952 |
g | 3.0 | -4.0 | 5.000000 |
r | -2.0 | -4.0 | 4.472136 |
k | -3.0 | 5.0 | 5.83095 |
점 b에서 밑변의 길이는 (5-0)이 되며 높이는 (3-0)이 됩니다. 그러므로 이 관계를 공식화하면 식 2와 같이 정리됩니다.
$$\begin{equation}\tag{2} \text{Distance}=\sqrt{(x_1-x_0)^2+(y_1-y_0)^2} \end{equation}$$위 식에서 $x_0, y_0$은 시작점, $x_1, y_1$은 종말점을 나타냅니다.
예)
(0, -3)과 (4, 0)사이의 거리를 계산합니다.
여러 좌표들 사이의 거리는 numpy 모듈의 array()
함수를 사용하여 배열 구조로 전환한 뒤 numpy.linalg.norm()
함수를 사용하여 계산할 수 있습니다.
x=np.array([[0], [-3]]) y=np.array([[4],[0]]) x, y
(array([[ 0], [-3]]), array([[4], [0]]))
la.norm([x, y])
5.0
np.sqrt((0-4)**2+(-3-0)**2)
5.0
식 2에서 나타난 것과 같이 각 점의 좌표는 기준점으로부터 방향과 거리를 포함하고 있습니다. 이를 벡터라고 합니다. 반면에 거리와 같은 각 점의 크기는 스칼라라고 합니다. 다음과 같이 정의할 수 있습니다.
- 벡터(Vector): 크기와 방향을 가지고 있는 값
- 스칼라(Scalar): 크기만을 가지는 값
그림 1은 모든 좌표는 원점인 (0, 0)을 기준으로 하였습니다. 그러나 이 기본 좌표가 (0, 0)이 아닌 경우 좌표자체가 이동된다고 생각할 수 있습니다. 예로 A가 (1,1)로 이동된 경우는 그림 2와 같이 변경됩니다.
d={'r':(-1, -3), 'g':(4, -3), 'b':(6, 4), 'k':(-2, 6)} col=['black','red','green','navy'] plt.figure(dpi=100) plt.scatter(1, 1, label="A(1,1)") for i, j in enumerate(d.keys()): plt.scatter(d[j][0], d[j][1], s=0.01) plt.annotate(j, xy=d[j], xytext=(1,1), arrowprops=dict(facecolor=col[i])) if (j=="k") | (j=="b"): plt.text(d[j][0]+0.1, d[j][1]+0.5, f"{j}{d[j]}", color=col[i], weight="bold") else: plt.text(d[j][0]-0.5, d[j][1]-0.5, f"{j}{d[j]}", color=col[i], weight="bold") plt.legend(loc="best") plt.axhline(0) plt.axvline(0) plt.axhline(1, linestyle="--") plt.axvline(1, linestyle="--") plt.xlim(-4, 8) plt.ylim(-5, 8) di={'south':(0.1,-3), 'easth':(3,-0.5), 'west':(-3,-0.5), 'north':(0.1,3) } di2={'south':'y-', 'easth':'x+', 'west':'x-', 'north':'y+' } n=0 for i, j in zip(di.keys(), di2.keys()): plt.text(di[i][0], di[i][1], (di2[j], j), color=col[n], weight='bold') n +=1 plt.show()
그림 2의 경우 그림 1의 기준점 A가 (0,0) → (1,1)로 이동한 것입니다. 이것은 기준이 되는 축이 x와 y 방향으로 1만큼 씩 상승한 것으로 각 점의 모든 위치가 동일한 크기만큼 상승한 것입니다. 그러므로 기본 축의 변경은 다른 모든 점들의 변경을 유도하므로 각 점의 거리는 변함이 없을 것입니다.
차원과 축
여러 1차원 벡터들의 결합으로 2차원 이상의 객체를 생성할 수 있으며 특히 2차원은 행렬(matrix)로 표시합니다. 1차원 벡터를 포함하여 모든 텐서는 numpy의 array(배열 객체, 자료형)
를 사용하여 나타낼 수 있습니다.
다음 코드의 객체 a는 리스트 객체 [1, 2]를 인수로 전달한 것으로 이를 그래프로 나타내면 그림 3과 같이 하나의 축 위에 표시됩니다. 반면에 객체 a1의 경우는 두 개의 리스트를 포함하는 객체를 인수로 전달하는 것으로서 두 개의 축으로 표현되며 축의 갯수는 그 객체의 차원(dimension)이 됩니다.
array 배열 객체에서 대괄호(리스트) 1개는 1개의 축을 나타냅니다. 그러므로 a는 1개의 행으로 이루어진 벡터로 행벡터(row vector), a1은 두 개의 리스트 즉, 두 개의 행이 결합된 형태입니다. 그러므로 2개의 축으로 구성된 것을 의미하며 한개의 축에서 한개의 요소만을 포함하는 것으로 열벡터(column vector)라고 합니다
a=np.array([1,2])#행벡터 a
array([1, 2])
a1=np.array([[1],[2]]) #열벡터 a1
array([[1], [2]])
plt.figure(dpi=100) plt.arrow(0, 0, 1, 2, width=0.007, head_width=0.05, overhang=0.2, label=f"a1={a1}", color="blue") plt.arrow(1, 0, 2, 0, width=0.007, head_width=0.05, overhang=0.2, label=f"a={a}", color="red") plt.text(0.8, 1.3, 'column vector', color="blue", fontsize=12, weight="bold") plt.text(1.5, 0.15, 'row vector', color="red", fontsize=12, weight="bold") plt.legend(loc="upper left") plt.show()
일반적으로 실수의 차원은 $\mathbb{R}^n$로 나타내며 스칼라(scalar)는 0차원($\mathbb{R}^0$), 1차원 배열을 벡터(vector, $\mathbb{R}^1$), 2차원 배열을 행렬($\mathbb{R}^2$), 3차원 이상의 배열을 텐서(tensor)라고 합니다. 그러므로 실제적으로 열벡터는 행렬 또는 텐서로 나타내는 것이 정확합니다. 그림 3과 같이 두 벡터 a와 a1은 같은 원소들을 포함하고 있지만 기하학적으로는 다른 의미를 가집니다.
그림 3과 같이 객체 a와 a1은 모두 선을 나타내지만 a의 경우 하나의 축 위에 표시되지만 a1의 경우 x, y의 두 축에 의해 형성되는 평면 위에 나타냅니다. 즉, a는 1차원에서 나타낼 수 있지만 a1은 2차원이 되어야 표시할 수 있습니다.
파이썬의 numpy 배열에서 단일한 벡터의 차원은 (원소 갯수, )의 형태로 나타내며 위의 a1과 같은 여러 벡터의 모임 즉, 행렬의 형태는 (행 갯수, 열 갯수)로 표현합니다. 이것은 다음 코드에서 사용한 numpy 객체의 차원과 형태를 반환하는 속성 ndim
과 shape
의 결과로 확인할 수 있습니다.
print(f'a의 차원:{a.ndim}, a의 형태:{a.shape}')
a의 차원:1, a의 형태:(2,)
print(f'a1의 차원:{a1.ndim}, a1의 형태:{a1.shape}')
a1의 차원:2, a1의 형태:(2, 1)
그림 1은 x, y 두 개의 축으로 구성되며 4개의 점들은 x 축의 값과 y 축의 값으로 나타냅니다. 즉, 다음과 같이 나타낼 수 있습니다.
b | g | r | k | |
---|---|---|---|---|
x 축 | 5.0 | 3.0 | -2.0 | -3.0 |
y 축 | 3.0 | -4.0 | -4.0 | 5.0 |
위의 각 점은 원점 (0, 0)을 기준으로 방향과 크기를 나타내는 벡터이며 표의 전체는 4개의 벡터가 결합하여 하나의 그룹으로 나타낸 것으로 행렬이 됩니다. 이 행렬의 경우를 나타내기 위해서는 두 개의 축이 관계되므로 2차원이 됩니다.
arr=np.array([[5.,3.,-2.,-3.], [3.,-4.,-4.,5.]]) arr
array([[ 5., 3., -2., -3.], [ 3., -4., -4., 5.]])
객체 arr의 경우는 두 개이 리스트(두개의 대괄호)를 포함하므로 2개의 축을 의미합니다. 2개 축이 존재한다는 것은 평면 즉, 2차원을 나타냅니다. 요약하면 축 하나면 선, 즉 1차원이 되며 3개의 축이면 공간 즉, 3차원을 나타냅니다. 이와 같이 차원 개념은 크기 뿐만 아니라 방향을 나타냅니다. 그러므로 크기만을 나타내는 스칼라는 차원이 없는 상태로 0차원이라고 합니다.
위 코드의 객체 arr은 2차원으로 2개의 행과 4개의 열로 구성된 행렬입니다. 즉, 2×4 행렬이라고 나타냅니다.
print(f'arr의 차원:{arr.ndim}, arr의 형태:{arr.shape}')
arr의 차원:2, arr의 형태:(2, 4)
벡터와 행렬의 형태 또는 차원은 그들의 연산 과정 등에서 변화시켜야 할 경우가 존재합니다. 배열 객체의 구조를 전환하기 위해 np.reshape(row#, column#)
함수를 적용합니다. 이 함수의 인수는 전환하기 위한 행과 열의 수입니다. 다음 코드에서 인자로서 row의 수는 -1입니다. 이 값은 다른 인자인 열의 값을 기준으로 자동으로 지정된다는 것을 의미합니다. 다음의 경우는 열의 수 2를 기준으로 행의 수는 자동적으로 조절됩니다.
arr.reshape(-1, 2)
array([[ 5., 3.], [-2., -3.], [ 3., -4.], [-4., 5.]])
댓글
댓글 쓰기