프로필사진

IT Anthology/encyclopedia

[밑러닝] 파이썬으로 간단한 계층(덧셈 노드/곱셈 노드)에서의 역전파 구현하기

다각 2020. 3. 29. 18:47

* 이 글은 <밑바닥부터 시작하는 딥러닝2 (저자: 사이토 고키)> 책을 읽으며 정리한 글입니다.
* 나중에라도 제가 참고하기 위해 정리해 두었으며, 모든 내용을 적은 것이 아닌,
필요하다고 생각되는 부분만 추려서 정리한 것임을 미리 밝힙니다.


목차

  1. 덧셈 노드에서의 역전파 구현
  2. 곱셈 노드에서의 역전파 구현
  3. 사과 둘, 귤 셋

앞서 '오차역전파(backward propagation of error)'에 대한 개념에 대해 익혔다. 이번 글에서는 오차역전파가 파이썬으로 어떻게 구현되는지 살펴 보겠다. 오차역전파에 대한 개념이 아직도 아리까리한 사람들은 후딱 이전 글을 보고 오자.

 

2020/03/29 - 이보다 더 쉬울 수는 없다! 오차역전파(back-propagation)법 완벽 파헤치기

 

시작하기에 앞서, 순전파를 처리하는 함수는 forward()라는 이름으로, 역전파를 처리하는 함수는 backward()라는 이름으로 만들어보기로 한다.


1. 덧셈 노드에서의 역전파 구현

$z = x+y$일 때 덧셈 노드에서의 역전파를 살펴보도록 하자. 덧셈 노드에서의 역전파는 뒤에서 들어온 미분값을 그대로 흘려보내는 특징이 있다. 즉, 다음과 같이 구현할 수 있다.

class AddLayer:
    def __init__(self):
        pass
    def forward(self, x, y):
        return x + y
    def backward(self, d_out):
        dx = d_out
        dy = d_out
        return dx, dy

dx = d_outdy = d_out이라고 표기하긴 했지만, 실제로는 * 1이 그 뒤에 생략되어 있었음을 잊지 말자. (dx = dout * 1, dy = dout * 1)

 

2. 곱셈 노드에서의 역전파 구현

$ z= xy$일 때 곱셈 노드에서의 역전파를 구현해보도록 하자. 덧셈 노드와는 달리, $x$값과 $y$값이 역전파 계산 때 사용된다. 따라서 __init__()함수에서 x와 y의 변수를 선언해, 이 값들을 저장할 공간을 만들어주자. 파이썬으로 구현하면 다음과 같다.

class MulLayer:
    def __init__(self):
        self.x = None
        self.y = None
    def forward(self, x, y):
        self.x = x
        self.y = y
        return x * y
    def backward(self, d_out):
        dx = d_out * self.y
        dy = d_out * self.x
        return dx, dy

 

3. 사과 둘, 귤 셋

위에서 구현한 덧셈 노드에서의 역전파와 곱셈 노드에서의 역전파 코드를 활용해 조금 더 복잡한 역전파를 구현해보도록 하자. 앞선 포스팅에서 사과 2개와 귤 3개를 살 때의 총액을 구하는 계산을 한 적이 있다. 다음과 같이 말이다.

위에 쓴 '덧셈에 대한 역전파 코드'와 '곱셈에 대한 역전파 코드'를 활용하여 사과 둘 귤 셋의 순전파와 역전파를 계산하는 코드를 구현해 보자.

apple = 100
n_apple = 2
tangerine = 150
n_tangerine = 3
tax = 1.1

# 계산 그래프의 노드 생성
mul_app = MulLayer()
mul_tan = MulLayer()
add_app_tan = AddLayer()
mul_tax = MulLayer()

# 순전파(forward propagation)
app_price = mul_app.forward(apple, n_apple)
tan_price = mul_tan.forward(tangerine, n_tangerine)
all_price = add_app_tan.forward(app_price, tan_price)
final_price = mul_tax.forward(all_price, tax)

# 역전파(backward propagation)
d_fin = 1
d_all, d_tax = mul_tax.backward(d_fin)
d_app_price, d_tan_price = add_app_tan.backward(d_all)
d_tan, d_n_tan = mul_tan.backward(d_tan_price)
d_app, d_n_app = mul_app.backward(d_app_price)

# 결과 출력
print('현재 사과 2개와 귤 3개를 구매하기 위해서 {}원 지불해야 합니다.'.format(final_price))
print('사과 가격이 1원 오를 때마다 같은 구성으로 구매하기 위해서 {}원씩 더 내야 합니다.'.format(d_app))
print('귤 가격이 1원 오를 때마다 같은 구성으로 구매하기 위해서 {}원씩 더 내야 합니다.'.format(d_tan))
print('세금 가격이 1(100%) 오를 때마다 같은 구성으로 구매하기 위해서 {}원씩 더 내야 합니다.'.format(d_tax))

위의 코드를 실행시키면 다음과 같이 출력된다.

세금의 어마어마한 영향력을 확인할 수 있다!! (곱셈이니까 그럴 수밖에..)

 


 

정리

이렇게 열심히 배운 역전파, 머신러닝 실전에서 쓰면 어떨까?

바로 이어서 다음 포스팅에서 활성화함수 계층의 역전파를 파이썬으로 구현해보도록 하자.