최적화란 어떤 함수가 주어졌을 때 그 최솟값(또는 최대값)을 반환하는 '입력(함수의 인수)'을 찾는 일이다. 신경망 학습의 목표도 손실 함수의 출력을 최소화하는 매개변수를 찾는 것이니 최적화 문제에 속한다.
- 로젠블록 함수
이번에는 로젠블록 함수의 출력이 최소가 되는 x0와 x1을 찾을 것이다. 답부터 말하면 (x0,x1)=(1,1)이다.
- 미분 계산
가장 먼저 로젠블록 함수의 (x0,x1)=(0.0, 2.0)에서의 미분을 계산해 보자.
def rosenbrock(x0,x1):
y=100*(x1-x0 **2) **2 + (1-x0) ** 2
return y
이 코드를 실행하면 x0와 x1의 미분을 각각 -2.0과 400.0이라고 나온다. 이때 두 미분값을 모은 값, 즉 (-2.0, 400.0) 벡터를 기울기(gradient) 혹은 기울기 벡터라고 한다. 기울기는 각 지점에서 함수의 출력을 가장 크게 하는 방향을 가리킨다. 지금 위의 예에서는 (x0,x1)=(0.0,2.0)지점에서 y값을 가장 크게 늘려주는 방향이 (-2.0, 400.0)이라는 의미이다. 반대로 기울기에 마이너스를 곱한 (2.0, -400.0) 방향은 y값을 가장 작게 줄여주는 방향을 뜻한다.
- 경사하강법 구현
복잡한 형상의 함수라면 기울기가 가리키는 방향에 반드시 최대값이 존재한다고는 볼 수 없다(마찬가지로 반대 방향에 최솟값이 존재한다고 볼 수도 없다). 그러나 국소적으로 보면 기울기는 함수의 출력을 가장 크게 하는 방향을 나타낸다. 그래서 기울기 방향으로 일정거리만큼 이동하여 다시 기울기를 구한느 작업을 반복하면 점차 원하는 지점에 접근하리라 기대할 수 있다. 이것이 경사하강법이다.
그렇다면 로젠블록 함수의 최솟값을 우리의 Dezero를 통해 구해보자.
X0=Variable(np.array(0.0))
x1=Variable(np.array(2.0))
lr=0.001
iters=50000
for i in range(iters):
print(x0,x1)
y=rosenbrock(x0,x1)
x0.cleargrad()
x1.cleargrad()
y.backward()
x0.data -= lr * x0.grad
x1.data -= lr * x1.grad
출발점 (0.0, 2.0)에서 시작하여 위치가 계속 갱신되는 모습을 볼 수 있다. 다음 그림은 이 결과를 플롯한 모습이다.
iters=50000으로 설정해 실행하면 실제로 (1.0,1.0) 위치에 간신히 도착한다.
위의 결과들을 통해 경사하강법은 일반적으로 수렴이 느리다는 단점이 있다.
경사하강법을 대체할 수 있는, 수렴이 더 빠른 방법은 여러 가지가 있다. 그중에서 유명한 것이 뉴턴 방법이다. 뉴턴 방법으로 최적화하면 더 적은 단계로 최적의 결과를 얻을 가능성이 높아진다.
- 뉴턴 방법을 활용한 최적화 이론
이번에는 뉴턴 방법을 활용해 최적화를 구현할 것이다. 경사하강법 대신 뉴턴 방법을 사용하여 실제로 더 빨리 수렴하는지 확인할 것이다.
아래는 뉴턴 방법의 원리에 대한 설명이다.
결론적으로 뉴턴 방법을 활용한 최적화는 2차 미분의 정보도 이용한다. 뉴턴 방법은 추가된 2차 미분 정보 덕에 효율적인 탐색을 기대할 수 있으며, 결과적으로 목적지에 더 빨리 도달할 확률이 커진다.
이제 y=x^4 - 2x^2 수식을 최적화 해보겠다. 초깃값을 x=2로 설정한 후 최솟값 중 하나인 x=1에 도달할 수 있는지 검증해 보자.
- 뉴턴 방법을 활용한 최적화 구현
Dezero는 아직 2차 미분은 자동으로 구하지 못하므로 다음과 같이 수동으로 2차 미분을 구한다.
def f(x):
y=x**4 -2*x**2
return y
def gx2(x):
return 12 * x ** 2 -4
x=Variable(np.array(2.0))
iters=10
for i in range(iters):
print(i,x)
y=f(x)
x.cleargrad()
y.backward()
x.data -=x.grad / gx2(x.data)
위의 결과를 보면 목적지까지 빠르게 도달했음을 알 수 있다.
'Deep learning > 모델 구현' 카테고리의 다른 글
33. 형상 변환 함수, 합계 함수 (0) | 2021.10.16 |
---|---|
32. 고차 미분 (0) | 2021.10.14 |
30. 테일러 급수 미분 (0) | 2021.10.12 |
29. 연산자 오버로드 (0) | 2021.10.10 |
28. 변수 사용성 개선 (0) | 2021.10.10 |