티스토리 뷰

반응형

 

앞선 포스팅에서 

선형 회귀에 대한 내용을 알아보았다.

이번에는 경사 하강법에 대해 

쉬운 소개를 해보려고 한다.

 

 

 

 

1. 경사 하강법이란(Gradient Descent)

 

그림 1 (출처 : 모두의 딥러닝)

 

 

위와 같은 그래프에서 

오차가 제일 적은 지점은

a = m일 때이다.

 

아래로 볼록한 함수의

가장 아랫 부분을 찾는 것이다.

a가 m에서 멀어질 수록 오차는 커진다.

 

즉, m과 같은 a(기울기)를 찾았을 때 

오차가 최소화 된다는 개념이다.

 

 

 

 

그림 2 (출처 : 모두의 딥러닝)

 

 

이 m을 찾아가는 과정을

위 그래프와 같이 

경사를 하강시키며 (m에 수렴시키며)

적합한 a를 찾는 과정을

경사하강법이라고 한다.

 

처음 그래프를 보면 

잘 이해가 안될 수 있는데,

우리는 이차함수 그래프 중

y=ax+b인 그래프에만 익숙하기 때문이다.

그래서 이를 x에 대하여 미분한 값인

a를 기울기라고 칭해왔다.

 

y=ax+b 그래프에서

y는 오차(E)가 되고 x는 기울기(a)로 바꾸면 

위의 그래프와 같다. 

 

그래서 최솟값 m에서의 순간 기울기가

0이 될 때가

오차가 최소화되는 지점인 것이다.

 

오차 함수 그래프에서

미분 값이 0인 지점을 찾아라!

가 우리의 미션이다.

 

오차 함수에 대해서 이해가 가지 않는다면

likethefirst.tistory.com/entry/Python-%EC%84%A0%ED%98%95%ED%9A%8C%EA%B7%80-2-a%EC%99%80-b%EC%97%90-%EB%94%B0%EB%A5%B8-%ED%8F%89%EA%B7%A0-%EC%98%A4%EC%B0%A8-%EC%A0%9C%EA%B3%B1MSE-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%ED%95%98%EA%B8%B0-%EC%84%A0%ED%98%95%ED%9A%8C%EA%B7%80-%EC%8B%A4%EC%8A%B5?category=935632

를 참고하길 바란다.

 

[Python] 선형회귀 (2) / 기울기 a와 y절편 b에 따른 평균 오차 제곱(MSE) 프로그래밍 하기, 선형회귀

likethefirst.tistory.com/entry/%EC%84%A0%ED%98%95%ED%9A%8C%EA%B7%80-Linear-Regression-Model-1 [Python] 선형회귀 (1) / 최소제곱법의 프로그래밍과 결과값 그래프로 나타내기 likethefirst.tistory.com/entr..

likethefirst.tistory.com

 

 

 

 

2. 학습률 (learning rate, lr)

우리는 경사가 계속 하강하듯이 (그림 2 참고)

a의 지점을 바꿔주면서 m으로 수렴시키는데,

어느만큼 이동시킬지,

이동 거리를 결정하는 것이 학습률이다.

 

학습률의 값은 최적의 값이라는 건 없고,

적절히 바꿔주면서 최적의 학습률을 찾아야 한다.

 

+ 추가

y=ax+b 식이 있을 때,

적절한 a만 찾는다고 

미분 값이 0인 지점을 찾을 수 있는 것이 아니라,

b값도 고려해야 한다.

b값이 너무 크거나 작으면

오차도 함께 커지기 때문이다.

이 b도 역시 경사 하강법을 통해 구한다.

 

 

 

 

3. 어떻게 하는가?

최솟값이 되는 지점을 찾으려면

이차 함수의 미분이 필요하다.

그 이차 함수는 평균 제곱 오차 함수가 된다.

 

평균 제곱 오차의 식은 원래

$\frac{1}{n}\sum_ \ (\hat{y_{i}}-y_{i})^2$인데, 

$\hat{y_{i}}$은 원래 $x_{i}$를

대입했을 때의 값이므로,

$y_{i}=ax_{i}+b$를 대입하면

$\frac{1}{n}\sum_ \ ((ax_{i}+b)-y_{i})^2$

와 같이 바뀐다.

 

이 식을 우리가 궁금해하는 a와 b를 위해

각각 a와 b로 편미분 한다.

 

 

그림 3 (출처 : 모두의 딥러닝)

 

 

이를 코딩으로 옮기면 된다.

평균 제곱 오차를 a/b로 미분한 결과를

