역전파알고리즘은 1986년 데이비드 등이 개발한 알고리즘이다. 핵심은 "은닉 유닛(hidden unit)이 무엇을 해야하는지는 모르지만, 은닉층의 활성도를 바꿀때 얼마나 빨리 오차가 변하는지는 계산할 수 있다".

 

그림1. Simple neural network

 

반환되는 Outcome $\hat{y}$가 변화할 때, 오차율(E)가 얼마나 변화할 것인지를 다음과 같이 미분식을 이용해보자. 아랫첨자 j은 데이터포인트이다. 

$\frac{\delta E}{\delta W_{1}} = \frac{\delta E}{\delta o_{1}} \frac{\delta o_{1}}{\delta z_{1}} \frac{\delta z_{1}}{\delta_{W_{1}}}$

 

첫번째 곱인 $\frac{\delta E}{\delta o_{1}}$ 은 MSE와 구하는 공식이 같아서 구할 수 있고, 

두번쨰 곱인 시그모이드(sigmoid)함수의 미분은 $\sigma'(\cdot) = \sigma(\cdot)(1-\sigma(\cdot))$ 으로 구할 수 있다.

세번째 곱은 W와 H1의 곱이 Z1이기 때문에,  $\frac{\delta z_{1}}{\delta_{W_{1}}} = h_{1}$

 

이를 모두 곱해주면된다. 곱한 모든 식의 아래와 같이 업데이트하는 과정을 이어나가면 끝이다.

$W_{1}^{new} = W_{1} -\alpha \frac{\delta E}{\delta W_{1}}$

 

 

위와 같은 과정을 $\hat{y}$ 을 이전레이어의 출력값으로 변경해서 층마다 업데이트하면된다.

 

 

예제를 위해서, 아래의 간단한 MLP(Multi-layer perceptron)을 생성해보았다.

import tensorflow as tf
model = tf.keras.models.Sequential()
model.add(tf.keras.layers.InputLayer(input_shape=(100)))
model.add(tf.keras.layers.Dense(10))
model.add(tf.keras.layers.Dense(1, activation='sigmoid'))

model.compile(loss='binary_crossentropy')

model.summary()

 

그리고 랜덤으로 xs, ys을 만들어주고, 학습시켰다.

xs = tf.constant(tf.random.uniform(shape=(100, 10)))
ys = tf.round(tf.random.uniform(shape=(100, 1)))

model.fit(xs, ys)

 

다행히 tensorflow2.x 은 역전파알고리즘을 tf.Gradient 객체로 한번에 구할 수 있게 만들어주어, 이를 사용하면된다.

with tf.GradientTape(persistent=True) as tape:
    tape.watch(xs)
    w = model.trainable_weights
    ys = model(xs)
    
    
dE_dW = tape.gradient(ys, w)

 

아래의 gradient descent방법과 같이 update을 해주면된다.

lr = 0.005
Ws = model.trainable_weights

for W, grad in zip(Ws, dE_dW):
    W = W - (lr * grad)

 

 

추가적으로 matrix derivation을 직접해보는경우 아래와같이 matrix shape이 안맞는 경우가 발생한다. 필자도 이 떄문에 한 일주일을 낭비했다..

 

마찬가지로, 우리가 구하고싶은것은 dE/dW 이므로, 아래와 같다.

 

 

https://medium.com/jun-devpblog/dl-3-backpropagation-98206058d72e

 

[DL] 3. Backpropagation

1. Error Backpropagation

medium.com

https://souryadey.github.io/teaching/material/Matrix_Calculus.pdf

반응형

+ Recent posts