블로그 이미지
윤영식
Application Architecter, Full Stacker, KnowHow Dispenser and Bike Rider

Publication

Statistics Graph

Recent Comment

'gradient descent'에 해당되는 글 2

  1. 2018.08.11 [Cost Function] 로지스틱 회귀의 비용함수 이해
  2. 2018.07.19 [Machine Learning - NG] Gradient Descent
2018.08.11 16:12 AI Deep Learning

텐서플로우 강좌를 들으면서 다음의 모델을 실습으로 쥬피터에 코딩을 했다. 여기서 Cost function을 짤때 log함수를 왜 사용하고 앞에 - (마이너스)값은 왜 붙이는지 정리해 본다. 



준비

  - 아나콘다 설치

  - jupyter notebook 실행

  - python v3 


import tensorflow as tf


input_data = [[1, 5, 3, 7, 8, 10, 12]]

label_data = [0, 0, 0, 1, 0]


INPUT_SIZE = 7

HIDDEN1_SIZE=10

HIDDEN2_SIZE=8

CLASSES = 5

Learing_Rate = .05


x = tf.placeholder(tf.float32, shape=[None, INPUT_SIZE])

y = tf.placeholder(tf.float32, shape=[CLASSES])


feed_dict = {x: input_data, y: label_data}


W_h1 = tf.Variable(tf.truncated_normal(shape=[INPUT_SIZE, HIDDEN1_SIZE], dtype=tf.float32))

b_h1 = tf.Variable( tf.zeros([HIDDEN1_SIZE]), dtype=tf.float32)

hidden1 = tf.sigmoid(tf.matmul(x, W_h1) + b_h1)


W_h2 = tf.Variable(tf.truncated_normal(shape=[HIDDEN1_SIZE, HIDDEN2_SIZE], dtype=tf.float32))

b_h2 = tf.Variable( tf.zeros([HIDDEN2_SIZE]), dtype=tf.float32)

hidden2 = tf.sigmoid(tf.matmul(hidden1, W_h2) + b_h2)


W_o = tf.Variable(tf.truncated_normal(shape=[HIDDEN2_SIZE, CLASSES], dtype=tf.float32))

b_o = tf.Variable( tf.zeros([CLASSES]), dtype=tf.float32)

output = tf.sigmoid(tf.matmul(hidden2, W_o) + b_o)


cost = tf.reduce_mean(-y*tf.log(output)-(1-y)*tf.log(1-output))

train = tf.train.GradientDescentOptimizer(Learing_Rate).minimize(cost)


sess= tf.Session()

init = tf.initialize_all_variables()

sess.run(init)


for i in range(10):

    _, loss = sess.run([train, cost], feed_dict = feed_dict)

    print('step:', i)

    print('lost:', loss)


//결과

step: 0
lost: 0.794413
step: 1
lost: 0.780786
step: 2
lost: 0.767388
step: 3
lost: 0.754181
step: 4
lost: 0.741128
step: 5
lost: 0.728179
step: 6
lost: 0.715276
step: 7
lost: 0.702345
step: 8
lost: 0.689285
step: 9
lost: 0.675957



cost(비용) 함수의 목적은 비용 판단을 통해 올바른 W(가중치, 기울기)와 b(바이어스, 시작점)을 찾는 것이다. 다시 말하면 목표하는 W과 b를 찾을 수 있다면, 어떤 형태가 되었건 비용함수라고 부를 수 있다는 뜻이다. 



Inference => Loss => Training => Evaluation  순서로 진행을 한다. 좋은 예제로 MNIST.py 구글 강좌 예제 소스를 먼저 참조해 보자.


- Inference: 가설함수 수립

- Loss: 비용함수 수립

- Training: 최적화 작업 수행하여 Loss (Cost)가 작아지는 W, b 값을 구함

- Evaluation: 검증은 Training을 통해 구해진 W, b가 가설함수에 적용되어 test data를 넣었을 때, Labeled data와 일치하는지 검증함




