Logistic Regression


Logistic Regression의 기본 개념

Linear regression 방식은 0.5를 기점으로 1과 0을 만들기가 어렵다.
즉 학습 데이터에 너무 기울기가 민감하다는 점이다.

그래서 나온것이 logistic 함수이다.

Logistic Hypothesis
$$H(X) = \frac{1}{1+e^{-W^{T}X}} $$

Cost function을 
위의 Hoypothesis를 바로 이용해서 구하게 되면
구불 구불한 graph가 형셩되어 local minimum에 도달하는 문제가 발생 한다.

New cost function for logistic

그래서 새로 나온 cost 함수는 아래와 같다.

갑자기 log를 하는 이유는 exponential이 결국 cost 함수를 구불구불 하게 만들기 때문에 이러한 특성을 제거해 주기 위해서
log를 취하게 된다.

Logistic은 0~1 사이의 값이므로
g(z) = -log(z)를 생각해보면 결국 z가 1이면 0인 그래프가 생성된다.

cost함수의 정의는 결국 예측값이랑 실제값이랑 같으면 cost가 0이고
틀리면 패널티를 주는 것이 철학이다.

위함수 대로 cost를 계산해보면
H(x) = 1 -> cost(1) = 0 
H(x) = 0 -> cost(0) = infinite

반대로 y=0일때를 계산해 보면
H(x) = 0, cost = 0
H(x) = 1, cost = infinite

결국 우리가 목표로하는 cost 함수가 잘 만들어진것을 알 수 있다.
그리고 아래의 그래프를 보면 bowl 모양으로 local minimum이 없는 gradient decesent하기 좋은 graph shape인 것을 알 수 있다.
이러한 것을 convexity가 아주 좋다고 한다.

이것을 If조건 없이 간소화하면 아래와 같은 수식이 된다.
$$ C(H(x),y) = -y\log{(H(x))}+(1-y)\log{(1-H(x))}$$

Minimum cost, Gradient decent algorithm

이제 간소화된 hypothesis를 이용해서 cost function을 아래와 같이 생성한다.
$$ cost(W) = -\frac{1}{m}\sum{y\log{(H(x))}+(1-y)\log{(1-H(x))}}$$

그리고 이것을 partial derivative해서 gradient descent algorithm을 수행 한다.
derivative를 하는 것은 복잡하므로 그냥 그렇게 한다고만 생각하자.
컴퓨터가 자동으로 계산해 줄 것이다.

$$ W:=W-\alpha\frac{\partial}{\partial W}cost(W)$$

Logistic regression의 Cost function을 최적화 하는 코드는 아래와 같다.
아래의 GradientDescentOPtimizer함수가 tensorflow에 구현되어 있으니 이것을 그냥 사용하면 된다.

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

# Minimize
a = tf.Variable(0.1) # Learning rate, alpha
optimizer = tf.train.GradientDescentOptimizer(a)
train = optimizer.minimize(cost)

Logistic Regression Basic Implementation

간단한 Logistic Regression을 이용한 코드는 아래와 같다.

Training Data

#x0 x1 x2 y
1 2 1 0
1 3 2 0
1 3 4 0
1 5 5 1
1 7 5 1
1 2 5 1

Code

import tensorflow as tf
import numpy as np

xy = np.loadtxt('logisticTrain.txt', unpack=True, dtype='float32')

x_data = xy[0:-1]
y_data = xy[-1]

X = tf.placeholder(tf.float32)
Y = tf.placeholder(tf.float32)

W = tf.Variable(tf.random_uniform([1,len(x_data)],-1.0, 1.0))

# Our hypothesis
h = tf.matmul(W, X)
hypothesis = tf.div(1., 1+tf.exp(-h))

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

# Minimize
a = tf.Variable(0.1) # Learning rate, alpha
optimizer = tf.train.GradientDescentOptimizer(a)
train = optimizer.minimize(cost)

# Before starting, initialize the variables. We will `run` this first.
init = tf.initialize_all_variables()

# Launch the graph.
with tf.Session() as sess:
    sess.run(init)

    # Fit the line.
    for step in xrange(2000):
        sess.run(train, feed_dict={X:x_data, Y:y_data})
        if step % 200 == 0:
            print step, sess.run(cost, feed_dict={X:x_data, Y:y_data}), sess.run(W)

    # Test model: re-substitution error
    correct_prediction = tf.equal(tf.floor(hypothesis+0.5), Y)
    # Calculate accuracy
    accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
    print sess.run([hypothesis, tf.floor(hypothesis+0.5), correct_prediction, accuracy], feed_dict={X:x_data, Y:y_data})
    print "Accuracy:", accuracy.eval({X:x_data, Y:y_data})

    print '----------------------------------------'
    # study hour attendance
    # unseen data, but we don't know exact answer
    print sess.run(hypothesis, feed_dict={X:[[1], [2], [2]]}) > 0.5
    print sess.run(hypothesis, feed_dict={X:[[1], [5], [5]]}) > 0.5

    print sess.run(hypothesis, feed_dict={X:[[1, 1], [4, 3], [3, 5]]}) > 0.5