학습률을 곱해 기존의 a, b값을 업데이트 한다.

 

 

 

 

 

4. 프로그래밍화 하기

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import matplotlib.pyplot as plt
import numpy as np
 
data = [[281], [493], [691], [897]] # 데이터셋 설정
= [i[0for i in data] # [2, 4, 6, 8]이 됨
= [i[1for i in data] # [81, 93, 91, 97]이 됨
 
x_data = np.array(x) # 넘파이 배열로 변환
y_data = np.array(y) 
 
= 0 # 기울기 a를 0으로 초기화
= 0 # y절편 b를 0으로 초기화
 
lr = 0.05 # 학습률 설정 (learning rate)
 
epochs = 2000 # 반복 횟수 설정
 
# 경사 하강법 시작
for i in range(epochs):
    y_pred = a * x_data + b # y 예측 값을 구하는 식
    error = y_data - y_pred # 오차 error = y 값 - y 예측 값
 
    a_diff = -(1 / len(x_data)) * sum(x_data * (error)) # 평균 제곱 오차를 a로 미분한 값
    b_diff = -(1 / len(x_data)) * sum(y_data - y_pred) # 평균 제곱 오차를 b로 미분한 값
 
    a = a - lr * a_diff # 학습률 * 미분 결과 후 기존 a 값 업데이트
    b = b - lr * b_diff # 학습률 * 미분 결과 후 기존 b 값 업데이트
 
    if i % 100 == 0# epoch가 100번 반복될 때마다 아래의 내용을 출력
        print("epoch = %.f, 기울기 = %.04f, 절편 = %.04f, 에러 = %.04f" % (i, a, b, error.mean()))
 
plt.scatter(x, y) # 이하 그래프 출력
plt.plot([min(x_data), max(x_data)], [min(y_pred), max(y_pred)])
plt.show()
 
cs

 

 

설명은 주석에 붙여두긴 했으나,

본인의 경우에는 line 23-24의 과정이

잘 이해되지 않았었다.

 

 

 

그림 4

 

 

 

line 23-24 :

a_diff와 b_diff가 

오차 함수를 각각 a, b로

편미분 한 변수인데

 

a_diff = -(1 / len(x_data)) * sum(x_data * (error)) # 평균 제곱 오차를 a로 미분한 값

b_diff = -(1 / len(x_data)) * sum(y_data - y_pred) # 평균 제곱 오차를 b로 미분한 값

 

갑자기 식이 이렇게 프로그래밍화 되는 것이

이해하기 어려웠다.

 

 

는 시그마 값의 2/n이니 

평균을 구한다는 것인데,

2가 왜 갑자기 1이 되는가에 대해서는

어차피 lr(학습률)을 곱하기 때문에

있으나 마나 한 수라고 이해했다.

(그저 수식을 간단하게 하는 것이다.)

 

이후 * sum(x_data * (error)) 부분은

(error)가 y^ - y 이고,

y^는 ax+b이기 때문에,

x * (ax+b-y)

= x_data * (y^-y)

= x_data * error가 된 것이다.

 

x, y가 1개가 아니라

$x_{i}$처럼 여러 데이터이기 때문에

sum() 을 한 것이다.

 

이를 epoch를 통해 여러번 반복한 후

matplotlib을 이용하여

line 32부터 그래프 출력을 한다.

 

 

 

 

  - 결과  

 

 

 

최적의 기울기 a는 2.3,

y 절편 b는 79가 나왔고

에러 값이 0에 도달했다.

 

epoch가 100번일 때마다 

결과값을 출력하도록 했으므로

2000번째까지 보고 싶다면

epoch를 2001로 조정하면 된다.

 

 

 

 

여기서 line 33 plt.plot()는

그래프의 x축과 y축 값을 설정해주는 것인데,

plt.plot([min(x_data), max(x_data)], [min(y_pred), max(y_pred)])

라고 썼으므로 

파란색 직선의 그래프를 나타낸다고 할 수 있다.

즉, x값에 따른 y값의 예측 그래프인 것이다.

파란색 점은 원래 있던 데이터셋의 정보이다.

 

 

아래는 경사 하강법을 공부하는 데에 있어

많은 의문을 해결하게 해준 좋은 포스팅들이다.

더 깊게 공부해보고 싶다면

참고하시길 권한다.

https://m.blog.naver.com/marketing815/221783327249
https://brunch.co.kr/@linecard/447

반응형
댓글
반응형
Recent Post.
Recent Reply.
Thanks for comming.
오늘은
명이 방문했어요
어제는
명이 방문했어요