페이지

2022년 8월 19일 금요일

14.2 해결책

 해결책은 간단합니다. 위 설명을 Variable 클래스의 코드에 그대로 반영하면 됩니다.

class Variable:

  def __init__(selfdata):
    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(selffunc):
    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이 나옵니다. 실행 결과와 일치하는군요. 이상으로 같은 변수를 반복 사용하기 위한 구현을 완성했습니다.

댓글 없음: