욱이명 2020. 11. 23. 18:25

위 산점도에 가장 잘 맞는 직선을 그린다면 어떤 모습일까. 가운데 그림의 직선이 다른 두 직선보다 데이터를 잘 표현하고 있다는 것을 직관적으로 알 수 있다. 즉, 데이터를 표현하는 점들의 가운데 지점을 가로지르는 직선을 자연스럽게 찾아낼 수 있다. 

 

위 그래프는 1개의 특성에 대한 타깃 데이터를 그림으로 표현한 것인데 10개의 특성으로 그래프를 그린다면 11차원 그래프는 그릴 수도 없지만 11차원 공간을 가로지르는 초평면은 상상하기도 어렵다. 그래서 보통은 특성의 개수를 1, 2개만 사용하여 2차원이나 3차원 그래프로 그리는 경우가 많다. 항상 그런 것은 아니지만 낮은 차원에서 얻은 직관은 높은 차원으로 확장될 수 있으므로 위와 같이 입력 데이터의 특성 1개를 골라 시각화하는 경우가 많다.

 

선형 회귀와 경사 하강법의 관계

선형 회귀의 목표는 입력 데이터(x)와 타깃 데이터(y)를 통해 기울기(a)와 절편(b)을 찾는 것이었다. 즉, 산점도 그래프를 잘 표현하는 직선의 방정식을 찾는 것이 회귀 알고리즘의 목표였다. 이번에 설명하려는 경사 하강법(gradient descent)이 바로 그 방법 중 하나이다. 경사 하강법은 모델이 데이터를 잘 표현할 수 있도록 기울기(변화율)를 사용하여 모델을 조금씩 조정하는 최적화 알고리즘이다. 또한, 회귀 문제를 풀기 위한 알고리즘은 경사 하강법 외에 아주 많다.

예측값

딥러닝 분야에서는 기울기 a를 종종 가중치를 의미하는 w나 계수를 의미하는 θ로 표기한다. 그리고 y는 y^으로 표기하며 읽을 때는 와이-햇(y-hat)이라고 읽는다. 즉, y^=wx+b에서 가중치 w와 절편 b는 알고리즘이 찾은 규칙을 의미하고, y^은 우리가 예측한 값(예측값)을 의미한다.

 

우리가 입력과 출력 데이터(x, y)를 통해 규칙(a, b)을 발견하면 모델을 만들었다고 한다. 그 모델에 대해 새로운 입력값을 넣으면 어떤 출력이 나오는데, 이 값이 모델을 통해 예측한 값이다. 예를 들어 y=7x+4라는 모델의 x에 7을 넣으면 53이라는 값이 나오는데, 이 값이 모델을 통해 예측한 값이다. 그래서 타깃 데이터를 표현하는 y라는 문자와 구분하기 위해 y^이라는 문자를 따로 준비한 것이다. 

예측값으로 올바른 모델 찾기

y^=wx+b 이 식에서 우리가 찾고 싶은 것은 훈련 데이터(x, y)에 잘 맞는 w와 b이다. w와 b를 찾기 위한 방법은 다음과 같다.

 

1. 무작위로 w와 b를 정한다(무작위로 모델 만들기).

2. x에서 샘플 하나를 선택하여 y^을 계산한다(무작위로 모델 예측하기).

3. y^과 선택한 샘플의 진짜 y를 비교한다(예측한 값과 진짜 정답 비교하기, 틀릴 확률 99%).

4. y^이 y와 더 가까워지도록 w, b를 조정한다(모델 조정하기).

5. 모든 샘플을 처리할 때까지 다시 2~4 항목을 반복한다.

 

먼저 w와 b를 무작위로 초기화하겠다. 여기에서는 간단하게 두 값을 모두 실수 1.0으로 정하겠다. 쉽게 말해 아직 w와 b를 어떻게 초기화할지 규칙을 정하지 않았으므로 임시 규칙을 정한 것이다. 물론 이 방법은 w의 개수가 많아지면 번거롭기도 하고 바람직한 방법도 아니다.

w와 b를 가각 1.0으로 초기화

다음으로 임시로 만든 모델로 훈련 데이터의 첫 번째 샘플 x[0]에 대한 y^을 계산해 보겠다. 계산한 y^은 y_hat 변수에 저장한다.

그런 다음 첫 번째 샘플x[0]에  대응하는 타깃 값 y [0]을 출력하여 y_hat의 값과 비교한다.

y_hat은 1.06 정도이고 타깃은 151.0이므로 차이가 크다. w와 b를 무작위 값으로 정했기 때문에 예측 결과가 잘 나오지 않은 것이 당연하다. 단순히 w와 b를 조금씩 변경해서 y_hat이 증가하는지 또는 감소하는지 살펴보며 y [0]에 가까워지도록 해보겠다. 먼저 w를 0.1만큼 증가시키고 y_hat의 변화량을 보겠다.

확인해 보니 y_hat보다 조금 증가했다.

 

다음으로 w가 0.1만큼 증가했을 때 y_hat이 얼마나 증가했는지 계산해 보겠다. y_hat이 증가한 양을 w가 증가한 양으로 나누면 된다.

위 y_hat의 변화율은 아래의 식과 같이 결국 훈련 데이터의 첫 번째 샘플인 x[0]이라는 것을 알 수 있다.

 

변화율로 가중치 업데이트

