2019년 6월 24일 월요일

#모모딥2 Linear Regression + Gradient Descent Algorithm - Part2

모모딥 linear regression - #2
ML의 목표
Cost 가 최소가 되는 w, b 를 찾는것

Hypothesis and Cost

Hypothesis function(가설함수)
H(x)=Wx+bH (x) = Wx + b
cost = tf.reduce_mean(tf.square(hypothesis - y_data))
Cost function
Cost(W,b)=1mi=1m(Wxiyi)2Cost(W,b) = \frac{1}{m} \sum_{i=1}^m(Wx_i-y_i)^2

tensorflow를 이용해 표현해보면
Hypothesis = W * x_data + b
Cost = tf.reduce_mean(tf.square(hypothesis - y_data))
  • tf.reduce_mean 은 한 차원을 줄인 평균값을 구하는 함수
  • tf.square 은 제곱을 나타내는 함수


공부하기에 앞서 우리는 가설 함수를 보다 단순하게 보기 위해

Hypothesis function(가설함수)
H(x)=WxH (x) = Wx
Cost function
Cost(W)=1mi=1m(Wxiyi)2Cost(W) = \frac{1}{m} \sum_{i=1}^m(Wx_i-y_i)^2
이렇게 b를 제외하고 재정의 하겠습니다.

해당 과정은 선형대수에서 W가 matrix 로 표현 되면서
H(x)=Wx+bH (x) = Wx + b
위의 연산 과정에서 b가 W matric안에 들어 갈 수 있기 때문입니다.


그럼 이제 W 값에 따른 Cost function 의 최솟값을 찾아야 합니다.
우리의 Cost함수
Cost(W)=1mi=1m(Wxiyi)2Cost(W) = \frac{1}{m} \sum_{i=1}^m(Wx_i-y_i)^2
현재 x(input data) , y(output data) 는 상수값으로 주어지고 있고
W의 변화에 따라 Cost(W)도 변하게 됩니다.
그럼 특정 Cost(W)는 좌표평면 위에서 이차함수의 모양을 그리게 되고
특정 W 에서 Cost(W)가 최소가 되는 점을 발견할 수 있습니다.
그런데 이러한 과정을 컴퓨터가 찾을 수 있도록 설계한것이 바로
Gradient descent algorithm 입니다.

Gradient Descent Algorithm(경사하강법)

w, b 뿐만 아니라 많은 parameter에 대해서도 사용가능합니다.

사용방법

  1. 임의의 value로 w와 b를 설정
  2. gradient를 구해서 cost가 최소가 되는 방향으로 W 와 b update
  3. cost가 최소가 될때까지 반복
이때 gradient를 사용하는 이유는
우리가 눈으로 볼수 있는 이차함수의 최소는 기울기가 0인 지점이기 때문에 이를 이용합니다.

Gradient descent algorithm

W:=Wα1mi=1m(W(xi)yi)xiW := W- \alpha \frac{1}{m} \sum_{i=1}^m(W(x_i)-y_i)x_i
위의 식은
W에서 Cost(W)의 함수를 W에 대해 편미분한 값을 α\alpha(learning rate)를 곱해서 빼준 값으로 update해주겠다는 의미입니다.

이때 α\alpha가 learning rate(학습속도)의 역할을 하는데
일반적으로 작은 상수값을 사용합니다.

learning rate 설정에서 중요한것

  • 너무 크게 설정할 경우 : W 값의 변화가 급격하게 이루어지기 때문에 원하는 값이 안 나오고 NaN 값이 나올수 있으며
  • 너무 작게 설정할 경우 : 학습속도가 느려질 수 있다.


나중에 위의 코드를 구현함에 있어서 초기 W값을 아무렇게나 설정해줘도 되는 이유는 최소값을 기준으로
  • 왼쪽에는 기울기가 - 이기때문에 W값을 증가시키는 방향으로
  • 오른쪽은 기울기가 + 이므로 W값을 감소시키는 방향으로
update되기 때문이다.
Gradient descent Algorithm을 사용하는데 주의해야할 점은
convex function에서 사용가능 하다는 것인데
(이는 local minimum 과 global minimum이 일치해야하기 때문이다)
convex function이란?
function 위의 임의의 두 점을 이은 할선이 두점을 이은 곡선보다 위에 있는 함수(= 볼록함수)

Pure Python로 구현한 Cost function

import numpy as np

X = np.array([1, 2, 3]) #python 의 numpy library를 사용하여 [1,2,3]을 array로 만든다

