본문 바로가기

인공지능/딥러닝

선형 회귀와 경사 하강법

이번 글에서는 딥러닝의 가장 기초가 되는 선형 회귀에 대해 다뤄보려고 합니다. 

그리고 경사 하강법으로 학습을 하고 나아가 뉴런(유닛) 클래스를 만들어 보는 것까지 얘기하겠습니다. 

이 글에서의 코드는 구글의 코랩(Colab)으로 실습합니다.

이 글의 마지막에 제가 실습한 코랩 url을 첨부하겠습니다. 

 

인공지능과 딥러닝에 대한 기본 개념과 이해는 인공지능 카테고리의 다른 글을 참고해주세요. 

이 글은 'Do it! 정직하게 코딩하며 배우는 딥러닝 입문' 책으로 공부하며 정리한 글입니다. 


선형 회귀

선형 회귀는 머신러닝 알고리즘 중 가장 간단하면서 딥러닝의 기초가 되는 것입니다.

선형 회귀는 다음과 같이 간단한 1차 함수로 표현할 수 있습니다. 

y = ax + b

중학교에서 배웠던 1차 함수에서 우리는 a, b가 주어지고 x, y 값을 찾아야 했지만 인공 지능에서 중요한 것은 절편(b)과 기울기(a)를 찾는 것 입니다. 먼저 여러 점이 주어지고 그 점을 가장 잘 표현할 수 있는 1차 함수를 찾는 것이 목적입니다. 그렇게 만들어진 1차 함수들을 '선형 회귀로 만든 모델'이라고 부르고 가장 잘 표현한 하나의 1차 함수가 바로 최적의 모델입니다. 

인공 지능에서 중요한 것은 예측입니다. 따라서 이렇게 만들어진 모델로 미지의 점(x)에 대한 예측(y값)을 할 수 있습니다. 

 

 

경사 하강법

경사 하강법은 모델이 데이터를 잘 표현할 수 있도록 기울기(변화율)를 사용하여 모델을 조금씩 조정하는 최적화 알고리즘입니다. 

즉, 회귀 문제를 풀기 위한 많은 알고리즘 중 하나가 경사 하강법이라고 생각하시면 됩니다. 

딥러닝에서는 기울기(a)를 가중치를 의미하는 w로 표기하고 y 값은 예측값을 의미하는 y-hat 으로 표기합니다.

따라서 직선의 방정식을 위와 같이 표현할 수 있습니다. 

선형 회귀에서 말했듯이 가중치 w와 절편 b를 찾는 것이 중요합니다. 

여기서 중요하게 알아야할 것은, 하나의 x, y에 대해 가중치와 절편을 구하는 것입니다. 첫 번째 x에 대해 w, b를 조정하고 그 다음 샘플 x에 대해 w, b를 조정하여 결국 최적의 w, b를 결정하여 최적의 모델을 구하게 됩니다. 이것이 바로 학습입니다. 

 

훈련 데이터에 잘 맞는 w와 b를 찾는 방법

1. 무작위로 w와 b를 선택합니다. 즉, 무작위로 일단 모델을 만드는 것입니다.

2. 입력 데이터 x에서 샘플 하나를 선택하여 예측값을 계산합니다. 

3. 예측값과 샘플의 진짜 y값, 즉 타깃을 비교합니다. 

4. 예측값이 y와 더 가까워지도록 w와 b를 조정합니다. (모델 조정)

5. 모든 샘플을 처리할 때까지 2~4 과정을 반복합니다. 

 

4번에서 가중치를 업데이트할 때 변화율로 업데이트하는 방법이 있습니다. 

여기서의 변화율은 w를 증가시켰을 때 y_hat이 증가한 양입니다. 각각의 샘플에 대해 가중치의 변화율을 구할 수 있는데 수식으로 정리하면 변화율은 결국 훈련 데이터의 i번째 샘플 x[i] 입니다. 

y_hat이 y보다 작은 경우 변화율을 사용해 어떻게 업데이트 할까요?

변화율이 양수이면 x축이 w고 y축이 y_hat인 그래프에서 w가 증가하면 y_hat이 증가하므로 변화율을 가중치에 더하는 방법으로 가중치를 업데이트할 수 있습니다.

변화율이 음수이면 w가 증가하면 y_hat이 감소하므로 변화율(음수)를 가중치에 더하면 y_hat이 증가하므로 가중치를 업데이트할 수 있습니다.

절편을 업데이트할 때도 변화율로 업데이트할 수 있습니다. 

이 때의 변화율은 b를 증가시켰을 때 y_hat이 증가한 양입니다. 당연하게도 변화율은 1입니다. 절편이 1 증가하면 그래프 위치가 +y 방향으로 1 증가하기 때문이죠. 

y_hat이 y보다 작은 경우 절편을 업데이트하기 위해서는 단순하게 1만 더하면 됩니다.

▶ 여기에 문제가 있습니다. 예측값과 타깃값의 차이가 크면 큰 폭으로 w, b를 조정해야하는데 위의 방법으로는 너무 조금씩밖에 조정되지 않습니다. 그리고 예측값이 y보다 크면 y_hat을 감소시키지 못합니다. 

따라서 오차 역전파를 사용하여 더욱 적절하게 w와 b를 업데이트할 수 있습니다. 

 

