해결책은 간단합니다. 위 설명을 Variable 클래스의 코드에 그대로 반영하면 됩니다.
class Variable:
def __init__(self, data):
if data is not None:
if not isinstance(data, np.ndarray):
raise TypeError('{}은(는) 지원하지 않습니다.' .format(type(data)))
self.data = data
self.grad = None
self.creator = None
def set_creator(self, func):
self.creator = func
def backward(self):
if self.grad is None:
self.grad = np.ones_like(self.data)
funcs = [self.creator]
while funcs:
f = funcs.pop()
gys = [output.grad for output in f.outputs]
gxs = f.backward(*gys)
if not isinstance(gxs, tuple):
gxs = (gxs,)
for x, gx in zip(f.inputs, gxs):
if x.grad is None:
x.grad = gx
else:
x.grad = x.grad + gx
if x.creator is not None:
funcs.append(x.creator)
이와 같이 미분값(grad)을 처음 설정하는 경우에는 지금까지와 똑같이 출력 쪽에서 전해지는 미분값을 그대로 대입합니다. 그리고 그 다음번부터는 전달된 미분값을 '더해' 주도록 수정합니다.
앞의 코드에서 미분값을 더할 때 코드를 x.grad = x.gard + gx라고 썼습니다. 그 대신 복잡한 대입 연산자 +=을 사용하여 x.grad += gx 처럼 써도 좋을 것입니다. 그러나 이렇게 하면 문제가 되는 경우가 있습니다. 그 이유와 배경은 다소 복잡하고 딥러닝의 본질적인 문제에서도 벗어나기 때문에 부록 A에서 따로 설명했습니다. 관심 있는 분은 참고하세요.
이제 같은 변수를 반복해서 사용할 수 있습니다. 시험 삼아 앞에서 실패했던 계산에 다시 도전해보겠습니다.
x = Variable(np.array(3.0))
y = add(x, x)
y.backward()
print(x.grad)
2.0
이번에는 2.0이라는 올바른 결과를 얻었습니다. 그렇다면 x를 세 번 사용해도 여전히 잘 작동하느지 봅시다.
x = Variable(np.array(3.0))
y = add(add(x, x),x)
y.backward()
print(x.grad)
3.0
결과로 3.0을 얻었습니다. 수식으로 확인하면 y = x + x + x = 3x 이므로 미분하면 3이 나옵니다. 실행 결과와 일치하는군요. 이상으로 같은 변수를 반복 사용하기 위한 구현을 완성했습니다.
댓글 없음:
댓글 쓰기