본문 바로가기
CS/딥러닝

경사하강법

by jaehoonChoi 2023. 3. 18.

경사하강법은 볼록함수에서 극솟값을 찾아가는 방법입니다.

만약 볼록함수가 보장이 된다면 반드시 최적값에 도달할 수 있습니다.

 

 

볼록함수가 아니라면,  반드시 최적값에 도달한다는 보장은 없습니다.

만약 전역최솟값이 아닌 지역최솟값에 빠진다면 그 부분에서만 맴돌고 더이상 진전이 없습니다.

 

 

 

이러한 부분을 해결하기 위해 모멘텀 방식으로 지역해에 빠지는걸 방지하는 여러 규제가 적용됩니다.

이러한 규제는 이후에 소개합니다. 아무튼 경사하강법을 메인으로 딥러닝이 진행된다는 점이 중요합니다.

경사하강법은 매우 간단한 방식으로 작동합니다.

\(\bigtriangledown f(\textbf{x})=(\partial f/\partial x_1 , ... , \partial f/\partial x_n)\) 에 대하여, 

$$ \textbf{x} \leftarrow \textbf{x}-\eta \bigtriangledown f(\textbf{x}) $$

를 적용해주면 됩니다. 벡터 \(\textbf{x}\) 의 성분 \(x_1, ... , x_n\)  각각 편미분하여 학습률을 곱해 빼주는 방식입니다.

그냥 변수가 1개일 땐 직관적으로 기울기의 반대방향으로 이동하면 작동한다는게 이해되지만

다변수함수일때도 그래디언트 방향으로 이동하면 경사하강법이 작동한다는건 직관적으로 이해하기 어렵습니다. 

이 부분은 수학적인 부분으로, 방향도함수와 그래디언트의 관계에 대한 글을 소개합니다. 

(https://m.blog.naver.com/cindyvelyn/222147143662)

그래디언트의 방향이 바로 가장 빠르게 최적점에 도달하는 방향임을 알 수 있습니다. 

 

간단하게 프로그래밍을 해보겠습니다. 우선 경사하강법 알고리즘을 구현합니다.

 

def gradient_desent(f, df_dx, x_init, lr=0.01, epoch=100):
  # f: 함수
  # df_dx: 미분한 함수
  # x_init: 시작점
  # lr: 학습률
  # epoch: 반복횟수

  eps=1e-5 # 매우 작은 값
  count=0 # 도달하는데 횟수 
  x_old=x_init
  x_min=x_init
  y_min=f(x_min)

  x_log, y_log=[x_min],[y_min] # 경사하강 경로추적 list

  for i in range(epoch):
    grad=df_dx(x_old) 
    x_new=x_old-lr*grad  # 이동 
    y_new=f(x_new)
    if y_new<y_min: 
      x_min=x_new
      y_min=y_new
    if np.abs(x_old-x_new)<eps: # 진전이 없을 때
      break
    x_log.append(x_old)
    y_log.append(y_new)
    x_old=x_new
    count+=1
  return x_log, y_log, count

 

이제 구현한 알고리즘을 토대로 \(y=x\sin(x^2)+1 \) 그래프를 그려 확인해보겠습니다. 

 

def f(x): # f(x)
  return x*np.sin(x**2)+1

def df_dx(x):  # f'(x)
  return np.sin(x**2)+2*x**2*np.cos(x**2)

# -0.5에서 시작 start1
x_log1, y_log1, count1=gradient_desent(f, df_dx, x_init=-0.5)
plt.scatter(x_log1, y_log1, color='red')
plt.text(-0.5, f(-0.5)+0.5, 'start1\n {}'.format(count1), fontsize=13)

# 1.5에서 시작 start2
x_log2, y_log2, count2=gradient_desent(f, df_dx, x_init=1.5)
plt.scatter(x_log2, y_log2, color='blue')
plt.text(1.5, f(1.5)+0.5, 'start2\n {}'.format(count2), fontsize=13)

# -2.2에서 시작 start3
x_log3, y_log3, count3=gradient_desent(f, df_dx, x_init=-2.2)
plt.scatter(x_log3, y_log3, color='orange')
plt.text(-2.2, f(-2.2)+0.1, 'start3\n {}'.format(count3), fontsize=13)

x=np.arange(-5, 5, 0.01)
plt.plot(x, f3(x))
plt.show();

 

결과를 출력하면,

 

 

위와 같이 나옴을 알 수 있습니다. 오렌지 색과 파란색의 경우 기울기가 가팔라 지역최솟값에 빠르게 도달하지만

빨간색의 경우 기울기가 완만하여 느리게 도달함을 확인할 수 있습니다. 

'CS > 딥러닝' 카테고리의 다른 글

[논문 리뷰] AlexNet(2012)  (0) 2023.06.21
신경망 기본구조와 구현  (0) 2023.03.18

댓글