본문 바로가기
AI

ML05-1-logistic_regression : Binary Classification

by 월곡동로봇팔 2019. 10. 23.

이번 게시물은 logistic_regression에서도 Binary Classification 이다.

 

먼저 logitistic regression에 대해서 살펴보자

 

logistic regression은 선들로 인해 구역을 구분지어놔서, 실제 데이터가 어디에 속하는지 classification을 쓸 수 있다.

예제로 binary classification을 이용하여 (0, 1)을 이용하여 학습, 악성종양인지 양성종양인지 진단가능하다.

 

우리가 실제 데이터를 다루다보면, 실수를 논하기 때문에 값들이 커지게 된다. 

그래서 sigmoid, (1/ (1+e^x)) 함수를 쓰니 0~1로 수렴하면서 데이터들간의 간격이 줄었고,

hypothesis를 0-1로 맞추기위해 sigmoid를 쓴다.

 

sigmoid function

import tensorflow as tf
tf.set_random_seed(777)  # for reproducibility, tf로 임의의 값을 넣었을 때, 그 값은 일정하다.

x_data = [[1, 2],
          [2, 3],
          [3, 1],
          [4, 3],
          [5, 3],
          [6, 2]]
y_data = [[0],
          [0],
          [0],
          [1],
          [1],
          [1]]

# placeholders for a tensor that will be always fed.
# weight의 shape를 항상 신경써야한다.
X = tf.placeholder(tf.float32, shape=[None, 2])
Y = tf.placeholder(tf.float32, shape=[None, 1])

W = tf.Variable(tf.random_normal([2, 1]), name='weight')
b = tf.Variable(tf.random_normal([1]), name='bias')

# Hypothesis using sigmoid: tf.div(1., 1. + tf.exp(tf.matmul(X, W)))
hypothesis = tf.sigmoid(tf.matmul(X, W) + b)

tf.set_random_seed(777)은 내가 Tensorflow에 W,b를 임의로 넣을 때, 그 넣는 난수의 처음 값을 항상 일정하게 준다. 저 seed를 지정하지 않으면, 내가 python 파일을 실행할 때마다 cost, W, b 값들은 항상 변할 것이다.

 

X, Y를 똑같이 placeholder로 정의하였다. 여기서 우리는 앞으로 data의 형태를 알 것이며, 입력받는 data의 format을 알기 때문에, shape를 [None, 2],[None, 1] 로 해두었다. (항상 X, Y, W, b의 shape는 신경쓰기!!!)

 

Hypothesis 는 tf.sigmoid를 써서 연산하였다.

 

 

# cost/loss function
cost = -tf.reduce_mean(Y * tf.log(hypothesis) + (1 - Y) * tf.log(1 - hypothesis))

우리는 여기서 sigmoid 함수의 cost 함수가 달라짐을 알 수 있다. cost함수를 기존의 cost함수로 적용한다면, 단계가 거듭하면 할수록 cost함수에 변곡점이 많이 존재한다. 그렇다면 cost함수를 미분했을 때 0으로 수렴하는 값들이 많이 존재하며, 제대로 된 cost의 최솟값을 가리킬때의 weight를 조정할 수가 없다.

 

sigmoid cost function

따라서 변곡점이 많은 함수일 때는, log를 취해주면 변곡점이 사라지고 완만한 곡선이 된다.

  1. 만약 y = 1인 경우는 -log(H(x))이며 , Hypothesis가 1로 수렴할 때 cost 값이 0으로 수렴한다.
  2. 만약 y = 0인 경우는 -log(1-H(x))이며, Hypothesis가 0으로 수렴할 때 cost 값이 0으로 수렴한다.

우리는 y = 1, y = 0인지 binary classification을 하는 것이기에! cost함수를 위와 같이 이렇게 정의한다.

cost_function

train = tf.train.GradientDescentOptimizer(learning_rate=0.01).minimize(cost)

# Accuracy computation
# True if hypothesis>0.5 else False
predicted = tf.cast(hypothesis > 0.5, dtype=tf.float32)
accuracy = tf.reduce_mean(tf.cast(tf.equal(predicted, Y), dtype=tf.float32))

print('predicted : ', predicted)

# Launch graph
with tf.Session() as sess:
    # Initialize TensorFlow variables
    sess.run(tf.global_variables_initializer())

    for step in range(100001):
        # train은 값 안넣어도 무방
        # def run(self, fetches, feed_dict=None, options=None, run_metadata=None)
        # sess.run은 fetches가 딕셔너리, 튜플, 리스트, numpy 스타일로 들어오게 된다.
        # fetches에서 train이 빠지면 학습이 되지 않기 때문에 값이 일정하게 된다.
        cost_val, train_val = sess.run([cost, train], feed_dict={X: x_data, Y: y_data})
        if step % 2000 == 0:
            print(step, "cost_val : ",cost_val)
            # print(step, "train_val : ", type(train_val))

    # Accuracy report
    h, c, a = sess.run([hypothesis, predicted, accuracy],
                       feed_dict={X: x_data, Y: y_data})
    print("\nHypothesis: ", h, "\nCorrect (Y): ", c, "\nAccuracy: ", a)

 

predicted를 tf.cast를 썼다. tf.cast는 안에 조건문이 True 이면 1, 아니면 0을 도출해낸다. dtype은 tf.float32이다.

accuracy 는 predicted와 Y가 같다면 True를 반환하고 tf.cast에 의해서 1을 반환한다. 이를 다 더하여 실제 accuracy 를 측정한다.

 

여기서 제일 중요한 포인트는!

 

  1.  Sigmoid 라는 함수! 그리고 왜 쓰는지 (sigmoid를 대신해서 나온 함수들이 굉장히 많다. ex) ReLu,,,, 등등)
  2.  Sigmoid의 cost function이 왜 log로 이루어져있고, y=0 or y=1일때 함수가 다른지

이 가정들이 굉장히 중요하다.

댓글