59doit
경사하강법 본문
경사하강법
훈련데이터 -> (x : 입력데이터, y : 타킷데이터)
y = ax + b (a : 기울기, b : 절편)
y_hat : 예측값
y_hat = wx + b (w : 가중치, b : 절편)
모델이 데이터를 잘 표현할 수 있도록 기울기를 사용하여 모델을 조정하는 최적화 알고리즘
즉 w와 b를 찾기 위한 방법
# 1. 훈련데이터 준비하기
x = diabetes.data[:,2] # 세번째 특성만 뽑아내기 y = diabetes.target |
# 2. 훈련데이터의 첫번재 샘플로 y_hat 구하기
# (2-1) w, b 무작위로 정하기
w = 1.0 b = 1.0 |
# (2-2) x[0] 에 대한 y_hat 구하기
y_hat = x[0]*w + b |
# 3. 타깃과 예측 데이터 비교하기
print(y_hat) print(y[0]) |
# 예측데이터 1.0616962065186832 # x[0]에 대응하는 타깃값 151.0 |
▶예측값이 1.06정도 , 타긴은 151.0 이므로 차이가 크다.
w와 b를 조금씩 변경해서 y_hat이 증가하는지 감소하는지 확인해봐야한다.
# 4. w와 b를 변경해서 y_hat 증가 또는 감소 확인하기
# (4-1) w만 변화시키기
w_inc : w값을 증가(감소)시킨 값 (조정한값)
y_hat_inc : w값을 증가(감소)시킨 값에 대한 예측한값
w_inc = w + 0.1 y_hat_inc = x[0]*w_inc + b print(y_hat_inc) |
# 1.0678658271705517 |
▶1차함수의 기울기를 0.1만큼 높여준다고 생각하면 쉽다.
# (4-2) w값 조정한 후 예측값 증가 확인
w_rate : w의 변화율 (y_hat 증가값)
y_hat 증가한양 / w 증가한양
w_rate = (y_hat_inc - y_hat) / (w_inc - w) print(w_rate) |
# 0.06169620651868429 |
▶y_hat 이 얼마나 증가했는지 확인하기 위해서는 y_hat 증가량을 w증가량으로 나누면 된다.
0.0616ㆍㆍㆍ : 첫번째 훈련 데이터 x[0]에 대한 w의 변화율이다.
w의 변화율 : 0.06169620651868429 = x[0] : 0.061696206518683294 와 같다.
# 5. w 가중치 업데이트 하기
w_new = w + w_rate print(w_new) |
# 1.0616962065186843 |
▶cf)
변화율이 양수일때 가중치 업데이트 방법
: w가 증가하면 y_hat도 증가한다. -> 변화율을 w에 더하는 방법으로 w를 증가시킬 수 있다.
변화율이 음수일때 가중치 업데이트 방법
: w가 증가하면 y_hat은 감소한다 -> 변화율을 w에 더하는 방법으로 w를 증가시킬 수 있다.
∴즉, 가중치를 업데이트 하는 방법은 w+w_rate 이다.
# 6. 변화율로 절편 업데이트
# (6-1) b 변화시키고 y_hat 증가값 확인하기
b_inc : b 조정값
y_hat_inc : b를 조정 시킨 후 예측값
b_inc = b + 0.1 y_hat_inc = x[0]*w + b_inc print(y_hat_inc) |
# 1.1616962065186833 |
▶절편 b에 대한 변화율을 구한 다음 변화율로 b를 업데이트
# (6-2) 변화율 확인
b_rate = (y_hat_inc - y_hat) / (b_inc -b) print(b_rate) |
# 1.0 |
▶b가 1만큼 증가하면 y_hat도 1만큼 증가한다.
# (6-3) 변화율 1 더하기
b_new = b + 1 print(b_new) |
# 2.0 |
▶변화율이 1이므로 b를 업데이트 하기 위해서는 1을 더하면된다
∴ y_hat이 y보다 커지면 y_hat을 감소시키지 못한다.
# 7. w,b를 적절하게 업데이트하기
오차역 전파 : w,b를 더 능동적으로 업데이트 할 수 있다.
모델을 업데이트 할 때 오차의 크기를 반영한다.
y에서 y_hat을 뺀 오차의 양을 변화율에 곱하는 방법으로 w업데이트 하기
# (7-1) 오차와 변화율 곱하여 가중치 업데이트 하기 , x[0] 사용
w의 변화율과 b의 변화율에 오차를 곱하기
w_new, b_new
err = y[0] - y_hat w_new = w + w_rate*err b_new = b + 1*err print("w_new :",w_new,",","b_new :",b_new) |
# w_new : 10.250624555903848 , b_new : 150.9383037934813 |
▶w와 b가 큰폭으로 바뀌었다.
# (7-2) x[1]사용 오차 구하기
y_hat = x[1] * w_new + b_new err = y[1] - y_hat w_rate = x[1] # w_rate는 샘플값과 같아진다는것을 위에서 알았으므로 w_rate = x[1]과 같다고 본다 w_new = w_new + w_rate*err b_new = b_new + 1*err print("w_new :",w_new,",","b_new :",b_new) |
# w_new : 14.132317616380695 , b_new : 75.52764127612656 |
▶w_rate는 샘플값과 같아진다는것을 위에서 알았으므로 w_rate = x[1]과 같다고 본다
# 8. 전체 샘플 반복하기 for문 사용
# 8-1)
for x_i, y_i in zip(x,y): y_hat = x_i * w + b err = y_i - y_hat w_rate = x_i w = w + w_rate*err b = b + 1*err print("w :",w,",","b :",b) |
# w : 587.8654539985616 , b : 99.4093556453094 |
▶ zip 함수는 여러개의 배열에서 동시에 요소를 하나씩 꺼낸다
입력x와 타깃y배열에서 요소 하니씩 꺼내 err계산
w,b를 업데이트 한다.
# 9. 시각화 ; 모델이 전체 데이터 세트를 잘 표현하는지 그래프로 알아보기
plt.scatter(x,y) pt1 = (-0.1, -0.1*w +b) pt2 = (0.15, 0.15*w +b) plt.plot([pt1[0], pt2[0]], [pt1[1], pt2[1]]) plt.xlabel('x') #입력데이터 plt.ylabel('y') #타킷데이터 plt.show # 다음에 그려지는 plot 도 덮어져서 그려짐 |
▶산점도 위에 w와 b를 사용한 직선을 그려본다.
직선그래프는 시작점과 졸요점의 x좌표와 y좌표를 plot 함수에 전달한다.
x좌표 2개(-0.1,0.15) 지정
# 8-2) 여러에포크 반복하기
경사하강법에서는 주어진 훈련 데이터로 훈련 데이터로 학습을 여러번 반복한다.
-> 전체 훈련 데이터를 모두 이용하여 한 단위의 작업을 진행하는 것을 에포크 라고 한다.
#9 에서 찾은 직선은 데이터 중심에서 벗어나, 100번의 에포크를 반복하여 직선이 어떻게 이동하는지 확인하기위함
for i in range(1,100) : for x_i, y_i in zip(x, y) : y_hat = x_i * w + b err = y_i - y_hat w_rate = x_i w = w + w_rate * err b = b + 1 * err print("w :",w,",","b :",b) |
# w : 913.5973364346786 , b : 123.39414383177173 |
# 9-2) 시각화 ; 모델이 전체 데이터 세트를 잘 표현하는지 그래프로 알아보기
plt.scatter(x,y) pt1 = (-0.1, -0.1*w +b) pt2 = (0.15, 0.15*w +b) plt.plot([pt1[0], pt2[0]], [pt1[1], pt2[1]]) plt.xlabel('x') #입력데이터 plt.ylabel('y') #타킷데이터 plt.show |
▶시각화 결과를 보면 데이터에 맞는 머신러닝 모델을 찾았다고 볼 수 있다
경사하강법으로 선형 회귀의 가중치와 절편을 찾았다
=> y_hat = 913.6x + 123.4