본문 바로가기
DeepLearning Framework & Coding/Tensorflow 1.X

[코드로 이해하는 딥러닝 9] - Softmax Regression(multiple classification)

by 노마드공학자 2020. 12. 22.

[코드로 이해하는 딥러닝 0] - 글연재에 앞서 https://limitsinx.tistory.com/27

[코드로 이해하는 딥러닝 1] - Tensorflow 시작 https://limitsinx.tistory.com/28 

[코드로 이해하는 딥러닝 2] - Tensorflow 변수선언 https://limitsinx.tistory.com/29

[코드로 이해하는 딥러닝 3] - Tensorflow placeholder변수 https://limitsinx.tistory.com/30

[코드로 이해하는 딥러닝 4] - 선형회귀(Linear Regression) https://limitsinx.tistory.com/31

[코드로 이해하는 딥러닝 5] - 다중선형회귀(Multiple Linear Regression) https://limitsinx.tistory.com/32

[코드로 이해하는 딥러닝 6] - 회귀(Regression)에 대한 다른 접근 https://limitsinx.tistory.com/33

[코드로 이해하는 딥러닝 7] - .txt(.csv)파일 불러오기 https://limitsinx.tistory.com/34

[코드로 이해하는 딥러닝 8] - Logistic Regression(sigmoid) https://limitsinx.tistory.com/35

 

※이 전글에서 정리한 코드/문법은 재설명하지 않으므로, 참고부탁드립니다

 

 

Single layer Neural network, 출처 : wikimedia

 

이전 글에서는 Sigmoid function을 통해 비선형성과 Binary Classification을 할 수 있다는것을 코드로 구현해보았습니다.

이번에 정리할 Softmax function 또한 Activation function중 하나인데요

 

Classification을 위해 사용됩니다!

 

이게 무슨말이냐구요??

 

Sigmoid는 최종 결과값을 0 혹은 1 딱 2개로 분류를 해버리기에 Binary Classification에 사용된다고 말씀드렸습니다.

하지만, 3개 4개 ,... N개로 분류를 하고싶다면 어떻게할까요??

 

예를들면, 수능시험을 치면 1등급~9등급까지 총 9가지의 단계로 나누는데요, 이런경우에는 Sigmoid로는 알수가 없죠

sigmoid는 Yes or No를 알고싶을때만 사용가능하답니다.

 

이렇게 여러개의 Classification도 할 수 있도록 하는것이 바로 Softmax function입니다.

 

softmax example , 출처 : https://towardsdatascience.com/softmax-activation-function-explained-a7e1bc3ad60

 

출처 : https://ljvmiranda921.github.io/notebook/2017/08/13/softmax-and-the-negative-log-likelihood/

 

Softmax function을 통과한 모든 output 값들의 총합은 1이됩니다.

바로 "확률(Probability)"가 되는것이죠

 

이것이 Sigmoid 와 Softmax의 가장 큰 차이점입니다!

 

Sigmoid는 output layer의 값들을 보고, 0.5보다 크면 1, 작으면 0 이런식으로 이진분류 밖에 하지 못하는데요

Softmax는 output layer로 나오는 모든값들을 Normalizing 해버리고, 각각에 대한 확률을 구해냅니다.

 

출처 : https://stackoverflow.com/questions/52658204/how-the-parameters-of-softmax-are-obtained-in-tensorflow-if-the-softmax-is-not-i

 

그럼 지금부터 코드를 분석해보겠습니다.

 

[코드 전문]

해당 코드의 y_data값을 보면 [0, 0, 1] 이런식으로 되어있죠

즉, 3비트로써 8개의 class를 나누고 있습니다.

 

x_data가 [1,2,1,1]일 때는 y_data는 [0,0,1] 

 

...

 

x_data가 [1,7,7,7]일 때는 y_data는 [1,0,0] 라는 의미입니다.

 

이것을 토대로 학습시켜보고, x_data가 [1,11,7,9] 일때는 어떤 y_data로 classification될까?를 알아보는 코드입니다.

 

 

[코드 분석-1]

 

① x_data = ...

    y_data = ...

: x_data는 1행4열, y_data는 1행3열의 데이터이기에 placeholder shape를 이렇게 정리해줍니다.

이제는 너무 많이 보셔서 익숙하실 것 같습니다.

 

★ nb_classes = 3

: softmax에서 처음나오는 변수입니다.

y_data를 보면 8개의 클래스를 총 3비트로 나누고 있죠 [0,0,1], 이렇게 클래스를 나눌때의 비트수를 의미합니다.

 

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

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

 

: input으로 들어오는 x_data가 (1,4) Matrix이기 때문에 y=xW+b를 해서 최종적으로 y값이 (1,3) Matrix가 나오려면

W는 (4,3)Matrix, b는 (1,3)이 나와야합니다.

※ 이부분은 한번 종이에 써가면서 심도있게 생각해보시면 큰도움이 됩니다. (행렬 사이즈 동기화)

 

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

: 기존의 y=wx+b값을 softmax에 통과시키는 코드입니다.

 

[코드 분석-2]

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

: sigmoid에서도 cost function이 바뀌었었는데요

softmax에서도 마찬가지로 cost function이 바뀝니다.

 

출처 : https://www.slideshare.net/ssuser06e0c5/the-world-of-loss-function

Cross-entropy기반 수학적 유도과정에 의해서 얻어지는데요, 전-혀 아실필요 없습니다.

그냥, Softmax function을 쓸때는 cost function을 이렇게 복붙(Ctrl C+V)해서 쓰시면 됩니다.

 

이하의 코드는 이제까지 매번 분석해온 코드와 동일합니다.

 

 

[결과값(2000번 학습)]

2000번 학습하고

 

[1,11,7,9]라는 x_data를 넣어본 결과 [0,1,0]으로 classification된다고 추정하고 있습니다.

 

 

Summary

 

머신러닝은 Activation Function을 어떤것으로 사용하냐에 따라 내가 어떤 식의 결과를 얻어낼 수 있을지 정해져있습니다.

Sigmoid, Softmax, ReLU, Hyper tan, Advanced RELU ...

선택할 수 있는 옵션은 정말 많은데요, 이것들을 내가 언제 적재적소에 선택해서 사용할지가 

머신러닝 엔지니어의 경험치라고 할 수있겠네요

 

[코드 공유]

 

#softmax는 multinomial classification(다중분류)를 위해 사용

#sigmoid는 cast를 통해 0,1 binary classification만 가능

#soft max로 하더라도 one got encoding으로 binary가능

#softmax의 cost function은 entropy로 유도

 

import tensorflow.compat.v1 as tf

tf.disable_v2_behavior()

import numpy as np

 

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]]

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]) #shape주의

Y=tf.placeholder("float",[None,3])

nb_classes = 3 #number of classes

 

W=tf.Variable(tf.random_normal([4, nb_classes]), name = 'weight'#input : 4, output : nb_classes

b=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)

 

#Launch graph

#with tf.Session() as sess : 

sess = tf.Session()

sess.run(tf.global_variables_initializer())

 

for step in range(2001) : 

    sess.run(optimizer, feed_dict = {X:x_data, Y:y_data})

    if step%2000 == 0 :

        print(step, sess.run([cost,W,b], feed_dict = {X: x_data, Y:y_data}))

 

#Testing & one-hot encoding(arg_max)

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

a = sess.run(hypothesis, feed_dict = { X:[[1,11,7,9]] })

print(a, sess.run(tf.arg_max(a,1)))

print(a)

 

댓글