Step-1) 가설함수 

  - matmul 은 Matrix Mutiply의 약어이다. 

  - sigmoid는 binary classification의 한계를 넘기 위해 적용. sigmoid 그래프는 중심축 0을 중심으로 좌측은 0으로, 우측을 1로 수렴한다.

  - 가설함수 (Hyphothesis):  H(x) = sigmoid(Wx + b) 로 결과값은 0 또는 1의 값을 갖는다. 수학 공식으로 하면,

     H(x) = 1 / (1 + math.exp(-(Wx + b))

     소스에서는  output = tf.sigmoid(tf.matmul(hidden2, W_o) + b_o) 이 가설함수이다.



Step-2) 비용함수

  - 가설함수를 정의했다면 해당 가설 함수의 적정한 W, b를 찾기 위해 비용(Cost) 함수를 정의한다.

     비용함수는 예측값과 실제값의 차이에 대한 평균값을 구한다. 로지스틱 회귀에 사용되는 실제 비용함수를 수학 공식으로 하면,

     cost = (1/n) * sum( -y_origin * log(sigmoid(Wx + b)) - (1 - y_origin) * log(1 - (sigmoide(Wx + b))) 

       n: 트레이닝 데이이터 수

       y_origin: 트레이닝에 에 사용될 x에 대한 입력값

     소스에서는  cost = tf.reduce_mean(-y*tf.log(output)-(1-y)*tf.log(1-output)) 이 비용함수이다. 


  - 비용함수에서 가설함수의 e를 사용하는게 아니라 log를 사용하는 이유는 e를 통해 비용함수를 그리면 다음과 같이 나오기 때문에 매끈한 경사를 만들기 위해 e의 역치함수인 log를 사용한다. 

    비용함수는 y=1 일때와 y=0 일때는 나누어 계산한다. 


  - 측정(실제 입력)값 y=1 일때는 -log(H(x)), -log(가설함수) 즉 -log(sigmoide(Wx + b)) 를 사용하고 그래프로 보면 sigmoid(Wx+b)가 0~1사이에 있고 -log(0~1)을 그린다. 

     H가 1이면 cost(1) = 0 이 되고, H가 0이면 cost = 무한대가 된다.

     좌측의 밥그릇이 된다.

     측정(실제 입력)값 y=0 일때는 가설값이 0이 되어야 한다. 이는 0에 가까울 수록 cost는 0에 가까워야 한다. -log(1 - sigmoid(Wx + b)) 되고 log(1 - (0~1)) 이 된다. 

    우측의 밥그릇이 된다.

     요약하면 -log(h)는 좌측, -log(1-h)는 우측이다. 


  * 주의할 것은 Linear Regression (binary classification)을 하기 위해 평균에 제곱을 하지 않는다. 

 

  - y=0 일때와 y=1일때의 각 수식을 하나의 수직으로 만들기 위해 다음 공식을 사용해 합쳐서 표현한다. 소스에서는 -y*tf.log(output)-(1-y)*tf.log(1-output) 이 된다. 

  


      y * A + (1-y) * B => y * -log(H(x)) + (1-y) * -log(1 - H(x)) => -y*log(H(x)) - (1-y)*log(1 - H(x))  => -( y*log(H(x)) + (1-y)*log(1 - H(x)) )


  - 이것을 다시 재구성하면 다음과 같다. 소스에서는 cost = tf.reduce_mean(-y*tf.log(output)-(1-y)*tf.log(1-output)) 이다.

  



Step-3) 옵티마이저

  -  코스트함수가 정해지면 옵티마이저를 설정한다. 

      경사하강법 (GradientDescent)는 cost(W)을 미분을 적용해서 W의 다음 위치를 계산하는 공식이다. 다음 위치로 이동하는 것은 Learning Rate (이동하는 Step 크기)로 정해진다.

  - W 와 b의 적정값을 계산하기 위해 비용함수를 만들었다면 학습을 통해 GradientDescent가 W와 b값을 구한다. 여기서 나온 W,b를 통해 예측을 수행한다.

  - 소스는  tf.train.GradientDescentOptimizer(Learing_Rate).minimize(cost) 이다.

  - GradientDescent Optimizer는 gradient를 계산해서 변수에 적용하는 일을 동시에 하는 함수이다. W와 b를 적절하게 계산해서 변경하는 역할을 하며, 그 진행 방향이 cost가 작아지는 쪽으로 수행한다. train을 수행하게 되면 텐서 그래프의 모든 변수의 값이 자동 변경되며 계산된다. 소스는 _, loss = sess.run([train, cost], feed_dict = feed_dict) 이다.


  - 또한 텐서를 run하기 전에 그래프에 연결된 모든 variable을 초기화해야 한다. 

  - 옵티마이저 설명 참조

  



Step-4) 가절 검증

  - Accuracy or Evaluation

  - output 은 hypothesis 가설함수로 이것을 실제 테스트를 해본다. 

  - Linear에서 x, y 데이터를 placeholder를 통해 train 시키고, 최종 W,b가 구해진 가설함수에 대해서 test 데이터를 넣어 보고 예측이 맞는지 검증한다. 

  - Linear Regression 예 (Linear Regression에 대한 이해 참조)

