2018년 8월 20일 월요일

DL/코세라 딥러닝 4.Gradient Descent(경사 하강법)

이 글은 코세라 Andrew Ng 교수의 deep learning AI 강의를 듣고 기억하기 좋게 정리한 것입니다. 목표는 제 부모님도 이해하시도록 쉽게 쓰는 것입니다.

Gradient Descent란 무엇인가? - 오차를 최소화하기

Gradient descent 알고리즘은 우리 말로는 경사 하강법이라고 부르며 최적화 알고리즘 중의 하나인데 여러 분야에서 쓰인다고 한다. 딥 러닝에서는 cost 함수의 값을 최소화하는 일에 쓰인다. cost 함수가 아래로 볼록(convex)한 경우에 임의의 시작점에서 출발해서 가장 오차를 많이 줄이는 방향으로 한 step마다 나아가서 오차값이 최소가 되는 극솟점을 찾을 수 있다. 가장 오차를 많이 줄이는 방향으로 간다는 것은 미분 기울기 값이 가장 큰, 즉 가장 가파른 방향으로 간다는 뜻이다. 냉면 그릇에 구슬을 떨어뜨리는 것을 생각하면 알기 쉽다. 함수가 냉면 그릇과 같은 아래로 볼록한 모양이라면 어느 지점에서 출발하든 결국 가장 바닥으로 가게 되는데, 이게 gradient descent 알고리즘이 의도하는 결과다.
오차값이 최소가 되는 점을 찾는다는 건 비용함수 \(J(w, b)\)를 최소화하는 w와 b를 찾는 일이다. 비용함수는 오차의 정도를 나타내는 함수이다. 경사 하강법을 통해서 오차를 최소화하기 때문에 이는 딥러닝에서 학습의 핵심이 된다. 최소값(minimum)에는 local과 global이 있는데, 우리 말로 하면 극솟값과 최솟값이다. 최종 목표는 local minimun을 잘 피해서 global minimun에 도달하는 것이다.


오차를 최소화하는 (w, b) 찾기

적절한 w,b를 찾는 과정은 다음과 같다.

1. w와 b를 특정한 값으로 초기화한다. 로지스틱 회귀에서는 거의 모든 초기화 방법이 다 유효한데, 보통 전부 0으로 초기화한다. 함수가 convex하기 때문에 초기화 값에 상관없이 대체로 같은 값에 도달한다.

2. gradient descent를 사용해서 내려가는 경사가 가장 가파른 방향으로 한 step 이동한다. 이 step의 크기는 learning rate에 의해 결정된다. learning rate란 아래 식에서의 \(\alpha\)를 가리킨다.
$$
    w := w-\alpha {dJ(w, b) \over dw}\\
    b := b-\alpha {dJ(w, b) \over db}
$$
여기서 := 연산자는 =과 같은 대입 연산자인데, 좌변의 값을 우변 값으로 업데이트 한다는 뜻으로 쓰였다. 그리고 \(\alpha \)는 learning rate를 나타낸다. 위의 식에서 \(dJ(w, b) \over dw \)는 사실 d 대신 편미분 기호를 써서 \(\partial J(w, b) \over \partial w \)로 써야 좀 더 정확하다.

3. Repeat until convergence - 위의 w와 b 업데이트를 minimun 값에 도달할 때까지 충분한 횟수만큼 반복한다. 아래 의사코드는 gradient descent를 한 단계 계산하기 위한 과정이다.

Gradient Descent와 Backward Propagation(오차역전파)

경사하강법을 통해서 기울기를 구해 거기에 learning rate를 곱해서 매개변수를 업데이트하는 게 딥러닝의 기본개념이다. 이걸 빠르게 해주는 게 back propagation,  우리 말로는 오차역전파이다.

로지스틱 회귀에서 Gradient Descent를 구하는 의사코드

#변수들 0으로 초기화
J = 0
for j=1 to n
    dw_j = 0
db = 0

#training data의 수 m개에 대하여 반복하기
for i=1 to m
    z[i] = w.T*x[i] + b
    a[i] = sigmoid(z[i])
    J += -( y[i]*log(yhat[i]) + (1-y[i])*log(1-yhat[i]) )
    dz[i] = a[i] - y[i]
    for j=1 to n
        dw_j = x[i]*dz
    db += dz[i]

#m으로 나누어서 평균 구하기
J /= m
for j=1 to n
    dw_j /= m
db /= m


위 코드에서 각각의 변수들은 다음과 같은 것을 나타낸다. (accumulator : 값을 더해서 모아두는 용도로만 쓰이는 변수. 여기선 나중에 m으로 나눠 평균값을 구하기 위해 쓰였음)

J : 비용함수 값의 accumulator. 비용함수 수식은 다음과 같다.
$$ J(w, b) = {1 \over m} \sum_{i=1}^m L(a^i, y^i) $$
dw_j : dw 값의 accumulator. w는 feature의 개수와 같으므로 j는 1부터 n_x(feature의 개수)가 된다. 즉 dw = \({\partial J(w, b) \over \partial w}\)
db : db 값의 accumulator. \({\partial J(w, b) \over \partial b}\)
z^i : 개별 z값이다. accumulator가 아니다.
dz^i : z^i에 대한 각각의 미분값이다. accumulator가 아니고 하나의 training sample에 대한 것이므로 주의.

위의 코드는 아직 벡터화(vectorization)를 적용하기 전이다. 벡터화에 대해선 다음 링크에서 알아보자. - https://silverskystudyandworkout.blogspot.com/2018/08/dl-vectorization.html

아무튼 위의 코드를 한 번 실행한 후에는 gradient descent를 한 단계 계산하는 과정이 완료된다. 이것을 충분히 반복하면 만족할 만한, 최소화된 오차를 주는 weight 값들을 구할 수 있다.

local minimun 이란?

위에서 global minimun에 잘 도달하기 위해서는 local minimum을 피해야 한다고 말했다. local minimum 이란 건 함수의 최솟값이 아닌 극솟값을 말하는데, 경사하강법을 이용해서 오차를 계속 줄여나가더라도 local minimum에 빠져버린다면 거기서 더 이상 움직이지 못하므로 global minimum에 도달할 수 없다. 따라서 기계학습 최적화에서 local minimum 문제를 해결하는 것은 중요하다.
그런데 local minimun 문제는 그렇게 중요하지 않다고 한다. 변수가 많을수록 local minimum이 생길 확률이 줄어들기 때문이다.


참고 링크

http://darkpgmr.tistory.com/133?category=761008
이 블로그에 글 쓰시는 분이 정말 정리를 잘 해놓으셨다. 머신러닝 관련만 있는 게 아니고 선형대수학이나 미적분, 프로그래밍 일반에 대한 글도 있다. 종종 참고하자.

댓글 없음:

댓글 쓰기

DL/코세라 딥러닝 3.이진 분류기(Binary Classifier)를 만들기 위해서는?

이 글은 코세라 Andrew Ng 교수의 deep learning AI 강의를 듣고 기억하기 좋게 정리한 것입니다. 목표는 제 부모님도 이해하시도록 쉽게 쓰는 것입니다.