페이지

2022년 8월 13일 토요일

10.3 기울기 확인을 이용한 자동 테스트

 앞 절에서 역전파 테스트를 작성하여 미분의 기댓값을 손으로 계산해 입력했습니다. 사실 이부분을 자동화할 방법이 있습니다. 바로 기울기 확인(gradient checking)이라는 방법이죠, 기울기 확인이란 수치 미분으로 구한 결과와 역전파로 구한 결과를 비교하여 그 차이가 크면 역전파 구현에 문제가 있다고 판단하는 검증 기법입니다.

우리는 4단계에서 수치 미분을 구현했습니다. 수치 미분은 쉽게 구현할 수 있고 거의 정확한 미분값을 내줍니다. 따라서 수치미분의 결과와 비교하면 역전파를 정확히 구현했는지 검증할 수 있습니다.

기울기 확인은(기댓값을 몰라도) 입력값만 준비하면 되므로 테스트 효율을 높여줍니다. 그러니 우리 테스트에서도 기울기 확인을 이용하겠습니다. 4단계에서 구현한 numerical_diff 함수를 사용하면 되겠군요. 복습도 겸해서 이 함수의 코드까지 함깨 보여드리겠습니다.


def numerical_diff(fxeps=1e-4):
  x0 = Variable(x.data - eps)
  x1 = Variable(x.data + eps)
  y0 = f(x0)
  y1 = f(x1)
  return (y1.data - y0.data)/(2 * eps)

class SquareTest(unittest.TestCase):

  def test_forward(self):
    x = Variable(np.array(2.0))
    y = square(x)
    expected = np.array(4.0)
    self.assertEqual(y.data, expected)


  def test_backward(self):
    x = Variable(np.array(3.0))
    y = square(x)
    y.backward()
    expected = np.array(6.0)
    self.assertEqual(x.grad, expected)
  
  def test_gradient_check(self):
    x = Variable(np.random.rand(1)) # 무작위 입력값 생성
    y = square(x)
    y.backward()
    num_grad = numerical_diff(square, x)
    flg = np.allclose(x.grad, num_grad)
    self.assertTrue(flg)
    
if __name__ == '__main__':
    unittest.main(argv=['first-arg-is-ignored'], exit=False)


기울기 확인을 할 test_gradient_check메서드 안에서 무작위 입력값을 하나 생성합니다. 이어서 역전파로 미분값을 구하고, numerical_diff 함수를 사용해서 수치 미분으로도 계산해봅니다. 그런 다음 두 메서드로 각각 구한 값들이 거의 일치하는지 확인합니다. 이때 np.allclose라는 넘파이 함수를 이용합니다.

np.allclose(a,b)는 ndarray 인스턴스인 a 와 b의 값이 가까운지(close)판정합니다. 얼마나 가까워야 가까운 것인지는 np.allclose(a, b, rtol=1e-08)과 같이 인수 rtol과 atol로 지정할 수 있습니다. 이 함수는 a와 b의 오든 요소가 다음 조건을 만족하면 True를 반환합니다.

[a - b] <= (atol + rtol * |b|)

한편 기울기 확인을 하는 대상의 계산(함수)에 따라 atol과 rtol의 값을 미세하게 조정해야 할 수도 있습니다. 기준을 정하는데는 참고 문헌[5]등의 도움이 됩니다. 그럼 이상의 이루기 확인을 위 코드에 추가하고 테스트를 돌려봅시다. 이번에 얻은 결과는 다음과 같습니다.

---------------------------------------------------------------------- Ran 3 tests in 0.010s

이와 같이 기울기 홗인을 이용하면 미분을 자동으로 계산하는 딥러닝 프레임워크를 반자동으로 테스트할 수 있고, 덕분에 더 체계적으로 더 넓은 범위를 검증하는 테스트 케이스를 만들 수 있습니다.


댓글 없음: