[머신러닝] Softmax Classification

in kr-steemit •  7 years ago 

그동안 우리는 특정 숫자를 도출해내거나, 0 또는 1 중의 한 숫자를 예측하는 방법들을 살펴봤다. 사실 현실에서는 그 중간에 위치한 변수들이 너무나도 많다. 대학에서 평점을 매길 때 A부터 F까지 한정된 개수의 점수를 나타내는 것이 대표적이다. 0 또는 1만으로는 나타내기 힘들고, 100점 만점의 점수만으로 평기하기에도 애매하다. 이제 우리는 Softmax Classifiaction이라는 방법을 사용해 이 문제를 해결할 수 있다.

import tensorflow as tf

x_data = [[1, 2, 1, 1],
         [2, 1, 3, 2],
         [3, 1, 3, 4],
         [4, 1, 5, 5],
         [1, 7, 5, 5],
         [1, 2, 5, 6],
         [1, 6, 6, 6],
         [1, 7, 7, 7]]

# One-hot-encoding
y_data = [[0, 0, 1], [0, 0, 1], [0, 0, 1], [0, 1, 0], [0, 1, 0], [0, 1, 0], [1, 0, 0], [1, 0, 0]]

X = tf.placeholder('float', [None, 4])
Y = tf.placeholder('float', [None, 3])
nb_classes = 3

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


위의 x_data와 같은 변수와 y_data라는 결과물을 토대로 학습을 진행하려고 한다. 먼저 알아야 할 기본 개념은 One-hot-encoding이다. 일종의 약속을 코드로 구현했다고 보면 된다. 예를 들어 A라는 점수는 [1, 0, 0]으로, B[0, 1, 0]으로, C[0, 0, 1]이라는 코드로 치환해서 사용한다는 약속이다. 단 하나의 숫자만 1로 표현한다고 해서 One-hot-encoding이라고 부른다. 위의 y_data는 이와 같은 개념을 사용한 것이다.





hypothesis를 정의하는 기본 논리는 같다. X라는 데이터에 W라는 변수를 곱해 Y라는 결과물을 예측하는 것이다. 다만 이제는 0 또는 1의 단 두 결과만 나오거나 무한한 임의의 숫자를 도출해내는 것이 아니라 한정된 결과물만 나타내야 하기 때문에 더욱더 차원에 대한 고려가 필요하다.

위 그림에서 결과물은 세 개만 나올 수 있다. 그리고 만약 세 개의 결과물에 대한 예측 점수가 각각 2.0, 1.0, 0.1으로 나올 경우, 전체 합이 1인 확률로 표시하는 것이 Softmax Classification의 골자다.

그리고 그림에 나타나 있는 식은 물론 이해하면 좋지만, 몰라도 사용할 수 있다. 구글에서 이미 TensorFlow안에 구현해두었기 때문에.


# tf.nn.softmax computes softmax activations
# exp(logits) / reduce_sum(exp(logits), dim)
hypothesis = tf.nn.softmax(tf.matmul(X, W) + b)

# cross entropy cost/loss
cost = tf.reduce_mean(-tf.reduce_sum(Y * tf.log(hypothesis), axis = 1))
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.1).minimize(cost)


tf.nn.softmax라는 메소드를 사용해서 한 줄의 코드로 저 위의 복잡한 수식을 코드로 구현할 수 있다. cost의 경우 기존의 방식과는 달라진 것을 발견할 수 있다. 실제 결과물인 Yhypothesis의 결과물과의 차이가 아닌 곱으로 나타내고 있다. 이또한 수학적인 부분이기 때문에 자세한 공식은 사용하지 않겠지만, 결과적으로 예측이 틀릴 경우 cost가 증가하고 반대의 경우 cost0이 되는 수식으로 이해하면 된다.

# Launch graph
with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    
    for step in range(2001):
        sess.run(optimizer, 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}))


학습을 하는 방식은 동일하다. 전체 Graph를 그리고 변수를 초기화한 후에 optimizer를 실행하기 위해 x_datay_data를 넣는다.

0 2.2636468
200 0.6693883
400 0.56024593
600 0.4671715
800 0.3768742
1000 0.28712988
1200 0.23116957
1400 0.20998713
1600 0.19221275
1800 0.17709729
2000 0.16409844


위와 같이 출력이 되는 것을 볼 수 있다. 학습을 진행할수록 cost0을 향해 줄어드는 것을 확인할 수 있다.

    # Testing & One-hot-encoding
    a = sess.run(hypothesis, feed_dict={X: [[1, 11, 7, 9],
                                           [1, 3, 4, 3],
                                           [1, 1, 0, 1]]})
    print(a, sess.run(tf.argmax(a, 1)))


실제로 학습 결과가 잘 나오는지 테스트를 해본다. 여기서 argmax라는 새로운 메소드를 사용한다. 첫번째 그림에서 보았듯이 가장 확률이 높은 결과물을 예측치로 설정하기 위해, 여러 확률 중에서 max 값을 찾아내는 방법이다. 그 결과는 아래와 같이 나온다.

[[8.8530891e-03 9.9113691e-01 1.0071689e-05]
 [8.2685965e-01 1.5776965e-01 1.5370723e-02]
 [2.3587551e-08 4.0142154e-04 9.9959856e-01]]
 
 [1 0 2]


첫번째 리스트에 담긴 결과물들은 각 결과물에 대한 score를 나타낸다. 이를 확률로 변환해서 가장 높은 확률의 결과물을 찾아낸 것이 두번째 리스트에 담긴 숫자들이다. 학습한 내용들을 토대로 다른 임의의 x_data들에 대해 새로운 예측치를 나타내는 것이다.










Authors get paid when people like you upvote their post.
If you enjoyed what you read here, create your account today and start earning FREE STEEM!
Sort Order:  

kr-dev 태그를 이용해보시는건 어떻게 생각하시는지요 :) 개발자들이 자주 사용하는 태그입니다.

아 그렇군요! 좋은 태그 추천 감사드립니다 : )

일교차가 큰 날씨에요 감기조심하세요^^

감사합니다 : )