Result

1200 0.217096 [[-6.07444096  0.19686432  1.39010859]]
1400 0.205831 [[-6.5395813   0.2086037   1.48329437]]
1600 0.196362 [[-6.96585989  0.21742623  1.57006204]]
1800 0.188185 [[-7.36184502  0.22416407  1.65168989]]
[array([[ 0.00389449,  0.02695587,  0.46784386,  0.88681448,  0.92534608,
         0.79747105]], dtype=float32), array([[ 0.,  0.,  0.,  1.,  1.,  1.]], dtype=float32), array([[ True,  True,  True,  True,  True,  True]], dtype=bool), 1.0]
Accuracy: 1.0
----------------------------------------
[[False]]
[[ True]]
[[False  True]]

재치환 오류의 경우 0로 정확도가 1이 나온다.
그리고 2,2 5,5에 대해서는 False와 True가 나온다.
이것은 test data set을 임의로 만든 것이기 때문에 딱히 의미는 없다.
대략 생성된 모델로 저렇게 예측한 다는것을 보여주기 위함이다.

XOR with Logistic Regression

train.txt 데이터는 아래와 같다.
아무 편집기로나 하나 만들어 주면 된다.

import tensorflow as tf
import numpy as np

xy = np.loadtxt('train.txt', unpack=True)

x_data = xy[0:-1]
y_data = xy[-1]

X = tf.placeholder(tf.float32)
Y = tf.placeholder(tf.float32)

W = tf.Variable(tf.random_uniform([1,len(x_data)],-1.0, 1.0))

# Our hypothesis
h = tf.matmul(W, X)
hypothesis = tf.div(1., 1+tf.exp(-h))

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

# Minimize
a = tf.Variable(0.01) # Learning rate, alpha
optimizer = tf.train.GradientDescentOptimizer(a)
train = optimizer.minimize(cost)

# Before starting, initialize the variables. We will `run` this first.
init = tf.initialize_all_variables()

# Launch the graph,
with tf.Session() as sess:
    sess.run(init)

    # Fit the line.
    for step in xrange(1000):
        sess.run(train, feed_dict={X:x_data, Y:y_data})
        if step % 200 == 0:
            print step, sess.run(cost, feed_dict={X:x_data, Y:y_data}), sess.run(W)

    # Test model
    correct_prediction = tf.equal(tf.floor(hypothesis+0.5), Y)
    # Calculate accuracy
    accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
    print sess.run([hypothesis, tf.floor(hypothesis+0.5), correct_prediction, accuracy], feed_dict={X:x_data, Y:y_data})
    print "Accuracy:", accuracy.eval({X:x_data, Y:y_data})

1) 200번 마다 print를 통해서 값을 출력하게 된다.
step, cost, W(wegiht) 이 세개의 값이다.

2) test model에서
hypothesis는 0~1사이의 값을 가진다. 
이것에 floor를 취하게 되면, element wise the largest value가 리턴 되어 지므로 0.5를 기준으로 0~1이 잘 반환 된다.
이것과 실제 Y값을 비교함으로써 accuracy를 측정 하게 된다.
마지막으로는 최종적으로 평균을 구하게 된다.

결과

/root/tensorflow/bin/python /root/PycharmProjects/TensorFlowTest/XORwithLogisticRegression.py
I tensorflow/core/common_runtime/local_device.cc:25] Local device intra op parallelism threads: 8
I tensorflow/core/common_runtime/local_session.cc:45] Local session inter op parallelism threads: 8
0 0.74015 [[ 0.71727103 -0.98306912]]
200 0.729532 [[ 0.66214472 -0.84831709]]
400 0.721451 [[ 0.60500312 -0.73486906]]
600 0.715226 [[ 0.54846114 -0.63875955]]
800 0.710393 [[ 0.49420556 -0.55683309]]
[array([[ 0.5       ,  0.38061982,  0.60909009,  0.48914438]], dtype=float32), array([[ 1.,  0.,  1.,  0.]], dtype=float32), array([[False, False,  True,  True]], dtype=bool), 0.5]
Accuracy: 0.5

Process finished with exit code 0

위와 같이 Logistic Regression 방법으로는 0.5의 정확도 밖에 얻을 수 없는것을 알 수 있다.

제대로 동작 하지 않는다.


+ Recent posts