본문 바로가기
수학/Numpy로 공부하는 선형대수

벡터와 행렬의 연산

by 대소기 2021. 11. 12.

브로드캐스팅

* 원래 덧셈, 뺄셈은 차원이 같은 두 벡터끼리만 가능하지만, 벡터와 스칼라의 경우 관례적으로 일벡터를 사용해 스칼라를 벡터로 변환한 연산을 허용한다.

선형조합(Linear Combination)

* 벡터/행렬에 다음처럼 스칼라곱을 곱한 후 더하거나 밴 것을 벡터/행렬의 선형조합이라고 한다.

* 벡터나 행렬을 선형조합해도 크기는 변하지 않는다.

벡터와 벡터의 곱셈

내적(inner product)

* 벡터 x와 벡터 y의 내적은 다음과 같이 표기한다. 내적은 점으로도 표기할 수 있고(dot product), <x, y>기호로 나타낼 수도 있다.

* 내적에는 다음과 같은 조건이 필요하다.

1. 두 벡터의 차원이 같음.

2. 앞의 벡터가 행 벡터이고 뒤의 벡터가 열 벡터의 형태를 띰.

* 위에서 열거한 조건 하에 내적이 이뤄질 때 결과 값은 scalar값이 된다.

import numpy as np

x=np.array([[1],[2],[3]])
y=np.array([[4],[5],[6]])

x.T @ y

#array([[32]])

* 벡터의 내적은 python에서 구현할 때 @ 연산자를 사용한다.

x=np.array([1,2,3])
y=np.array([4,5,6])

x@y

#32

* 또한 python에서 벡터를 1차원 array로 구현하였을 때는 따로 Transpose를 해주지 않아도 알아서 내적을 계산해준다.

가중합

* 위에서 배운 내적은 가중합 계산에서 사용될 수 있다.

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

* 위 식을 벡터 표현으로 나타내면 $w^T x$ 또는 $x^T w$ 라는 간단한 수식으로 표시할 수 있게 된다.

* 만약 가중치가 모두 1이면 일반적인 합을 계산한다.

평균

* 평균을 구하는 식을 벡터로 표현하면 다음과 같다.

* 이를 python으로 코딩하면 다음과 같다.

x=np.arange(10)
N=len(x)

np.ones(N) @ x / N

* 위와 같이 계산할 수도 있지만, 사실 x.mean()을 사용하는 것이 더 편하다.

유사도(Similarity)

* 두 벡터가 닮은 정도를 정량적으로 나타낸 값

* 내적을 이용하면 cosine 유사도를 계산하는 것이 가능하다.

from sklearn.datasets import load_digits
import matplotlib.gridspec as gridspec

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

plt.figure(figsize=(9, 9))
gs = gridspec.GridSpec(1, 8, height_ratios=[1],
                       width_ratios=[9, 1, 9, 1, 9, 1, 9, 1])

for i in range(4):
    plt.subplot(gs[2 * i])
    plt.imshow(eval("d" + str(i + 1)), aspect=1,
               interpolation='nearest', cmap=plt.cm.bone_r)
    plt.grid(False)
    plt.xticks([])
    plt.yticks([])
    plt.title("image {}".format(i + 1))
    plt.subplot(gs[2 * i + 1])
    plt.imshow(eval("v" + str(i + 1)), aspect=0.25,
               interpolation='nearest', cmap=plt.cm.bone_r)
    plt.grid(False)
    plt.xticks([])
    plt.yticks([])
    plt.title("vector {}".format(i + 1))
plt.tight_layout()
plt.show()
print('vector 1과 vector2의 내적 값: {}'.format((v1.T @ v2)[0][0]))
print('vector 3과 vector4의 내적 값: {}'.format((v3.T @ v4)[0][0]))
print('vector 1과 vector3의 내적 값: {}'.format((v1.T @ v3)[0][0]))
print('vector 1과 vector4의 내적 값: {}'.format((v1.T @ v4)[0][0]))
print('vector 2과 vector3의 내적 값: {}'.format((v2.T @ v3)[0][0]))
print('vector 2과 vector4의 내적 값: {}'.format((v2.T @ v4)[0][0]))

