딥러닝 역전파 수식 행렬의 전치(Transpose) 기준?
Backpropagation을 직접 구현하는 과정에서 이유 없이 갑자기 발생하는 행렬 전치(Transpose)와 관련된 의문점이 오랜 기간 절 괴롭혔습니다. Backpropagation을 하기 위해서 Cost Function을 해당 계층의 W(가중치)로 편미분 한 후, 현재 W를 수정하는 수식을 유도하는 과정에서 일부 행렬이 전치행렬로 갑자기 변경됩니다. 문제는 제가 행렬이 전치(Transpose)되는 근거와 기준을 이해할 수가 없다는 것입니다. 딥러닝 책이나 웹 문서를 찾아보면 “편미분 과정에서 적당히 행렬을 맞춰준다.“라는 표현으로 이 부분을 설명합니다. 제가 찾고 싶었던 답은 Backpropagation 미분 과정에서 행렬의 방향성(Transpose 할 것이나 말 것이냐)은 어떻게 결정되는가입니다. 사실 이런 문제는 제가 수포자이기 때문에 발생하는 문제였고, 결론은 정말 간단한 것이었습니다. 이 부분을 기록 차원에서 정리해 보겠습니다.
문제: 행렬의 Transpose 왜 발생?
예제로 사용하기 위한 간단한 네트워크를 다음과 같이 정리하겠습니다. 문제를 단순화하기 위해서 가장 가난한 형태로 네트워크를 이용합니다.
- Layer: 2
- Input Feature: 2
- Network Type: Logistic Regression(Binary Classification, 이진 분류)
- Activation Function: sigmoid
- cost function: Mean Square Error(MSE)
예제로 사용할 신경망은 <그림 1>과 같습니다.
<그림 1> 네트워크에서 두 번째 레이어의 Weight($W^{[2]}$)가 오차에 미치는 영향을 알아보고, Layer 2의 $W^{[2]}$를 업데이트하는 식을 유도해 보겠습니다.
사전 준비
본론으로 들어가기 전에 앞으로 사용할 몇 가지 공식을 사전에 정리하겠습니다.
- <식 1>. forward propagation 주요 공식 정리 $$ \begin{align} A^{[0]} & = Input Feature & (1) \\
Z^{[1]} & = W^{[1]}A^{[0]} & (2) \\
A^{[1]} & = g(Z^{[1]}) & (3) \\
Z^{[2]} & = W^{[2]}A^{[1]} & (4) \\
A^{[2]} & = g(Z^{[2]}) & (5) \end{align} $$
- 입력 데이터(Input Feature)
- Layer1의 Weighted Sum (Input X W1)
- Layer1의 출력
- Layer2의 Weighted Sum (Layer 1의 출력 X W2)
- Layer1의 출력
Cost 편미분을 위한 주요 공식을 먼저 다음 <식2> 에서 정리합니다.
- <식 2>. Forward propagation 주요 공식 정리 $$ \begin{align} Cost & = \frac{1}{2}(\hat{Y}-Y)^2 & (1)\\
\frac{\partial Cost}{\partial A^{[2]}} & = \hat{Y}-Y & (2)\\\
sigmoid(Z^{[l]]}) & = sigmoid(Z^{[l]]})(1-sigmoid(Z^{[l]]})) & (3)\\
& = A^{[l]}(1-A^{[l]}) \\
\frac{\partial Z^{[l]}}{\partial W^{[2]}} & = \frac{\partial A^{[l-1]}W^{[l]}}{\partial W^{[l]}} = A^{[l-1]} & (4) \\\
\end{align} $$
- MSE(Mean Squre Error)로 계산한 오차
- $\hat{Y}$: Layer 2의 출력
- Y: 입력 데이터의 label
- Cost를 Layer 2의 출력으로: Layer 2의 출력이 오차에 미치는 영향
- 활성 함수 미분 결과
- Weighted Sum에 Weight가 미치는 영향
Layer 2의 $\Delta W^{[2]}$ 계산
현재 목표는 $\Delta W^{[2]}$를 계산하여 다음 공식을 완성하고 $W^{[2]}$를 업데이트하는 것입니다.
- <식 3>. Layer 2의 W 업데이트 $$ \begin{align} W^{[2]} &= W^{[2]} - \alpha\Delta W^{[2]} \\
&= W^{[2]} - \alpha \frac{\partial Cost}{\partial W^{[2]}} \end{align} $$
<식 3>을 완성하기 위해서는 Cost를 Layer 2 W로 미분하여, 이 W가 Cost에 미치는 영향을 파악해야 합니다. 다음과 같은 과정을 통해서 <식 3>을 완성할 수 있습니다.
- <식 4>. Layer 2의 W 업데이트 식 유도 $$ \begin{align} \Delta W^{[2]} & = \frac{\partial Cost}{\partial W^{[2]}} \\
& = \frac{\partial Cost}{\partial A^{[2]}}\frac{\partial A^{[2]}}{\partial W^{[2]}} \\
& = \frac{\partial Cost}{\partial A^{[2]}}\frac{\partial A^{[2]}}{\partial Z^{[2]}}\frac{\partial Z^{[2]}}{\partial W^{[2]}} \\
& = (\hat{y}-y)\frac{\partial A^{[2]}}{\partial Z^{[2]}}\frac{\partial Z^{[2]}}{\partial W^{[2]}} \\
& = (\hat{y}-y)g’(z^{[2]})\frac{\partial Z^{[2]}}{\partial W^{[2]}} \\
& = (\hat{y}-y)sigmoid’(z^{[2]})\frac{\partial Z^{[2]}}{\partial W^{[2]}} \\
& = (\hat{y}-y)A^{[2]}(1-A^{[2]})\frac{\partial Z^{[2]}}{\partial W^{[2]}} \\
& = (\hat{y}-y)A^{[2]}(1-A^{[2]})A^{[1]} \end{align} $$
<식 4>의 최종 결과는 <식 5>와 같이 정리됩니다.
- <식 5>. Layer 2의 W 업데이트 최종 식 $$ \begin{align} \Delta W^{[2]} & = (\hat{y}-y)A^{[2]}\odot(1-A^{[2]})A^{[1]T} \end{align} $$
최종 결과인 <식 5>를 보면 마지막 $A^{[1]}$이 $A^{[1]T}$로 변환되어 있는 것을 확인할 수 있습니다.
Backpropagation이 식으로 유도하는 과정에서 부분적으로 행렬이 전치행렬로 변환되는 것을 볼 수 있습니다. 딥러닝 책이나 웹 문서를 보면 이 부분을 다음과 같이 설명하고 있습니다.
앞뒤 상황에 따라서 행렬의 shape을 적당히 맞춰준다.
왜 $A^{[1]}$ 행렬이 전치(Transpose)되는 것까요? Backpropagation을 구하는 과정에서 행렬의 전치(Transpose)는 어떤 기준으로 해야 하는 걸까요?
Backpropagation 중 이전 레이어 출력의 전치?
이제부터 cost 함수 미분 과정에서 앞 계층의 출력을 전치(Transpose)하는 이유에 대해서 살펴보겠습니다.
Step 1: W 요소 단위로 업데이트 공식 분해
<식 5>는 행렬 단위로 Layer 2의 W 행렬이 Cost(오차)에 미치는 영향도를 알아봤습니다. 이 영향도를 세분하여 Layer 2의 W 행렬의 요소 단위로 접근해 보겠습니다.
- <식 6>. Layer 2의 W11 업데이트 식 유도 $$ \begin{align} \Delta w^{[2]}11 & = \frac{\partial Cost}{\partial w^{[2]}11} \\
& = \frac{\partial Cost}{\partial a^{[2]}_1}\frac{\partial a^{[2]}_1}{\partial z^{[2]}_1}\frac{\partial z^{[2]}_1}{\partial w^{[2]}11} \\
& = (\hat{y}-y)\frac{\partial a^{[2]}_1}{\partial z^{[2]}_1}\frac{\partial z^{[2]}_1}{\partial w^{[2]}11} \\
& = (\hat{y}-y)g’(z^{[2]}_1)\frac{\partial z^{[2]}_1}{\partial w^{[2]}11} \\
& = (\hat{y}-y)sigmoid’(z^{[2]}_1)\frac{\partial z^{[2]}_1}{\partial w^{[2]}11} \\
& = (\hat{y}-y)a^{[2]}_1(1-a^{[2]}_1)\frac{\partial z^{[2]}11}{\partial w^{[2]}11} \\
& = (\hat{y}-y)a^{[2]}_1(1-a^{[2]}_1)a^{[1]}1 \end{align} $$
<식 6>을 다음과 같이 정리할 수 있습니다.
- <식 7>. Layer 2의 W11 업데이트 최종 결과 $$ \begin{align} \Delta w^{[2]}11 & = (\hat{y}-y)a^{[2]}_1(1-a^{[2]}_1)a^{[1]}_1 \end{align} $$
<그림 3>와 같이 Layer 2의 w12가 Cost에 미치는 영향도는 <식 7>을 참조하여 다음과 같이 정리할 수 있습니다.
- <식 8>. Layer 2의 W12 업데이트 최종 결과 $$ \begin{align} \Delta w^{[2]}12 & = (\hat{y}-y)a^{[2]}_1(1-a^{[2]}_1)a^{[1]}_2 \end{align} $$
Step 2: $\Delta W^{[2]}$ 정리
<식 7>과 <식 8>의 수식을 $W^{[2]}$ 같은 Shape을 갖는 $\Delta W^{[2]}$ 행렬로 정리하면 사용하기 편리할 것 같습니다. <식 7>과 <식 8>의 두 수식을 Shape이 (1, 2)인 행렬로 정리하는 절차는 다음과 같습니다.
- <식 9> Delta W 식 정리 $$ \begin{align} \Delta W^{[2]} & = \begin{bmatrix} \Delta w^{[1]}11 & \Delta w^{[1]}12 \\
\end{bmatrix} \\
& =\begin{bmatrix} (\hat{y}-y)a^{[2]}_1(1-a^{[2]}_1)a^{[1]}_1 & (\hat{y}-y)a^{[2]}_1(1-a^{[2]}_1)a^{[1]}_2 \\
\end{bmatrix} \\
& =(\hat{y}-y)a^{[2]}_1(1-a^{[2]}_1) \begin{bmatrix} a^{[1]}_1 & a^{[1]}_2 \\
\end{bmatrix} \end{align} $$
<식 9>에서 마지막 두 개 요소를 갖는 (1, 2) 형태의 행렬을 다음과 같이 정리할 수 있습니다.
- <식 10> Delta W 식 정리 $$ \begin{bmatrix} a^{[1]}_1 & a^{[1]}_2 \\
\end{bmatrix} = A^{[1]T} $$
<식 10>의 정리를 이용하여 마지막 행렬을 $A^{[1]T}$로 치환하면 최종 식을 <식 11>과 같이 정리할 수 있습니다.
- <식 11> Delta W 식 정리 $$ \Delta W^{[2]} = (\hat{y}-y)a^{[2]}_1(1-a^{[2]}_1)A^{[1]T} $$
<식 11>는 결과적으로 <식 5>와 동일한 수식임을 알 수 있습니다. 행렬이 포함된 Cost 함수를 W로 미분한 결과와 W의 개별 요소로 Cost 함수를 미분한 후 개별 수식을 행렬로 정리한 결과가 같음을 확인할 수 있습니다.
행렬이 전치되는 이유는 행렬을 미분한 결과가 아니다.
처음에 제가 의문을 가졌던 부분은 Cost를 W로 미분하는 과정에서 행렬이 전치 기준이었습니다. 행렬이 포함된 식을 미분하는 과정에서 특정 행렬이 전치되는 기준과 이유를 명확히 하는 것 있습니다.
결과적으로 행렬을 미분하는 과정에서 행렬이 전치되는 것이 아니라, 각 W의 요소를 미분하고 그 결과 “수식을 선형대수의 행렬로 단순화하는 과정에서 행렬의 Shape이 결정된다“가 결론입니다.
행렬은 여러개의 연산을 한번에 표기하고 처리할 수 있는 수학적 툴입니다. 따라서 각 요소가 수행되는 반복적인 계산을 하나의 표기법으로 처리하고 연산할 수 있는 방식을 제공하는 것이 선형대수의 역할입니다.
처음 제 질문은 결과적으로 잘못된 것이었습니다. 미분 과정에서 행렬이 전치되는 것이 아니라, 각 요소의 연산을 선형대수화하는 과정에서 행렬의 shape이 결정되고 전치되는 것이었습니다.
위에서 언급한 것처럼 책에서 다음과 같은 문자을 볼 때는 성의 없는 표현이라고 넘어갔습니다.
앞뒤 상황에 따라서 행렬의 shape을 적당히 맞춰준다.
결과적으로 이 표현은 매우 적합한 표현입니다. 선형대수로 표현된 수식을 개별 요소로 분해하여 처리하는 것은 비효율적이며, 행렬 자체로 수식을 전계 하는 것이 맞습니다. 행렬을 적용하거나 최종 목적 행렬의 shape과 다를 경우에 행렬을 전치하여 shape을 맞추면 됩니다.
행렬의 Shape이 변경되는 유형은 크게 두 가지 인 것 같습니다.
- 행렬 곱: Weight Sum처럼 $\sum$을 이용하여 합산하는 것을 행렬곱으로 처리하는 경우
- Case 1: Weight Sum - $\sum_j\sum_i w_jix_i = WX$
- Case 2: L2 Norm - $||X||_2 = \sum x_i^2 = X^TX$
- 목적 행렬의 Shape
- 목적 행렬의 Shape에 현재 행렬의 Shape을 맞춤
결과적으로 앞뒤 상황에 따라서 행렬의 shape을 적당히 맞춰는 과정입니다.
결론: 수학에 대한 이미지
수학적 감각이 떨어지는 수포자로서, 이 문제를 고민하면서 두 가지를 느꼈습니다.
- 수학의 수식은 복잡한 개념은 단순화 시키고 커뮤니케이션하기 위한 표기법이다.
- 단순화 시키는 과정에서 대수학과 선형대수가 사용된다.
초기에 “내가 행렬의 방향을 이해하지 못하는 것은 미분을 잘 몰라서이며, 미분에 행렬의 방향을 결정하는 무엇인가가 있을 것이다.“라는 생각은 잘못된 것이었습니다. 행렬 변환은 식을 단순하게 만들기 위해서 선형대수화하는 과정에서 만들어진 것이었습니다.
수식에 대한 행렬의 변환에 확신이 없을 경우, 개별 요소로 수식 유도 후 행렬로 변환해 보면 명확할 것 같습니다. 이걸 이해하는데 두 달이 걸렸네요. 확실히 수학의 수식은 대화하고 개념을 단순화시키는 표기법인것 같습니다.