728x90
경사 하강법(gradient decent) : 그래프에서 오차를 비교해 가장 작은 방향으로 이동 시키는 방법
1. 미분의 개념
순간 변화율 : 어느 한 점에서 x를 0에 가까운 변화를 준 것. y에 값도 0에 가까운 변화를 가짐
기울기 : 그래프에서 점 a 에서의 순간 변화율
2. 경사 하강법의 개요
x를 적절히 조절해 순간 기울기가 0인 x = m 인 지점을 찾는것이 경사 하강법의 원리다.
즉, 반복적으로 기울기 a를 변화시켜 m의 값을 찾아가는 기법이다.
3. 학습률
위 사진에서 기울기의 부호를 바꿔 이동시킨다. 이 때 적절한 거리를 찾지 못해 너무 멀리 이동시키면 a 값이 한 점으로 모이지 않게 된다. 따라서 어느 만큼 이동시킬지를 결정해야 한다. 즉 이것을 학습률(learning rate)라고 한다.
오차의 변화에 따라 이차 함수 그래프를 만들고 적절한 학습률을 설정해 미분 값이 0인 지점을 구한다. y 절편 b 의 값도 이와 같은 성질을 가지고 있다. 따라서 최적의 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 tensorflow as tf # 데이터, x축 데이터, y축 데이터, 학습률 data = [[2, 81], [4, 93], [6, 91], [8, 97]] x_data = [x_row[0] for x_row in data] y_data = [y_row[1] for y_row in data] learning_rate = 0.1 # 기울기 a와 절편 b의 값을 임의로 정한다. a는 0~10 사이, b는 0~100 사이 a = tf.Variable(tf.random_uniform([1], 0, 10, dtype = tf.float64, seed = 0)) b = tf.Variable(tf.random_uniform([1], 0, 100, dtype = tf.float64, seed = 0)) # 일차방정식 y = a * x_data + b # 평균 제곱근 오차, 텐서플로 RMSE 함수 rmse = tf.sqrt(tf.reduce_mean(tf.square( y - y_data ))) # 경사 하강법, RMSE값을 최소로 하는 값 찾기 gradient_decent = tf.train.GradientDescentOptimizer(learning_rate).minimize(rmse) # 텐서플로 실행 후 결괏값 출력 with tf.Session() as sess: # 변수 초기화 sess.run(tf.global_variables_initializer()) # 2001번 실행(0번째를 포함하므로) for step in range(2001): sess.run(gradient_decent) # 100번마다 결과 출력 if step % 100 == 0: print("Epoch: %.f, RMSE = %.04f, 기울기 a = %.4f, y 절편 b = %.4f" % (step, sess.run(rmse), sess.run(a), sess.run(b))) | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | Epoch: 0, RMSE = 30.2139, 기울기 a = 7.5235, y 절편 b = 80.5984 Epoch: 100, RMSE = 2.8860, 기울기 a = 2.2299, y 절편 b = 79.4181 Epoch: 200, RMSE = 2.8826, 기울기 a = 2.2601, y 절편 b = 79.2379 Epoch: 300, RMSE = 2.8815, 기울기 a = 2.2773, y 절편 b = 79.1353 Epoch: 400, RMSE = 2.8811, 기울기 a = 2.2871, y 절편 b = 79.0770 Epoch: 500, RMSE = 2.8810, 기울기 a = 2.2927, y 절편 b = 79.0438 Epoch: 600, RMSE = 2.8810, 기울기 a = 2.2958, y 절편 b = 79.0249 Epoch: 700, RMSE = 2.8810, 기울기 a = 2.2976, y 절편 b = 79.0142 Epoch: 800, RMSE = 2.8810, 기울기 a = 2.2987, y 절편 b = 79.0081 Epoch: 900, RMSE = 2.8810, 기울기 a = 2.2992, y 절편 b = 79.0046 Epoch: 1000, RMSE = 2.8810, 기울기 a = 2.2996, y 절편 b = 79.0026 Epoch: 1100, RMSE = 2.8810, 기울기 a = 2.2998, y 절편 b = 79.0015 Epoch: 1200, RMSE = 2.8810, 기울기 a = 2.2999, y 절편 b = 79.0008 Epoch: 1300, RMSE = 2.8810, 기울기 a = 2.2999, y 절편 b = 79.0005 Epoch: 1400, RMSE = 2.8810, 기울기 a = 2.3000, y 절편 b = 79.0003 Epoch: 1500, RMSE = 2.8810, 기울기 a = 2.3000, y 절편 b = 79.0002 Epoch: 1600, RMSE = 2.8810, 기울기 a = 2.3000, y 절편 b = 79.0001 Epoch: 1700, RMSE = 2.8810, 기울기 a = 2.3000, y 절편 b = 79.0001 Epoch: 1800, RMSE = 2.8810, 기울기 a = 2.3000, y 절편 b = 79.0000 Epoch: 1900, RMSE = 2.8810, 기울기 a = 2.3000, y 절편 b = 79.0000 Epoch: 2000, RMSE = 2.8810, 기울기 a = 2.3000, y 절편 b = 79.0000 | cs |
에포크(Epoch) : 입력 값에 대해 몇 번이나 반복하여 실험했는지를 나타냄.
=> 평균 제곱근 오차(Root Mean Square Error, RMSE)의 변화, 기울기 a가 2.3에 수렴하는 것 y 절편 b가 79에 수렴하는 과정을 볼 수 있음. 이는 최소 제곱법으로 확인한 결과와 같음
똑같은 방식으로 x가 여러 개인 다중 선형 회귀에서도 사용이 가능하다.
5. 다중 선형 회귀란?
실제 성적 사이에도 오차가 있다. 그 이유는 공부한 시간 이외의 다른 요소가 성적에 영향을 끼쳤기 때문이다.
추가로 과외 수업 횟수를 조사했다.
두 개의 독립 변수 x1과 x2가 생겼다. 이를 사용해 종속 변수 y를 만들어야 한다. 기울기를 두 개 구해야 한다.
6. 코딩으로 확인하는 다중 선형 회귀 실습
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 tensorflow as tf # x1, x2, y의 데이터 값 data = [[2, 0, 81], [4, 4, 93], [6, 2, 91], [8, 3, 97]] x1 = [x_row1[0] for x_row1 in data] x2 = [x_row2[1] for x_row2 in data] # 새로 추가되는 값 y_data = [y_row2[2] for y_row2 in data] learning_rate = 0.1 a1 = tf.Variable(tf.random_uniform([1], 0, 10, dtype = tf.float64, seed=0)) a2 = tf.Variable(tf.random_uniform([1], 0, 10, dtype = tf.float64, seed=0)) # 새로 추가되는 값 b = tf.Variable(tf.random_uniform([1], 0, 100, dtype = tf.float64, seed=0)) # 새로운 방정식 y = a1x1 + a2x2 + b y = a1 * x1 + a2 * x2 + b # 평균 제곱근 오차, 텐서플로 RMSE 함수 rmse = tf.sqrt(tf.reduce_mean(tf.square( y - y_data ))) # 경사 하강법, RMSE값을 최소로 하는 값 찾기 gradient_decent = tf.train.GradientDescentOptimizer(learning_rate).minimize(rmse) # 텐서플로 실행 후 결괏값 출력 with tf.Session() as sess: # 변수 초기화 sess.run(tf.global_variables_initializer()) # 2001번 실행(0번째를 포함하므로) for step in range(2001): sess.run(gradient_decent) # 100번마다 결과 출력 if step % 100 == 0: print("Epoch: %.f, RMSE = %.04f, 기울기 a1 = %.4f, 기울기 a2 = %.4f, y 절편 b = %.4f" % (step, sess.run(rmse), sess.run(a1), sess.run(a2), sess.run(b))) | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | Epoch: 0, RMSE = 49.1842, 기울기 a1 = 7.5270, 기울기 a2 = 7.8160, y 절편 b = 80.5980 Epoch: 100, RMSE = 1.8368, 기울기 a1 = 1.1306, 기울기 a2 = 2.1316, y 절편 b = 78.5119 Epoch: 200, RMSE = 1.8370, 기울기 a1 = 1.1879, 기울기 a2 = 2.1487, y 절편 b = 78.1057 Epoch: 300, RMSE = 1.8370, 기울기 a1 = 1.2122, 기울기 a2 = 2.1571, y 절편 b = 77.9352 Epoch: 400, RMSE = 1.8370, 기울기 a1 = 1.2226, 기울기 a2 = 2.1607, y 절편 b = 77.8636 Epoch: 500, RMSE = 1.8370, 기울기 a1 = 1.2269, 기울기 a2 = 2.1622, y 절편 b = 77.8335 Epoch: 600, RMSE = 1.8370, 기울기 a1 = 1.2288, 기울기 a2 = 2.1628, y 절편 b = 77.8208 Epoch: 700, RMSE = 1.8370, 기울기 a1 = 1.2295, 기울기 a2 = 2.1631, y 절편 b = 77.8155 Epoch: 800, RMSE = 1.8370, 기울기 a1 = 1.2299, 기울기 a2 = 2.1632, y 절편 b = 77.8133 Epoch: 900, RMSE = 1.8370, 기울기 a1 = 1.2300, 기울기 a2 = 2.1632, y 절편 b = 77.8124 Epoch: 1000, RMSE = 1.8370, 기울기 a1 = 1.2301, 기울기 a2 = 2.1633, y 절편 b = 77.8120 Epoch: 1100, RMSE = 1.8370, 기울기 a1 = 1.2301, 기울기 a2 = 2.1633, y 절편 b = 77.8118 Epoch: 1200, RMSE = 1.8370, 기울기 a1 = 1.2301, 기울기 a2 = 2.1633, y 절편 b = 77.8117 Epoch: 1300, RMSE = 1.8370, 기울기 a1 = 1.2301, 기울기 a2 = 2.1633, y 절편 b = 77.8117 Epoch: 1400, RMSE = 1.8370, 기울기 a1 = 1.2301, 기울기 a2 = 2.1633, y 절편 b = 77.8117 Epoch: 1500, RMSE = 1.8370, 기울기 a1 = 1.2301, 기울기 a2 = 2.1633, y 절편 b = 77.8117 Epoch: 1600, RMSE = 1.8370, 기울기 a1 = 1.2301, 기울기 a2 = 2.1633, y 절편 b = 77.8117 Epoch: 1700, RMSE = 1.8370, 기울기 a1 = 1.2301, 기울기 a2 = 2.1633, y 절편 b = 77.8117 Epoch: 1800, RMSE = 1.8370, 기울기 a1 = 1.2301, 기울기 a2 = 2.1633, y 절편 b = 77.8117 Epoch: 1900, RMSE = 1.8370, 기울기 a1 = 1.2301, 기울기 a2 = 2.1633, y 절편 b = 77.8117 Epoch: 2000, RMSE = 1.8370, 기울기 a1 = 1.2301, 기울기 a2 = 2.1633, y 절편 b = 77.8117 | cs |
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 35 36 37 38 39 | import numpy as np import statsmodels.api as statm import statsmodels.formula.api as statfa import pandas as pd import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D data = [[2, 0, 81], [4, 4, 93], [6, 2, 91], [8, 3, 97]] X = [i[0:2] for i in data] Y = [i[2] for i in data] X_1=statm.add_constant(X) results=statm.OLS(Y,X_1).fit() hour_class=pd.DataFrame(X,columns=['study_hours','private_class']) hour_class['Score']=pd.Series(Y) model = statfa.ols(formula='Score ~ study_hours + private_class', data=hour_class) results_formula = model.fit() a, b = np.meshgrid(np.linspace(hour_class.study_hours.min(),hour_class.study_hours.max(),100), np.linspace(hour_class.private_class.min(),hour_class.private_class.max(),100)) X_ax = pd.DataFrame({'study_hours': a.ravel(), 'private_class': b.ravel()}) fittedY=results_formula.predict(exog=X_ax) fig = plt.figure() graph = fig.add_subplot(111, projection='3d') graph.scatter(hour_class['study_hours'],hour_class['private_class'],hour_class['Score'], c='blue',marker='o', alpha=1) graph.plot_surface(a,b,fittedY.reshape(a.shape), rstride=1, cstride=1, color='none', alpha=0.4) graph.set_xlabel('study_hours') graph.set_ylabel('private_class') graph.set_zlabel('Score') plt.show() | cs |
1차원 예측 직선이 3차원 '예측 평면'으로 바뀌었다.
좀 더 정밀한 예측을 할 수 있게 됐다.
'인공지능 > 딥 러닝' 카테고리의 다른 글
[모두의 딥러닝] 06. 퍼셉트론 (0) | 2018.05.06 |
---|---|
[모두의 딥러닝] 05. 참 거짓 판단 장치: 로지스틱 회귀 (0) | 2018.05.06 |
[모두의 딥러닝] 03. 가장 훌륭한 예측선 긋기: 선형회귀 (1) | 2018.04.05 |
[모두의 딥러닝] 02. 처음 해 보는 딥러닝 (0) | 2018.04.05 |
[모두의 딥러닝] 01. 파이썬과 텐서플로, 케라스 설치하기 (0) | 2018.03.27 |
댓글