# vector 1과 vector2의 내적 값: 3064.0
# vector 3과 vector4의 내적 값: 3661.0
# vector 1과 vector3의 내적 값: 1866.0
# vector 1과 vector4의 내적 값: 1883.0
# vector 2과 vector3의 내적 값: 2421.0
# vector 2과 vector4의 내적 값: 2479.0

* 상대적으로 같은 숫자를 나타내는 이미지 벡터끼리 유사도가 높은 것을 확인할 수 있다.

선형회귀 모형

* 독립변수 x1, ... ,xn 과 가중치 변수 w1, .... , wn의 선형결합으로 이뤄진 선형회귀 모형은 다음과 같다.

* 이를 독립변수 벡터 x와 가중치 벡터 w를 사용해 나타내면 다음과 같이 표현할 수 있다.

교환 법칙과 분배 법칙

* 행렬의 곱셈에서 교환법칙은 성립하지 않지만, 덧셈에 대한 분배법칙은 성립한다.

* 전치 연산도 마찬가지로 분배법칙이 성립한다.

* 덧셈에 대해서는 순서의 변경이 없지만, 곱셈에 대해서는 순서가 바뀌게 된다.

곱셈의 연결

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

항등행렬의 곱셈

* 어떤 행렬이든 항등행렬을 곱하면 그 행렬의 값이 변하지 않는다.

행렬과 벡터의 곱

1) 열 벡터의 선형 조합

* 행렬 X와 벡터 w의 곱은 행렬 X를 이루는 열벡터들과 가중치 벡터의 선형 결합을 통해 나타낼 수 있다.

* 벡터의 선형 조합은 두 이미지를 morping하는데 사용될 수 있다.


from sklearn.datasets import fetch_olivetti_faces

faces=fetch_olivetti_faces()

f, ax = plt.subplots(1,3)

ax[0].imshow(faces.images[6], cmap=plt.cm.bone)
ax[0].grid(False)
ax[0].set_xticks([])
ax[0].set_yticks([])
ax[0].set_title("image 1: $x_1$")

ax[1].imshow(faces.images[10], cmap=plt.cm.bone)
ax[1].grid(False)
ax[1].set_xticks([])
ax[1].set_yticks([])
ax[1].set_title("image 2: $x_2$")

new_face = 0.7 * faces.images[6] + 0.3 * faces.images[10] #6번 이지마와 10번 이미지의 선형결합
ax[2].imshow(new_face, cmap=plt.cm.bone)
ax[2].grid(False)
ax[2].set_xticks([])
ax[2].set_yticks([])
ax[2].set_title("image 3: $0.7x_1 + 0.3x_2$")

plt.show()

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

* 여러개의 벡터에 대한 선형 결합은 다음과 같이 나타낼 수 있다.

잔차

* 선형회귀분석을 통해 도출해 낸 가중치 벡터 w를 활용하였을 때의 예측값과 실제 값 사이의 차이를 잔차라고 한다.

잔차 제곱합(RSS : Residual Sum of Squares)

* 잔차의 크기는 잔차 벡터의 각 원소를 제곱한 후 더한 잔차 제곱합을 통해 나타낼 수 있다.

* 벡터의 제곱은 앞에서 살펴봤듯이 전치된 벡터(행벡터)와 원본 벡터(열벡터)의 곱을 통해 나타낼 수 있다.

* 또한 벡터를 제곱하면 '정방행렬' 형태가 된다((M x N) * (N x M) = M x M).

이차형식(Quadratic Form)

* 행벡터 x 정방행렬 x 열벡터의 형식으로 되어있는 것을 이차 형식이라고 한다.

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

 

부분행렬

* 다음과 같은 2차원 정방행렬 A,B가 있을 때 두 행렬의 곱 AB를 구하는 방법은 여러가지가 될 수 있다.

1) 앞에 곱해지는 행렬을 행 벡터로 나누어 계산

 

 

2) 뒤에 곱해지는 행렬을 열 벡터로 나누어 계산

3) 앞에 곱해지는 행렬을 열벡터로 뒤에 곱해지는 행렬을 행 벡터로 나누어 스칼라처럼 계산

 

'수학 > Numpy로 공부하는 선형대수' 카테고리의 다른 글

선형대수와 해석기하의 기초  (0) 2021.11.22
선형 연립방정식과 역행렬  (0) 2021.11.18
행렬의 성질  (0) 2021.11.15
데이터와 행렬  (0) 2021.11.12