Y = np.array([1, 2, 3])


def  cost_func(W, X, Y): #cost function의 평균구하는 수식을 이와 같이 구현하였다.
    c =  0
 for i in  range(len(X)):
  c += (W * X[i] - Y[i]) **  2
 return c /  len(X)

for feed_W in np.linspace(-3, 5, num=15): #-3 ~ 5 까지 15간격으로 나누어 for 문을 실행시켜준다.
 curr_cost = cost_func(feed_W, X, Y)
 print("{:6.3f} | {:10.5f}".format(feed_W, curr_cost)) #python formatting을 이용하여 출력해주도록 한다
W값에 따라 x_data와 y_data를 넣었을때 cost의 변화를 확인 할 수 있다.

TensorFlow를 이용 Cost function

X = np.array([1, 2, 3])
Y = np.array([1, 2, 3])

def cost_func(W, X, Y):
  hypothesis = X * W #가설함수
  return tf.reduce_mean(tf.square(hypothesis - Y))#Cost함수를 tf의 메소드를 이용해서 구현

W_values = np.linspace(-3, 5, num=15) #Pure python과 같은데 미리 변수로 참조한다

cost_values = [] # W에 따라 변하는 Cost를 담기위한 list이다

for feed_W in W_values:
    curr_cost = cost_func(feed_W, X, Y)
    cost_values.append(curr_cost) 
    print("{:6.3f} | {:10.5f}".format(feed_W, curr_cost))
이를 바탕으로 Gradient Algorithm을 구현해보면
tf.set_random_seed(0)  # random seed 를 초기화 시켜 다음 실행에도 같게 실행되게 한다

x_data = [1., 2., 3., 4.]
y_data = [1., 3., 5., 7.]

W = tf.Variable(tf.random_normal([1], -100., 100.)) #정규분포를 따르는 random number를 1개 생성해서 W에 할당

# W = tf.Variable([5.0]) 이렇게 직접 할당해 줄 수도 있는데 초기 W값의 설정에 따라 
# 도달하는 step이 달라 질 수 있다.

for step in range(300):
    hypothesis = W * X
    cost = tf.reduce_mean(tf.square(hypothesis - Y))

    alpha = 0.01 #적당히 작은 수를 alpha(learning rate)로 잡는다
    gradient = tf.reduce_mean(tf.multiply(tf.multiply(W, X) -Y, X))
   
    #기울기를 tf 제공 메서드를 이용해서 구해준다
    
    descent = W - tf.multiply(alpha, gradient)
    
    #그리고 W의 변화를 descent에 저장해주고
    
    W.assign(descent) #W에 update해준다
    
    if step % 10 == 0:   #10번의 step마다 출력한다
        print('{:5} | {:10.4f} | {:10.6f}'.format(step, cost.numpy(), W.numpy()[0]))



강의상에는 경사하강법보다 먼저 나와 있었는데 Gradient descent Algorithm을 하고 보면 더 이해가 잘 될것 같아서 뒷부분에 simple linear regression code도 첨부합니다.

Simple linear Regression

import tensorflow as tf
import numpy as np

tf.enable_eager_execution() #tf 를 즉시 실행합니다

# Data
x_data = [1, 2, 3, 4, 5]
y_data = [1, 2, 3, 4, 5]


# W, b initialize
W = tf.Variable(2.9) #텐서플로우의 변수를 지정해주는것
b = tf.Variable(0.5) #나중에는 랜덤값을 넣지만 일단은 설정해주자
learning_rate =  0.01

# W, b update
for i in  range(100):
 # Gradient descent
 with tf.GradientTape() as tape: #텐서플로우의 GradientTape에 with구문의 내용이 기록됨
  hypothesis = W * x_data + b #우리의 가설 함수를 지정해주고
  cost = tf.reduce_mean(tf.square(hypothesis - y_data)) #cost의 수식을 tensor 코드로 나타낸다
 
 W_grad, b_grad = tape.gradient(cost, [W, b]) #해당 cost식을 W와 B에 대해서 편미분으로 각각 기울기를 구해준다
 W.assign_sub(learning_rate * W_grad) #assing_sub의 의미는 A-=B 와 같은 의미다
 b.assign_sub(learning_rate * b_grad)

 if i %  10  ==  0: #10번씩 시행될때마다
  print("{:5}|{:10.4f}|{:10.4f}|{:10.6f}".format(i, W.numpy(), b.numpy(), cost)) #문자열 formatting을 이용해 print


출처 : 모두를 위한 딥러닝 2

가장 많이 본 글