w를 0.1만큼 증가시켰을 때 변화율이 양수였다. 변화율이 양수라면 예측값 y_hat이 타깃 y[0]에 가까워지고 있다는 뜻이니 w를 증가시켜도 된다. 하지만 w를 증가시키다 보면 y_hat의 변화율이 음수가 될 수도 있다. w를 증가시켰더니 y_hat변화율이 음수가 되었으니 반대로 w를 감소시키면 된다.

 

즉, 예측값 y_hat을 타깃 값 y[0]에 가까워지게 w를 업데이트하는 방법을 정리하면 'y_hat의 변화율이 양수라면 w를 증가시키고, 음수라면 w를 감소시킨다.'이다. 한마디로 w에 변화율을 더하기만 하면 y_hat을 y[0]에 가까워지게 할 수 있다. 이것을 코드로 표현하면 아래와 같다.

      

변화율로 절편 업데이트

이번엔 절편 b에 대한 y_hat의 변화율을 구한 다음 변화율로 b를 업데이트하겠다. b를 0.1만큼 증가시킨 후 y_hat이 얼마나 증가했는지 계산하고 변화율도 계산하겠다.

변화율의 값을 보니 1이다. 즉, b가 1만큼 증가하면 y_hat도 1만큼 증가한다. 1차 함수로 만든 그래프를 놓고 생각해 보면 절편이 1만큼 증가하면 그래프의 위치가 y 방향으로 1만큼 올라가니 당연한 결과이다. 즉, b를 업데이트하기 위해서는 변화율이 1이므로 단순히 1을 더하면 된다.

이렇게 해서 변화율을 더하는 방식으로 가중치와 절편을 업데이트해봤다. 하지만 이 방법에는 y_hat이 y에 한참 미치지 못하는 값인 경우, w와 b를 더 큰 폭으로 수정할 수 없고 y_hat이 y보다 커지면 y_hat을 감소시키지 못한다는 단점이 존재한다. 

오차 역전파로 가중치와 절편을 더 적절하게 업데이트

오차 역전파(backpropagation)는 y^과 y의 차이를 이용하여 w와 b를 업데이트한다. 

 

이전에는 변화율만으로 w와 b를 업데이트했다. 하지만 앞에서 설명했듯이 이 방법은 단점이 존재한다. 이번에는 y에서 y^을 뺀 오차의 양을 변화율에 곱하는 방법으로 w를 업데이트해 보겠다. 이렇게 하면 y^이 y보다 많이 작은 경우 w와 b를 많이 바꿀 수 있고 y^이 y를 지나치면 w와 b의 방향도 바꿔준다.

 

먼저 x[0]일 때 w의 변화율과 b의 변화율에 오차를 곱한 다음 업데이트된 w_new와 b_new를 출력해 보겠다. 

결괏값을 보면 변화율만 더해서 업데이트하는 이전 방식보다 w와 b가 각각 더 큰 폭으로 바뀌었음을 알 수 있다.

 

두 번째 샘플 x[1]을 사용하여 오차를 구하고 새로운 w와 b를 구해 보겠다.

w는 4만큼 커지고 b는 절반(약 150에서 75로)으로 줄어들었다. 이런 방식으로 모든 샘플을 사용해 가중치와 절편을 업데이트한다.

 

전체 샘플에 대해 앞의 과정을 반복하는 코드는 다음과 같다.

 

산점도 위에 w와 b를 사용한 직선을 그려 전체 샘플로 학습시킨 모델이 전체 데이터 세트를 잘 표현하는지 알아보겠다. 직선 그래프를 그리려면 시작점과 종료점의 x 좌표와 y 좌표를 plot() 함수에 전달하면 된다. x 좌표 2개[-0.1, 0.15]를 지정하고 y 좌표값은 w와 b를 사용해 계산하면 그래프를 손쉽게 그릴 수 있다.

직선의 모양을 보면 아주 만족스럽진 않지만 산점도를 어느 정도 잘 표현한 것 같다. 

 

보통 경사 하강법에서는 주어진 훈련 데이터로 학습을 여러 번 반복한다. 이렇게 전체 훈련 데이터를 모두 이용하여 한 단위의 작업을 진행하는 것을 특별히 에포크(epoch)라고 부른다. 일반적으로 수십에서 수천번의 에포크를 반복한다. 앞에서 찾은 직선은 데이터의 중심에서 조금 벗어난 것 같아 100번의 에포크를 반복하면서 직선이 어떻게 이동하는지 확인해 보겠다. 단순하게 for문 바깥쪽에 for문을 하나 더 씌우면 된다.

 

100번의 에포크를 반복하여 찾은 w와 b는 위와 같이 약 913.6, 123.4 정도이다. 저 w와 b를 이용하여 다시 한번 직선을 그래프로 나타내 보겠다.

직선이 전체 데이터의 경향을 제법 잘 따라갔다. 이 데이터에 잘 맞는 머신러닝 모델 'y^=913.6x+123.4'을 찾은 것이다.

 

이번에는 입력 x에 없었던 새로운 데이터가 발생했다고 가정해 보겠다. 이 데이터에 대해 예측값을 얻으려면 우리가 찾은 모델에 x를 넣고 계산하기만 하면 된다. x가 0.18일 때 y^의 값을 예측해 보겠다.

다음은 이 데이터를 산점도 위에 나타낸 것이다.

오른쪽 위의 박스로 표시한 점이 바로 x가 0.18일 때 예측한 y^으로 찍은 점이다. 산점도의 추세를 보니 어느 정도 잘 예측한 것 같다.