7. 역전파(Back propagation)
지난 시간에 사용한 인공 신경망입니다.
Layer 1
g1 weight = (2, -2, 0) g2 weight = (1, 3, -1)
g1 = x1*w11(1) + x2*w12(1) + x3*w13(1)
g2 = x1*w21(1) + x2*w22(1) + x3*w23(1)
s1 = sigmoid(g1)
s2 = sigmoid(g2)
Layer 2
f weight = (3, -2, -1)
g3 = s1*w1(2) + s2*w2(2) + s3*w3(2)
f = sigmoid(g3)
x1 | x2 | g1 | g2 | f | y |
0 | 0 | (2*0) + (-2*0) +(0*1) = 0 sigmoid(0) = 0.5 | (1*0) + (3*0) + (-1*1) = -1 sigmoid(-1) = 0.269 | (3*0.5) + (-2*0.269) + (-1*1) = -0.038 sigmoid(-0.038) = 0.491 | 1 |
0 | 1 | (2*0) + (-2*1) + (0*1) = -2 sigmoid(-2) = 0.119 | (1*0) + (3*1) + (-1*1) = 2 sigmoid(2) = 0.881 | (3*0.119) + (-2*0.881) + (-1*1) = -2.405 sigmoid(-2.405) = 0.083 | 0 |
1 | 0 | (2*1) + (-2*0) + (0*1) = 2 sigmoid(2) = 0.881 | (1*1) + (3*0) + (-1*1) = 0 sigmoid(0) = 0.5 | (3*0.881) + (-2*0.5) + (-1*1) = 0.643 sigmoid(0.643) = 0.655 | 0 |
1 | 1 | (2*1) + (-2*1) + (0*1) = 0 sigmoid(0) = 0.5 | (1*1) + (3*1) + (-1*1) = 3 sigmoid(3) = 0.953 | (3*0.5) + (-2*0.953) + (-1*1) = -1.406 sigmoid(-1.406) = 0.197 | 1 |
이런 결과가 나왔었습니다. 그러면 본격적으로 Cost를 줄이기 위한 Weight 조절에 들어가 보겠습니다. 우선 Cost function을 정의해보자면 ε = (y – f )2로 하겠습니다.(실제값과 예측값의 차이 제곱) 이때, error값을 Weight에 대해 편미분 하면 ∇Wε≡ ∂ε/∂W가 되겠죠. 왜 편미분 하는지는 https://godute.tistory.com/40 를 봐주시면 감사하겠습니다.
2. 경사 하강법(Gradient Descent), Tensorflow 선형 회귀 구현
이전 포스트에서 이어집니다. 선형 회귀 보러 가기 https://godute.tistory.com/39 위 그림은, 이전에 임의로 지었던 가설의 예측값과 실제 값의 차이를 나타낸 그래프입니다. 가설의 가중치 W를 9/5로 설정했을..
godute.tistory.com
경사 하강법으로 W에 대해 함수를 미분해 값이 감소하는 방향으로 가야 하기 때문입니다.
W← W+c1(−∇Wε) 우린 이 식을 이용해 W를 업데이트할 수 있습니다. 의미는 Error가 감소하도록 W를 업데이트해주겠다~~~ 입니다.
역전파를 이용하면, 저 복잡해 보이는 계산을 chain rule로 해결할 수 있습니다. 천천히 해볼까요?
ε = (y – f )^2 => ∂ε/∂f = -2(y-f)
s = W·X => ∂s/∂W = X
f = sigmoid(s) => ∂f/∂s = f(1-f) //계산 과정은 생략했습니다.
∂ε/∂W = (∂ε/∂f)·(∂f/∂W)
= (∂ε/∂f)·(∂f/∂s)·(∂s/∂W)
= -2(y-f)·f·(1-f)·X
-∂ε/∂W = (y-f)·f·(1-f)·X
W ← W + c·(y-f)·f·(1-f)·X (c는 양의 상수) //이 식을 각 신경망 노드에 적용하면,
Wi(j) ← Wi(j) + ci(j)·δi(j)·X(j-1)
δ = (y-f)·f(1-f)
// j번째 Layer의 i번째 Weight에 영향을 주는 것들. 여기서 δ는 j번째 Layer의 i번째 ∂ε/∂W를 의미합니다.
Wi(j) ← Wi(j) + ci(j)·(yi(j) - fi(j))·fi(j)·(1-fi(j))·X(j-1)
차례대로 값을 집어넣어 보겠습니다.
x1 = 1, x2 = 0인 경우
Layer 2 (Final Layer), 먼저 최종 레이어부터 δ를 계산
δ(2) = (y-f)·f·(1-f) //최종 δ에 영향을 주는 건, 하나의 output 뿐입니다.
δ(2) = (1 - 0.655)·0.655·(1-0.655) = -0.148
Layer 1 (Hidden Layer), 최종에서부터 Input을 향해 Back
δ1(1) = s1·(1-s1)·(δ(2)·W) //바로 다음 Layer의 총 δ·W. 여기선 Final Layer. 다음 층에서 Input으로 연결되는 노드가 많으면, 해당 값을 다 더하면 됩니다.)
δ1(1) = 0.881·(1-0.881)·(-0.148)·(3) //최종 Layer의 weight (3, -2, -1)
= -0.047
δ2(1) = s2·(1-s2)·(δ(2)·W)
δ2(1) = 0.5·(1-0.5)·(-0.148)·(-2) //weight (3, -2, -1)
= 0.074
Weight Update
Wi(j) ← Wi(j) + ci(j)·δi(j)·X(j-1) //c = 1
W(2) ← W(2) + δ(2)·X(1) = (3, -2, -1) + (-0.148)·(0.881, 0.5, 1) = (2.87, -2.074, -1.148)
W1(1) ← W1(1) + δ1(1)·X(0) = (2, -2, 0) + (-0.047)(1, 0 ,1) = (1.953, -2, -0.047)
W2(1) ← W2(1) + δ2(1)·X(0) = (1, 3, -1) + (0.074)(1, 0 ,1) = (1.074, 3, -0.926)
이렇게 역전파를 이용해 Weight를 조정해봤습니다. 어렵네요