본문 바로가기

파이썬/머신러닝

[#E6] Multinomial Logistic Classification [Softmax Regression]

SOFTMAX REGRESSION이란 Logistic Classfication 의 일종으로 Multinomial, 즉 다항을 사용하여 학습하는 모델입니다.


제공되는 데이터를 비교해보면 다음과 같습니다.


1
2
3
4
5
6
7
8
9
10
//Logistic Classification
 
x_data = [[4040], [5050], [6060], [7070], [8080], [9090]]
y_data = [[0], [0], [0], [1], [1], [1]]
 
 
//Multinomial Logistic Classification ( Softmax Regression )
 
x_data = [[12], [21], [31], [41], [17], [12], [16], [17]]
y_data = [[001], [001], [001], [010], [010], [010], [100], [100]]
cs


Softmaxy_data 데이터셋을 이해하기 위해서는 ONE HOT ENCODING에 대해서 먼저 알아야 합니다.



[ONE HOT ENCODING]


1
2
x_data = [[12], [21], [31], [41], [17], [12], [16], [17]]
y_data = [[A], [A], [A], [B], [B], [B], [C], [C]]
cs

 

다음과 같은 데이터가 있습니다.

우리는 Logistic Classfication을 이용해서 각각의 x 데이터셋이 A, B, C 를 지정함( 분류 )을 학습해야 합니다.


이는 단순히 PASS / NPASS로 생각할 수 없는 문제입니다.Logistic Classitication에서는 모든 y 데이터셋이 0 또는 1로 구성되어야 하기 때문입니다.


따라서 이 모델을 이용하기 위해서는 A, B, C를 0 또는 1로 구성해야 합니다. 따라서 데이터를 다음과 구성하는 방법이 ONE HOT ENCODING 입니다.


A -> [0, 0, 1]  //2번째 자리가 1

B -> [0, 1, 0]  //1번째 자리가 1

C -> [1, 0, 0]  //0번째 자리가 1


따라서 y_data 데이터셋은 다음과 같이 각각 A, B, C를 나타낼 수 있습니다.


1
y_data = [[001], [001], [001], [010], [010], [010], [100], [100]]
cs

 

이제 Hypothesis를 구성해야합니다. 기본 Logistic 에서는 Sigmoid 함수를 사용해서 이를 구성했는데 [#E5 : Logistic Classification 이란?], 이번에는 y 데이터의 형태가 달라졌으므로 Sofmax 함수를 이용해야 합니다.

 

A = X * W (Hypothesis) [2번째 자리의 추정값]

B = X * W (Hypothesis) [1번째 자리의 추정값]

C = X * W (Hypothesis) [0번째 자리의 추정값]


*b는 임의의 값이므로 제외

 

각각의 X*W (Hypothesis) 에서 임의의 크거나 작은 추정값를 가지게 됩니다 [#E4 : 다중 변수를 가지는 Multi Variables Linear Regression]여기서 Softmax 함수는 데이터에 따라 도출된 추정값의 합계가 1이 되도록 도와줍니다.


[Softmax 함수로 변환된 추정값 예시]


A = X * W = Softmax(추정값) = 0.7

B = X * W = Softmax(추정값) = 0.2

C = X * W = Softmax(추정값) = 0.1


이것은 곧 다음과 같이 표현됩니다.


[C추정값 = 0.1B추정값 = 0.2A추정값 = 0.7]

 

Softmax 함수는 두 가지 역할을 수행합니다.


1. Sigmoid 함수처럼 추정값을 0과 1 사이로 만들어준다. 


2. 변환된 값을 더한 총 합계가 1이 되도록 만들어준다.

 

따라서 총합이 1이므로 이는 마치 확률처럼 볼 수 있습니다. 위의 예시에서 보면 A가 될 확률은 0.7 입니다. 마찬가지로 B는 0.2, C는 0.1입니다.


즉, A가 될 확률이 제일 높으므로 이것은 A = [0, 0, 1] 과 같다고 볼 수 있습니다.


이를 종합해서 Hypothesis를 구성하면 다음과 같습니다.

 

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


그 다음으로, 기본 Logistic Classfication에서는 Sigmoid 함수를 이용했지만 이번에는 Softmax 함수를 이용했으므로 Cost 함수 또한 달라져야 합니다.


 

다음 그림과 같이 Y의 예측값 y_hat (그림에서 왼쪽)과 실제값 (그림에서 오른쪽)의 차이 ( Cost )를 구하는 과정에서 에서 Cost 함수로 CROSS - ENTROPY 함수를 이용하게 됩니다.


이 Cost 함수에 대한 설명은 여기를 참고하세요.


따라서 CROSS - ENTROPY를 이용한 Cost 함수는 다음과 같습니다.

 

1
cost = tf.reduce_mean(-tf.reduce_sum(Y * tf.log(hypothesis), axis=1))
cs

 

axis는 축으로, 이는 다음에 상세히 설명하겠습니다.


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
51
x_data = [[12], [21], [31], [41], [17], [12], [16], [17]]
y_data = [[001], [001], [001],  [010], [010], [010], [100], [100]]
 
= tf.placeholder("float", [None, 2])
= tf.placeholder("float", [None, 3])
nb_classes = 3    
 
= tf.Variable(tf.random_normal([2, nb_classes]), name='weight')
= tf.Variable(tf.random_normal([nb_classes]), name='bias')
 
# tf.nn.softmax computes softmax activations
# softmax = 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)
 
 
# LEARNING & PRINT
 
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}))
 
    print('--------------')
 
    # Testing & One-hot encoding
    a = sess.run(hypothesis, feed_dict={X: [[12]]})
    print(a, sess.run(tf.argmax(a, 1)))
 
    print('--------------')
 
    b = sess.run(hypothesis, feed_dict={X: [[21]]})
    print(b, sess.run(tf.argmax(b, 1)))
 
    print('--------------')
 
    c = sess.run(hypothesis, feed_dict={X: [[31]]})
    print(c, sess.run(tf.argmax(c, 1)))
 
    print('--------------')
 
    all = sess.run(hypothesis, feed_dict={
                   X: [[12], [21], [31]]})
    print(all, sess.run(tf.argmax(all, 1)))
cs


argmax 함수는 A, B, C에 대한 확률 추정치 중 1에 가장 근접한 값 (가장 큰 값)의 자릿수를 구하는 함수입니다. 이것은 axis 값입니다.


즉, 다음에서 학습 결과 추정치가 [0.7, 0.2, 0.1] 이 나왔다면 이는 곧 [1, 0, 0]을 나타내며 이는 A이고, argmax 함수는 0을 출력합니다.



학습결과


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
0 4.4966693
200 0.6843643
400 0.6545731
600 0.63928384
800 0.6288383
1000 0.620518
1200 0.61337596
1400 0.6070266
1600 0.60128355
1800 0.5960389
2000 0.5912201
 
--------------
 
  #A가 될 확률  #B가 될 확률  #C가 될 확률   #가장 큰 값의 위치 
 
[[0.06344459    0.37413925   0.56241614]] [2]
 
--------------
 
[[1.9597406e-04   1.6238879e-01   8.3741528e-01]] [2]
 
--------------
 
[[5.3981917e-06   3.8204747e-01   6.1794716e-01]] [2]
 
--------------
 
[[6.3444592e-02   3.7413925e-01   5.6241614e-01]
 [1.9597406e-04   1.6238879e-01   8.3741528e-01]
 [5.3981921e-06   3.8204747e-01   6.1794716e-01]] [2 2 2]
cs


학습 후 입력한 x 데이터는 [1,2] , [2,1], [3,1] 이고 이것에 대한 실제 Y 값은 [0, 0, 1], 즉 C입니다.


결과에서 보다시피 예측된 Y값, 즉 y_hat 또한 모두 [0, 0, 1], C값을 가리키므로 학습된 모델이 정확하다고 볼 수 있습니다.