오차 역전파

오차 역전파란 w와 b의 변화율에 타깃(y)에서 예측값(y_hat)을 뺀 오차를 곱하는 방법입니다. 

따라서 오차 역전파를 사용하면 오차의 크기를 반영해 모델을 업데이트할 수 있고 y_hat이 y보다 작은 경우에는 오차가 음수가 되어 가중치와 절편을 줄어드는 방향으로 업데이트할 수 있습니다. 

코드는 다음과 같습니다.

err = y_i - y_hat
w = w + x_i * err
b = b + 1 * err

경사 하강법에서는 주어진 훈련 데이터로 여러 번 학습을 합니다. 전체 훈련 데이터를 한 번 학습하는 것을 에포크(epoch) 라고 부릅니다. 일반적으로 수십에서 수천 번의 에포크를 반복합니다. 

여러 번 학습하는 것은 2개의 for문으로 처리할 수 있습니다.

전체 훈련 데이터에 대한 학습 -> for문 1개

여러 번의 에포크 반복 -> 위의 for문의 바깥쪽에 for문 1개

 

 

손실 함수

손실 함수는 예상한 값과 실제 타깃값의 차이를 함수로 정의한 것입니다.

경사 하강법은 어떤 손실 함수가 정의되었을 때 손실 함수 값이 최소가 되는 점을 찾아가는 방법이 되는 것입니다. 

위의 오차 역전파에서 말한 오차로 w와 b를 업데이트한 것은 '제곱 오차'라는 손실 함수를 미분한 것과 같습니다.

 

여러 손실 함수 중 '제곱 오차'에 대해 알아봅시다.

제곱 오차 식입니다.

제곱 오차 식을 가중치에 대해 편미분하고 절편에 대해 편미분하면 그 결과는 다음과 같습니다.

이 때 미분하면 결과값에 2가 나오므로 제곱 오차에 1/2를 곱한 식을 미분합니다.

* 미분적분학 기본 개념 - 미분 결과는 변화율과 같습니다.

 

가중치에 대해 편미분한 결과는

-(y - y_hat)x  로,

가중치에 대한 제곱 오차의 변화율과 같습니다. 변화율로 가중치를 업데이트할 때는 위의 경사 하강법에서 다뤘던 것과 비슷하게 변화율을 뺍니다. 왜냐하면 예측값이 커져야했던 것과 달리 이 식은 손실 함수이므로 손실 함수는 작을수록 최적의 모델이기 때문이죠.

업데이트 된 가중치

w = w + (y - y_hat)x

 

절편에 대해 편미분한 결과는 

-(y - y_hat)*1

그리고 위와 같이 절편을 업데이트하면

b = b + (y - y_hat)*1

 

인공지능 분야에서는 변화율을 gradient(경사) 라고 부릅니다.

 

 

뉴런

경사 하강법 알고리즘을 Neuron이라는 이름의 파이썬 클래스로 만들겠습니다.

이 뉴런은 절대 우리 뇌 속의 뉴런과 같지 않습니다. 따라서 뉴런을 유닛이라고도 부릅니다.

이 뉴런 클래스에서의 정방향 계산은 바로 예측값을 계산하는 것을 의미합니다. 

역방향 계산은 오차를 이용해 가중치와 절편의 gradient를 계산하는 것을 의미합니다. 

class Neuron:
  # 초기화 메서드
  def __init__(self):   
    self.w = 1.0  # 학습할 때 가중치와 절편은 시작값이 있어야함
    self.b = 1.0
    
  # 정방향 계산을 위한 메서드 
  def forpass(self, x): 
    y_hat = x*self.w + self.b
    return y_hat
  
  # 역방향 계산 메서드 (오차 역전파)
  def backprop(self, x, err): 
    w_grad = x*err
    b_grad = 1*err
    return w_grad, b_grad
  
  # 훈련을 위한 메서드
  # 가중치와 절편 업데이트. 이 과정이 '훈련'
  def fit(self, x, y, epochs=100):
    for i in range(epochs):		  # 100 에포크 반복
      for x_i, y_i in zip(x, y):  # 모든 샘플에 대해 반복
        y_hat = self.forpass(x_i)
        err = -(y_i - y_hat)
        w_grad, b_grad = self.backprop(x_i, err)
        self.w -= w_grad
        self.b -= b_grad

신경망 모델을 사용하는 딥러닝은 항상 경사 하강법 알고리즘을 사용합니다. 

이 글에서 다룬 경사 하강법 알고리즘이 딥러닝 핵심 중 하나입니다. 


 

위의 개념들을 익히며 코랩으로 실습한 것을 첨부합니다.

https://colab.research.google.com/drive/1kX9aMMmSaQMvixVVpmYj-Yf-tqlka_Ej#scrollTo=KbQaGm4-HpGV

 

Google Colaboratory

 

colab.research.google.com

'인공지능 > 딥러닝' 카테고리의 다른 글

[cs231n] Lecture Summary _part I  (0) 2021.06.27
[Tensorflow] Transfer Learning  (0) 2021.05.30
[Tensorflow] 이미지 분류  (0) 2021.05.30
이진 분류_로지스틱 회귀  (0) 2021.02.22