import tensorflow as tf

x_data = [1.,2.,3.]

y_data = [1.,2.,3.]


W = tf.Variable(tf.random_uniform([1], -100., 100.))

b = tf.Variable(tf.random_uniform([1], -100., 100.))


X = tf.placeholder(tf.float32)

Y = tf.placeholder(tf.float32)


h = W * X + b

cost = tf.reduce_mean(tf.square(h - Y))


rate = tf.Variable(0.1)

op = tf.train.GradientDescentOptimizer(rate)

train = op.minimize(cost)


init = tf.initialize_all_variables()


sess = tf.Session()

sess.run(init)


for step in range(2001):

    sess.run(train, feed_dict = {X: x_data, Y: y_data})

    if step % 100 == 0:

        print(step, sess.run(cost, feed_dict={X: x_data, Y: y_data}), sess.run(W), sess.run(b))


print('Test:', sess.run(h, feed_dict={X: 5}))




<참조>

- 김성훈 교수님 강좌 요약 블로그

- 조대협의 로지스틱 회귀 분석 블로그

- Tensorflow 유튜브 강의

- 로지스틱 회귀 이해

- 선형, 비선형 회귀 모델의 이해

- Tensorflow의 자료형 이해, 상수/변수/플레이스홀더 이해

- 선형 회귀를 Tensorflow로 구현하기

posted by peter yun 윤영식

앤드류 응교수님의 ML 강좌를 정리한다.





Gradient Descent


hypothesis 함수를 적절한 parameter를 가지고 검증할 필요가 있다. 아래 그림과 같이 특정 파라미터 값에 따라 하강한 위치가 틀려 질 수 있다. cost 함수를 최소값을 찾는 것인데, 잘 못된 곳으로 내려가면 해당 값이 최소인것으로 오인할 수 있다. 


- 하강의 스텝(learning rate, 얼마의 보폭으로 하강하는지 정도)은 알파이다. 

- 하강의 방향(direction)-기울기-는 미분(derivative)으로 계산한다.

- starting point가 틀리면 도착한 지점이 틀리게 나왔다. 



- 수학적으로 Gradient descent algorithm을 사용한다. 

   알파: Learning rate * 미분계수

   := 대입기호, = truth assertion

   temp0, temp1을 구한다음 세타0, 세타1에 대입한다. 







미분계수를 이용한 Gradient Descent 알고리즘 이해 


함수의 tanzent값을 구함. 즉, 기울기를 구함. 


- 세타1이 최소값보다 클때 미분계수에 의한 탄젠트 기울기값은 양수이다. 

- 세타1이 최소값보다 작을때 미분계수에 의한 탄젠트 기울기값은 음수이다. 




- 알파(learning rate)에 따라 하강 step이 정해진다.

  + 알파값이 작으면 최소값을 찾는데 느리고

  + 알파값이 크면 최소값을 못 찾고 멀어진다. 




- 하강 기울기가 줄어들 때마다 세타1의 값이 점점 작아진다. 이것은 공식에서 세타1 - 알파*미분계수(기울기 slop값) 을 빼주기 때문에 가능하다. 알파값은 상수 유지 가능.

- J(세타1) 이라는 cost function 그래프에서 미분계수값이 최소가 되는 곳의 세타1의 값을 알 수 있다.

즉, 미분계수 0을 찾는게 목적이다. 


세타1 := 세타1 - 알파 * 0 







비용함수와 기울기 하강 함수를 같이 사용하기


Gradient Descent 알고리즘과 비용 함수 J(세타1, 세타2)




- 좌측 좌표가 가운데로 하강을 할 수록 기울기가 점점 변경된다. 선형 회귀는 항시 하나의 최적값을 갖는 밥그릇의 Convex(볼록) 모양을 갖는다. 




결론 Cost function j의 해답을 얻기 위해 하강 기울기 알고리즘을 사용한다. 






Gradient Descent for Linear Regression


선형 회귀의 경우 새로운 형태의 Gradient Descent방정식이 도출된다. 

 - m: training set 사이즈

 - 세타0: 초기시작값 - 상수

 - 세타1: 기울기값 - 변경값 

 - xi, yi: training data set



Gradient Descent 식에 J(세타)즉 cost founction을 넣어서 식을 간략히 하면 다음과 같이된다. 





참조


posted by peter yun 윤영식
prev 1 next