텐서플로우 강좌를 들으면서 다음의 모델을 실습으로 쥬피터에 코딩을 했다. 여기서 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}))
<참조>
'Deep Learning' 카테고리의 다른 글
[자연어 처리] Word2Vec 강의 정리 (0) | 2018.11.25 |
---|---|
[뉴로모픽] 인공지능과 하드웨어의 결합 워크샵 (0) | 2018.10.18 |
[인공지능] 공부 여정 (0) | 2018.07.31 |
[ML] 11주차 - 독립 특성 발견 (0) | 2015.03.07 |
[ML] 10주차 - 고급 분류 기법 (0) | 2015.02.28 |