선형 회귀에서 잠깐 말했었던 예측선을 수정하는 걸 해볼 것이다.
a값을 무한대로 키우거나 작게 하면 오차는 무한대로 커진다. 이러한 관계를 이차 함수 그래프로 표현이 가능하다.
이걸 이용하여 a, b의 오차를 줄이는 방향으로 수정을 해야 한다.
저기서 y^- y를 t로 치환하면 이차함수 그래프가 되는 걸 알 수 있다. 여기서 우리는 y' - y = 0으로 가게 하는 즉, 오차가 0일 때 a, b를 구해야 한다. 그걸 구하긴 위해서는 이차 함수의 최솟값 즉, 기울기가 0에 가까울 때 a, b 구해야한다.
기울기가 0인 값을 m이라고 하였을 때m을 구하려면 임의의 한 점을 찍고 이 점을 m에 가까운 쪽으로 점점 이동시키는 과정이 필요하다. 이것이 가능하게 하는 게 경사 하강법이다. 이때 미분 기울기를 이용한다.
즉 우리는 미분 값이 0에 가까운 지점을 찾아야 한다.
임의의 a값을 설정하고 미분값이 0이 나올 때까지 계속 a값을 재설정한다. 이는 b도 같은 과정을 거친다.
여기서 주의할 점은 학습률을 너무 작거나 크게 잡으면 한 점으로 수렴하지 않고 발산한다. 딥러닝에서 학습률의 값을 적절히 바꾸면서 최적의 학습률을 찾는 것은 중요한 최적화 과정 중 하나이다.
데이터의 값이 크다면 0~1 사이로 줄여서 사용해주는 과정이 필요하다.
예를 들어 값이 200이라면 / 200을 하여 사용하다가 나중에 다시 200을 곱해주는 방식으로 사용한다.
b의 값도 a와 같은 성질을 가지고 있다. 그래서 b의 값을 구할 때도 경사 하강법을 사용한다.
궁금한 것은 a와 b이기 때문에 우리에게 필요한 값을 중심으로 식을 편미분 하여 구해야 한다.
for
1. y값 추정 값 계산 // y_pred = a * x_data + b
2. y^ - y 오차 계산 // a_diff = -(2/len(x)) * sum(x_data * (error)) b_diff = -(2/len(x)) * sum(error)
3. a, b 미분 계산
4. a, b 조정
a, b 편미분을 해주는 이유는 a값 변수로 두고 미분을 했다면 a의 기울기 a_diff 이 값이 0 일 때 오차가 발생하지 않았다고 볼 수 있고 오차가 발생했다면 a = a - lr * a_diff 이 과정을 통해 오차를 줄여주는 것이다. 이는 b에도 같이 적용된다.
import numpy as np
import matplotlib.pyplot as plt
data=[[2,81],[4,93],[6,91],[8,97]]
x = [i[0] for i in data]
y = [i[1] for i in data]
plt.figure(figsize = (8,5))
plt.scatter(x,y)
plt.show()
lr = 0.01
epochs = 2001
x_data = np.array(x)
y_data = np.array(y)
a=0
b=0
for i in range(epochs):
y_pred = a * x_data + b
error = y_pred - y_data
a_diff = (2/len(x_data)) * sum(error*x_data)
b_diff = (2/len(x_data)) * sum(error)
a = a - lr * a_diff
b = b - lr * b_diff
if i % 100 == 0:
print(i,error.mean())
#print("epoch=%.f , 기울기 = %.04f, 절편=%.04f" %(i,a,b))
plt.plot(x,y,"ro") #plt.scatter(x,y,color='red')
plt.plot(x,y_pred,"bo")
plt.plot(x,y_pred) #plt.plot([min(x_data), max(x_data)],[min(y_pred), max(y_pred)],color='blue')
plt.show()
위의 코드는 경사 하강법을 코드로 정리한 것이고
0 -90.5
100 -8.959862261532482
200 -6.475017034018357
300 -4.679295771189324
400 -3.3815832142578763
500 -2.443766240500807
600 -1.7660347416652478
700 -1.2762590206375535
800 -0.9223131625501537
900 -0.6665273710569402
1000 -0.481678842292272
1100 -0.34809449271993387
1200 -0.251557189610633
1300 -0.18179264816957996
1400 -0.13137595860273876
1500 -0.09494136684058319
1600 -0.06861120735807091
1700 -0.049583210478065354
1800 -0.035832262045488505
1900 -0.02589487431163917
2000 -0.018713429667489123
결과는 이렇게 나오고 선형 회귀 그래프와 비교를 해보면 이렇게 나온다
그래프 상으로는 변한 게 없지만 오차를 수정하며 a와 b값이 변한 걸 알 수 있다.
위의 예시는 공부시간에 대한 점수 즉 독립변수가 하나인 경우에 대한 것이고 2개 이상의 독립변수를 쓸 경우 다중 선형 회귀 경사 하강법를 사용해야 한다.
공부한 시간 (x1) | 2 | 4 | 6 | 8 |
과외 수업 횟수 (x2) | 0 | 4 | 2 | 3 |
성적 (y) | 81 | 93 | 91 | 97 |
예측 값 | 80.76387645 | 92.97153922 | 91.42520875 | 96.7558749 |
공부한 시간 | 2 | 4 | 6 | 8 |
성적 | 81 | 93 | 91 | 97 |
예측 값 | 83.6 | 88.2 | 92.8 | 97.4 |
아래의 표는 선형 회귀 최소 제곱 법만을 이용하여 찾은 예측 값인데 독립 변수가 늘고 경사 하강법 처리를 해주었을 때 예측 값이 성적과 유사하게 나온다.
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits import mplot3d
data=[[2,0,81],[4,4,93],[6,2,91],[8,3,97]]
x1 = [i[0] for i in data]
x2 = [i[1] for i in data]
y = [i[2] for i in data]
lr = 0.01
epochs = 2001
x1_data = np.array(x1)
x2_data = np.array(x2)
y_data = np.array(y)
a1=0
a2=0
b=0
for i in range(epochs):
y_pred = a1 * x1_data + a2 * x2_data + b
error = y_pred - y_data
a1_diff = (2/len(x1_data)) * sum(error*x1_data)
a2_diff = (2/len(x2_data)) * sum(error*x2_data)
b_diff = (2/len(x_data)) * sum(error)
a1 = a1 - lr * a1_diff
a2 = a2 - lr * a2_diff
b = b - lr * b_diff
if i % 100 == 0:
print(i,error.mean())
#print(a1,a2,b)
print(y_pred)
#print("epoch=%.f , 기울기 = %.04f, 절편=%.04f" %(i,a,b))
ax = plt.axes(projection ="3d")
ax.plot(x1,x2,y,"ro")
ax.plot(x1,x2,y_pred,"bo")
x1 = np.arange(np.min(x1),np.max(x1),0.01)
x2 = np.arange(np.min(x2),np.max(x2),0.01)
x1 ,x2 = np.meshgrid(x1, x2)
y_pred = a1 * x1 + a2 * x2 + b
ax.plot_surface(x1,x2,y_pred, rstride = 4, cstride = 4, alpha = 0.4 , cmap = cm.jet)
plt.show()
0 -90.5
100 -8.74168734352791
200 -6.36233607893675
300 -4.630406046779061
400 -3.369922184592241
500 -2.452564965116512
600 -1.7849298577179589
700 -1.2990377966341633
800 -0.9454148516726519
900 -0.688054838789256
1000 -0.500753145926172
1100 -0.36443855782798096
1200 -0.2652314089531771
1300 -0.19303034430427246
1400 -0.1404837910008041
1500 -0.10224141497072381
1600 -0.07440934545366673
1700 -0.05415369781832169
1800 -0.03941202505570729
1900 -0.02868331769700916
2000 -0.020875169772310187
[80.76387645 92.97153922 91.42520875 96.7558749 ]
'Machine Learning > 이론' 카테고리의 다른 글
[ML] Overfitting, Underfitting (0) | 2022.08.17 |
---|---|
Hypothesis and Inference, p-value (0) | 2022.08.11 |
[통계] 베이지안 이론 Bayesian theory (0) | 2022.08.10 |
[Statistics] 중심 경향성 (0) | 2022.08.09 |
[ML] 선형 회귀 (0) | 2021.03.30 |