41.1 벡터의 내적과 행렬의 곱
벡터의 내적은 두 벡터 사이의 대응 원소의 곱을 모두 합한 값입니다.
행렬 곱은 왼쪽 행렬의 가로방향 벡터와 오른쪽 행렬의 세로방향벡터 사이의 내적을 계산합니다.
그리고 그 결과가 새로운 행렬의 원소가 됩니다.
넘파이에선 np.dot 함수를 사용합니다.
np.dot(x, y)은 두 인수가 모두 1차원 배열이면 벡터의 내적을 계산하고 인수가 2차원 배열이면 행렬의 곱을 계산합니다.
41.2 행렬의 형상 체크
행렬곱은 아래 그림처럼 대응하는 차원(축)의 원소 수를 일치시킵니다.

41.3 행렬 곱의 역전파

행렬곱의 순전파에서 스칼라 L을 출력하는 계산을 다룰때 x의 i번째 원소에 대한 미분은 아래와 같습니다.


왼쪽의 그림은 xi를 미세하게 변화시켰을 때 L이 얼마나 변화하느냐를 뜻하는 변화율이고
xi를 변화시키면 벡터 y의 모든 원소들이 변화하고 y의 원소가 변화하면 결국 L이 변화합니다.

위의 식이 성립한다고 하면 아래처럼 바꿔줄 수 있습니다.

∂L/ ∂xi는 벡터 ∂L/ ∂y와 W의 i행 벡터의 내적으로 구해져서 아래의 식으로 끌어낼 수 있습니다.


위의 그림을 보면 행렬들의 형상이 결과에 잘 나와있는 것을 알 수 있습니다.
역전파에서도 행렬곱의 형상을 확인할 수 있습니다.

x,W,y가 있고 각각의 쉐입이 (N x D), (D x H), (N x H)라고 했을때 행렬곱의 역전파의 식을 보면

각 행렬의 원소를 계산해 양변을 비교하여 유도할 수 있고 행렬곱의 형상 체크도 충족하는지 확인 할수 있습니다.
class MatMul(Function):
def forward(self, x, W):
y = x.dot(W)
return y
def backward(self, gy):
x, W = self.inputs
gx = matmul(gy, W.T)
gW = matmul(x.T, gy)
return gx, gW
def matmul(x, W):
return MatMul()(x, W)
백워드 쪽을 보면 그림대로 매트릭스 연산을 전치해서 진행한걸 볼 수 있습니다.
if '__file__' in globals():
import os, sys
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
import numpy as np
from dezero import Variable
import dezero.functions as F
x = Variable(np.random.randn(2, 3))
w = Variable(np.random.randn(3, 4))
y = F.matmul(x, w)
y.backward()
print(x.grad.shape)
print(w.grad.shape)

실제 랜덤 다차원 배열을 통해 계산해도 오류가 없이 진행됩니다.
'Study 공부할레나' 카테고리의 다른 글
| [스터디/밑시딥3] 제 4고지 신경망 만들기_43. 신경망 (2) | 2023.10.10 |
|---|---|
| [스터디/밑시딥3] 제 4고지 신경망 만들기_42. 선형 회귀 (1) | 2023.10.10 |
| [스터디/밑시딥3] 제 4고지 신경망 만들기_40. 브로드캐스트 함수 (1) | 2023.10.09 |
| [스터디/밑시딥3] 제 4고지 신경망 만들기_38. 형상 변환 함수 (1) | 2023.10.08 |
| [스터디/밑시딥3] 제 4고지 신경망 만들기_37. 텐서를 다루다 (1) | 2023.10.08 |