본문 바로가기

파이썬/머신러닝

[#E8] Fancy Softmax Regression이란?

FANCY SOFTMAX REGRESSION은 말 그대로 SOFTMAX REGRESSION 모델을 예쁘게 사용하는 또 다른 모델이라고 볼 수 있습니다.


이 포스트에서는 데이터 data-04-zoo.csv  파일을 사용합니다. 해당 데이터는 다음과 같은 형식을 가지고 있습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
1,0,0,1,0,0,1,1,1,1,0,0,4,0,0,1,0
1,0,0,1,0,0,0,1,1,1,0,0,4,1,0,1,0
0,0,1,0,0,1,1,1,1,0,0,1,0,1,0,0,3
1,0,0,1,0,0,1,1,1,1,0,0,4,0,0,1,0
1,0,0,1,0,0,1,1,1,1,0,0,4,1,0,1,0
1,0,0,1,0,0,0,1,1,1,0,0,4,1,0,1,0
1,0,0,1,0,0,0,1,1,1,0,0,4,1,1,1,0
0,0,1,0,0,1,0,1,1,0,0,1,0,1,1,0,3
0,0,1,0,0,1,1,1,1,0,0,1,0,1,0,0,3
1,0,0,1,0,0,0,1,1,1,0,0,4,0,1,0,0
1,0,0,1,0,0,1,1,1,1,0,0,4,1,0,1,0
...
 
x-----------------------------x,y
cs


14번째 줄에서 보다시피 마지막 데이터 Y를 제외한 16개의 값은 x 데이터입니다. 

y 데이터는 0 ~ 6 범위를 가진 서로 다른 동물이고 ( 뱀, 코끼리, 사슴 ... ), X 데이터는 이 동물들을 특징짓는 요소( 날개, 부리, 꼬리 ... )의 유무라고 가정합니다.


다음과 같이 데이터를 로드합니다.


1
2
3
xy = np.loadtxt('data-04-zoo.csv', delimiter=',', dtype=np.float32)
x_data = xy[:, 0:-1]
y_data = xy[:, [-1]]
cs

 

중요한 것은 y 데이터입니다. 이는 0부터 6까지의 값을 가지고 있으므로, 이것을 사용할 수 있는 데이터로 만들기 위해 ONE HOT ENCODING으로 데이터를 변환해야 합니다.


그런데 각각의 Y 데이터를 수작업으로 변환하기에는 번거로우니, Tenserflow에서 제공하는 tf.one_hot함수를 이용할 수 있습니다.


문제는 tf.one_hot을 거친 데이터는 다음과 같이 한 차원이 추가된다는 것입니다.


1
2
3
4
5
6
7
//before one_hot_encoding (y_data_example)
 
[[3], [1]]
 
//after one_hot_encoding (y_data_example)
 
[[[0001000]], [[0100000]]]
cs

 

이를 위해서 마찬가지로 Tensorflow에서 제공하는 tf.reshape 함수를 이용하면 됩니다.


1
2
3
4
5
6
//nb_calsses = y 데이터가 갖는 출력 7개 ( 0 ~ 6 )
 
Y_one_hot = tf.one_hot(Y, nb_classes)  # one hot
 
Y_one_hot = tf.reshape(Y_one_hot, [-1, nb_classes])
 
cs

 

즉, 해당 과정은 다음과 같은 구성으로 진행됩니다.


1
2
3
 one_hot_encoding
[?, 7-> [?, 17-> [?, 7]
                  reshape
cs

 

이제 HypothesisCost를 정의해야 합니다.


1. Hypothesis


이는 Softmax Regression에서 사용된 Hypothesis 함수와 동일하지만, 아래와 같이 다르게 표현하겠습니다.


1
2
logits = tf.matmul(X, W) + b
hypothesis = tf.nn.softmax(logits)
cs

 

2. Cost

 

Cost 함수 또한 마찬가지로 CROSS - ENTROPY 함수를 이용합니다. 다만, 복잡한 함수 식을 직접 작성하기보다는 Tensorflow에서 제공하는 함수를 사용합니다.


1
2
3
4
5
6
7
//Softmax Regression
cost = tf.reduce_mean(-tf.reduce_sum(Y * tf.log(hypothesis), axis=1))

//Fancy Softmax Regression
cost_i = tf.nn.softmax_cross_entropy_with_logits_v2(logits=logits,
                                                 labels=tf.stop_gradient([Y_one_hot]))
cost = tf.reduce_mean(cost_i)
cs

 

SOURCE CODE


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import tensorflow as tf
import numpy as np
 
xy = np.loadtxt('data-04-zoo.csv', delimiter=',', dtype=np.float32)
x_data = xy[:, 0:-1]
y_data = xy[:, [-1]]
 
nb_classes = 7  # y_data : 0 ~ 6
 
= tf.placeholder(tf.float32, [None, 16])
= tf.placeholder(tf.int32, [None, 1])  # y_data : 0 ~ 6 ... only 1 output
 
Y_one_hot = tf.one_hot(Y, nb_classes)  # one hot
Y_one_hot = tf.reshape(Y_one_hot, [-1, nb_classes]) #reshape
 
= tf.Variable(tf.random_normal([16, nb_classes]), name='weight')
= tf.Variable(tf.random_normal([nb_classes]), name='bias')
 
logits = tf.matmul(X, W) + b
hypothesis = tf.nn.softmax(logits)
 
# Cross entropy cost/loss
cost_i = tf.nn.softmax_cross_entropy_with_logits_v2(logits=logits,
                                                 labels=tf.stop_gradient([Y_one_hot]))
cost = tf.reduce_mean(cost_i)
 
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.01).minimize(cost)
 
prediction = tf.argmax(hypothesis, 1)
correct_prediction = tf.equal(prediction, tf.argmax(Y_one_hot, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
 
# Launch graph
with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
 
    for step in range(2000):
        sess.run(optimizer, feed_dict={X: x_data, Y: y_data})
        if step % 100 == 0:
            loss, acc = sess.run([cost, accuracy], feed_dict={
                                 X: x_data, Y: y_data})
            print("Step: {:5}\tLoss: {:.3f}\tAcc: {:.2%}".format(
                step, loss, acc))
 
    # Let's see if we can predict
    pred = sess.run(prediction, feed_dict={X: x_data})
    for p, y in zip(pred, y_data.flatten()):
        print("[{}] Prediction: {} True Y: {}".format(p == int(y), p, int(y)))
 
cs


Prediction, correct_prediction, accuracy에 대해서는 [#E6 : Multinomial Logistic Classification[Softmax Regression]]에서 자세히 확인할 수 있습니다.