순전파(Foward)와 역전파(Backward)를 코드로 구현해보자.
각 Layer는 클래스로 구현 후, 변수를 인스턴스화 하여 Foward 된 신호를 저장 후, 역전파에서 해당 신호를 활용하도록 한다.
class MulLayer:
def __init__(self): # initialize x and y
self.x = None
self.y = None
def foward(self, x, y):
self.x = x
self.y = y
out = x * y
return out
def backward(self, dout):
dx = dout * self.y # 곱셈 노드에서 역전파는 x 와 y를 스위칭 하여 이전 입력 신호에 곱하여 다음 노드로 전달 한다.
dy = dout * self.x
return dx, dy
사과 계산그래프의 각 노드에 대한 순전파 / 역전파 코드를 구현한다.
apple = 100 # 사과 가격
apple_num = 2 # 개수
tax = 1.1 # 소비세
# Layer
mul_apple_layer = MulLayer() # 순전파 / 역전파 계층 인스턴스화
mul_tax_layer = MulLayer()
# foward
apple_price = mul_apple_layer.foward(apple,apple_num) # 사과 가격을 구하기 위한 순전파
price = mul_tax_layer.foward(apple_price, tax) # 소비세를 고려한 최종 가격
print(price)
# backward
dprice = 1 # 전달할 미분값 dz/dz = 1
dapple_price, dtax = mul_tax_layer.backward(dprice) # 곱에 대한 역전파 신호는 x 와 y가 스위칭.
print("dapple_price: {0} \ndtax: {1}".format(dapple_price, dtax))
dapple, dapple_num = mul_apple_layer.backward(dapple_price)
print("dapple: {0} \ndapple_num: {1}".format(dapple,dapple_num))
최종 가격과, 역전파후 값들에 대해 출력하면 다음과 같다.
220.0000000000000
dapple_price: 1.1
dtax: 200
dapple: 2.2
dapple_num: 110.00000000000001
Add 계층은 단순하다. 단순히 입력신호를 다음 노드로 전달한다.
class AddLayer:
def __init__(self):
pass
def foward(self, x,y):
out = x + y
return out
def backward(self, dout):
dx = dout * 1
dy = dout * 1
return dx, dy
사과가격을 계산 하기위한 계산 그래프 구현해 보았으니, 이를 응용하여 사과와 오렌지 가격 계산을 위한 계산 그래프를 구현 해보자.
각 연산 노드 (곱셈 및 덧셈)노드는 클래스로 선언한, MulLayer
AddLayer
를 사용한다.
apple = 100
apple_num = 2
orange = 150
orange_num = 3
tax = 1.1
# layers
mul_apple_layer = MulLayer()
mul_orange_layer = MulLayer()
add_apple_orange_layer = AddLayer()
mul_tax_layer = MulLayer()
# foward
apple_price = mul_apple_layer.foward(apple, apple_num) # Apple price without tax
orange_price = mul_orange_layer.foward(orange, orange_num) # Orange price without tax
all_price = add_apple_orange_layer.foward(apple_price, orange_price) # price including tax
price = mul_tax_layer.foward(all_price, tax) # Final Output
# backward
d_price = 1 # dz / dz = 1
d_all_price, d_tax= mul_tax_layer.backward(d_price) # x = y, y = x 스위치
print(d_all_price, d_tax)
d_apple_add_price, d_orange_add_price = add_apple_orange_layer.backward(d_all_price)
print(d_apple_add_price, d_orange_add_price)
d_apple_price, d_apple_num = mul_apple_layer.backward(d_apple_add_price)
print(d_apple_price, d_apple_num)
d_orange_price, d_orange_num = mul_orange_layer.backward(d_orange_add_price)
print(d_orange_price, d_orange_num)
계산결과는 다음과 같다.
1.1 650
1.1 1.1
2.2 110.00000000000001
3.3000000000000003 165.0