※ 위 내용의 복습 글입니다.
벡터의 사칙연산
Numpy에서 기본적인 같은 크기의 벡터들은 사칙연산을 지원한다. 두 벡터가 행렬에서 같은 위치에 있는 원소끼리 사칙연산이 가능하다. 주의하자 행렬의 사칙연산과는 다른 연산이다. 이를 요소별(element-wise) 연산이라 한다.
np.array([[5,6],[7,8]]) + np.array([[10,20],[30,40]])
- np.array([[1,2],[3,4]])
예외로 벡터와 스칼라 덧셈은 할 수 없지만, Numpy에서 관례적으로 1-벡터를 사용해 행렬과 덧셈이 가능하다.
벡터 내적
넘파이에서 벡터와 행렬의 내적은 dot() 명령어 또는 @(at)이라는 연산자로 계산한다.
이때, 결과값은 원래 스칼라 값이 맞지만 Numpy에선 배열의 차원에 맞춰서 나오게 된다.
배열 차원과 벡터의 차원은 다른 의미이다. 혼동하지 말자. 참고로 column vector를 Numpy로 표한할 때 2차원 배열을 이용해 표현한다.
1차원 배열끼리도 내적을 계산할 수 있다. 이때 앞이 column vector이고 뒤가 row vector이다.
연습 문제 2.2.1
A, B, C 세 회사의 주식은 각각 100만원, 80만원, 50만원이다. 이 주식을 각각 3주, 4주, 5주를 매수할 때 필요한 금액을 구하고자 한다.
(1) 주식의 가격과 수량을 각각 p 벡터, n 벡터로 표시하고 넘파이로 코딩한다.
(2) 주식을 매수할 때 필요한 금액을 곱셈으로 표시하고 넘파이 연산으로 그 값을 계산한다.
가중평균
가중합의 가중치값을 전체 가중치값의 합으로 나누면 가중평균이다.
가중평균은 mean() method를 이용해 쉽게 구할 수 있다.
유사도
내적은 두 벡터 간의 유사도를 계산하는 데도 이용할 수 있다. 두 벡터가 비슷한 경우 유사도가 커지고, 아닌 경우 작아진다. 유사도 중 하나인 코사인 유사도(cosine similarity)를 살펴보자.
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]
# 2 -> 1 dim
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()
같은 이미지일때 내적 값이 아닐 때보다 큰 것을 알 수 있다.
연습 문제 2.2.3
다음 코드를 실행하면 MNIST 숫자 이미지 전체 데이터를 모두 벡터로 변환하여 하나의 넘파이 행렬 X를 만든다. 이 행렬을 이용하여 다음 문제를 풀어라.
from sklearn.datasets import load_digits
X = load_digits().data
(1) 내적을 이용하여 첫 번째 이미지와 10번째 이미지의 유사도를 구하라.
X = load_digits().data
img = []; v = []; samples = [0,9]
for i in range(2):
img.append(digits.images[samples[i]])
v.append(img[i].reshape(64,1))
# images show
for i in range(2):
plt.subplot(1,2,i+1)
plt.imshow(img[i], interpolation='nearest', cmap=plt.cm.bone_r)
plt.grid(False); plt.xticks([]); plt.yticks([])
# similarity
np.dot(v1.T,v10) #np.dot(X[0].T, X[0])
(2) 내적을 이용하여 모든 이미지의 조합에 대해 유사도를 구하라. 어떻게 구현하는 것이 효율적일까? (힌트 : 이 문제는 뒤에서 배울 행렬과 행렬의 곱셈을 이용한다.)
행렬의 곱셈
내적에서 짐작했듯이 행렬의 곱셈은 Numpy에서 @ 또는 dot() 명령을 사용한다.
연습 문제 2.2.4
(1) A와 B가 위와 같을 때 AB를 연습장에 손으로 계산하고 넘파이의 계산 결과와 맞는지 확인한다.
-> 당연히 같다..
(2) 순서를 바꾸어 BA를 손으로 계산하고 넘파이의 계산 결과와 맞는지 확인한다. BA가 AB와 같은가?
-> 행렬의 곱셈은 교환법칙이 성립되지 않는다.
(3) A, B가 다음과 같을 때, AB, BA를 (계산이 가능하다면) 손으로 계산하고 넘파이의 계산 결과와 맞는지 확인한다. AB, BA 모두 계산 가능한가?
-> AB는 계산 가능하지만, BA는 계산 불가다.
(4) A, B가 다음과 같을 때, AB, BA를 (계산이 가능하다면) 손으로 계산하고 넘파이의 계산 결과와 맞는지 확인한다. AB, BA 모두 계산 가능한가? BA의 결과가 AB와 같은가?
-> 둘 다 계산은 가능하지만, 결과는 같지 않다.
(5) A가 다음과 같을 때, AAT와 ATA를 손으로 계산하고 넘파이의 계산 결과와 맞는지 확인한다. AAT와 ATA의 크기는 어떠한가? 항상 정방행렬이 되는가?
-> 결과값과 크기는 다르다. 항상 정방행렬이다. 3 x 2 dot 2 x 3 -> 3 x 3 or 2 x 3 dot 3 x 2 -> 2 x 2
(6) xx가 다음과 같을 때, xTx와 xxT를 손으로 계산하고 넘파이의 계산 결과와 맞는지 확인한다. xTx와 xxT의 크기는 어떠한가? 어떤 것이 스칼라이고 어떤 것이 정방행렬인가?
-> xTx -> 1 x 3 dot 3 x 1 -> 1 x 1 (scalar), xxt -> 3 x 1 dot 1 x 3 -> 3 x 3, 둘 다 정방행렬이다.
'Jupyter Notebook > 선형대수' 카테고리의 다른 글
[Python] 선형 연립방정식과 역행렬 (1) | 2021.02.26 |
---|---|
[Python] 행렬의 성질 (0) | 2021.02.22 |
[Python] 벡터와 행렬의 연산 (완) (0) | 2021.02.21 |
[Python] 데이터와 행렬 (0) | 2021.02.19 |