티스토리 뷰

모두의 딥러닝

Softmax Regression (Multinomial Logistic Regression)

강의-1

이번 강의에서는 Softmax 대해서 강의를 한다. Softmax 기존의 Logistic(binary) classification 여러 그룹으로 분류하기 위한 학습법이라고 설명한다.

다시 한번 강의에서 Logistic regression 대해 설명한다. 해당 내용을 간단히 설명하자면, Wx z 두고, 해당 값을 sigmoid라는 0~1사이의 값으로 변환하는 함수에 대입을 시킨다. 그러면 우리가 원하는 hypothesis 구할 있다. 추가적으로 hypothesis 통해 나온 값을 Y hat이라 부르는데 위에 모자를 것과 비슷한 모양이라고 해서 hat이라고 부른다고 한다.

 

이제 본론으로 넘어가 Multinomial classification 대해 알아보자.

다음과 같은 트레이닝 셋이 있다고 하자. 기존과는 다르게 두가지(binary)로의 분류가 아닌, A,B,C 같은 3개의 분류를 해야한다. 그렇다면 어떤 그래프를 그리면 다음과 같이 분류된 값들을 분류할 있을까?

김성훈 교수님께서는 다음과 같이 설명을 하신다.

첫번째 그래프는 C C 아닌 binary regression. 두번째 그래프는 B B 아닌 binary regression. 마지막으로 세번째는 A A 아닌 binary regression.

이렇게 그래프들을 분류하면 각각의 값들을 분류할 있는 그래프가 완성될 이다.

이것을 식으로 나타내면 다음과 같다.

X값에 각각의 W(A, B, C 그래프) 넣어주고, 계산을 하면, 다음과 같은 Y hat 값들을 출력한다.

우리는 기존에 배웠던 행렬 곱셈을 통해, 다음과 같이 조금 간편하고 쉽게 해당 데이터들을 구할 있다.

여기서 W 값을 위의 이미지에서 9개를 곱해야 하는가에 대해 생각해보자. 우선 x 데이터가 3 이다. 그리고 우리는 각각의 그래프에 대한 W 구하는 것이 학습을 하는 목적이다. 그러므로 W 위의 그림과 같이 여러 개가 생성 된다.

 

강의-2

이번 강의는 sigmoid 그럼 어디에 위치할까? 부터 시작한다.

위의 이미지를 설명하자면, 각각의 A,B,C 대한 Logistic regression 구한 결과인 Ya hat = 2.0, Yb hat = 1.0, Yc hat = 0.1 나온 것을 확인 있다. 3개의 값이 나왔는지 생각을 해보면, 우선 해당 Y hat들의 값은 각각의 a, b, c binary classification 적용한 값이다. 그래서 해당 값들은 a, b, c 확률에 대한 임을 있다.

강의에서 김성훈 교수님은 해당 값들을 확률로 나타낼 있으면 좋을 같다란 이야기를 하신다. 그걸 구현해주는 것이 Softmax 이다.

특징으로는 sigmoid 마찬가지로 0 1사이의 값으로 변환하고, 전체의 합은 1 되도록 만들어준다.

해당 이미지 Softmax 나타내는 이미지 인데, 해석을 해보면, 전체의 값에 해당 값을 나눠서 확률 값을 나타내는 있다.

우리가 해당 학습 모델을 통해 이루려고 하는 것은, 입력한 값이 a인지, b인지 c인지에 대해 알고자 함이다. 그렇다면 가장 값을 나머지는 의미가 없는 값이 된다. One-Hot Encoding 사용하여, 가장 값은 1 두고, 나머지는 0으로 변환할 있다. 텐서플로우에서는 argmax라는 함수를 사용하여 One Hot Encoding 적용할 있다.

해당 이미지에서 S(y) Y hat 나타내고, L Label값으로 Y 나타낸다. Cross-entropy 예측한 값과 실제 값의 차를 계산하는 것으로, entropy 값이 감소하는 방향으로 진행하다 보면 최저 값을 찾을 있다.

Cross entropy cost 함수를 나타내면 오른쪽 그래프와 같아진다.

Cross entropy cost function 계산하기 쉽게 식을 정리한 다음, 곱은 행렬곱이 아닌 엘리먼트 곱임을 주의하고 위의 이미지와 같이 각각의 값들을 대입해본다. 그러면 정답인 경우의 Cost값은 0이고, 정답이 아닌 경우, Cost값이 무한대 것을 있다.

Logistic cost Cross entropy 차이점은 무엇일까? 정답은 없다.

교수님은 각각의 함수들은 차이가 없다고 말한다.

실제로 행렬로 계산을 한다는 말고는 Logistic cost 함수와 차이점은 없다.

0 one hot encoding 이용하면, 0 => [1,0] 되고

1 one hot encoding 이용하면, 1 => [0,1] 된다.

그렇게 생각을 하면 Cross entropy Logistic cost 대체할 있기 때문이다.

 

Lab-1

이번 강의는 Softmax 학습법을 이용하여, 여러 개의 클래스로 분류를 하는 소스를 만들어본다.

우선 Softmax 함수에 대해 다시 한번 설명한다.

Softmax regression Logistic classification 분류하고자 하는 클래스 만큼 사용하여 각의 Y hat값을 출력하는 학습법이다.

부분을 조금 쉽게 하기 위해, matmul이라는 matrix multification 사용하여 번의 행렬 곱셈으로 위의 그림과 같이 2.0, 1.0, 0.1이라는 값의 Y hat 출력 있다.

여기서 Softmax sigmoid함수로 생각하면 되는데, 전체에 해당되는 Y hat 값에 각의 Y hat 값을 나눠. 합이 1 확률값으로 만들어 주는 함수이다. 그래서 0.7, 0.2, 0.1이라는 값이 출력하는 확인할 있다.

cost 비용이 최저 비용인 w b값을 찾는 것이 우리의 최종 목표이다. 바로 다음 동영상에서 위의 소스와 달리 텐서플로우에서 제공하는 Cross entropy 함수를 사용하여 조금 쉽게 구할 있다.

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

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(tf.float32
, [None, 4])
Y = tf.placeholder(tf.float32
, [None, 3])

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

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

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

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, "cost: ", sess.run(cost, feed_dict={X: x_data, Y: y_data}))

기존의 소스와 차이점은 y_data shape (2, 3) 이라는 점이 다르다. 해당 shape 통해, 해당 소스는 클래스가 3개라는 있다.

다른 부분은 기존의 소스와 차이가 없으나, cost 함수 , axis=1이라는 부분을 확인 있다.

해당 부분이 무엇일까? 찾아보니 이다. 나중에 김성훈 교수님께서 해당 부분에 대해 간략히 설명을 해주시지만, 부분의 이해를 돕기 위해, 간략히 예제를 들여 설명해보자.

Y_data 값으로 axis 0 1 두었을 때의 차이에 대해 설명하겠다.

우선 Y_data 위에 말했듯이, (2, 3) 모양을 갖춘 매트릭스이다.

해당 부분을 tf.reduce_sum 사용하여 계산을 하면, 모든 값들이 합해져, 8 나온다.

Axis = 0 으로 두면? [2 3 3]

Axis = 1 ? [1 1 1 1 1 1 1 1] 이다.

축을 어떻게 정의하느냐에 따라 배열을 합하는 방향() 달라진다.

 

Lab-2

해당 내용이, 위의 소스와 가장 차이점이다. 복잡한 식을 1번째 함수와 같이 구현할 있지만, 친절하게도 텐서플로우에서는 2번째 함수를 제공하여, 사용자들에게 편리함을 제공한다. 어느 것을 사용하느냐는 개발자의 선택이지만, 아무래도 2번을 자주 사용할 같다.

 

그럼 2번째 함수를 사용하여 파일로부터 데이터를 가져와, 동물들을 분류하는 내용을 소스로 만들어본다.

import tensorflow as tf
import numpy as np

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

nb_classes =
7

X = tf.placeholder(tf.float32, [None, 16])

# int 변환한 이유는 one hot 적용시 float 경우 에러가 발생
Y = tf.placeholder(tf.int32
, [None, 1])

Y_one_hot = tf.one_hot(Y
, nb_classes)
Y_one_hot = tf.reshape(Y_one_hot
, [-1, nb_classes])

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

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

cost_i = tf.nn.softmax_cross_entropy_with_logits(
logits=logits, labels=Y_one_hot)
cost = tf.reduce_mean(cost_i)

train = tf.train.GradientDescentOptimizer(
learning_rate=0.1).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
, dtype=tf.float32))

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())

   
for step in range(2000):
        sess.run(train
, feed_dict={X: x_data, Y: y_data})

       
if step % 200 == 0:
            loss
, accu = sess.run([cost, accuracy], feed_dict={X: x_data, Y: y_data})
           
print("step: {:5}\t cost: {:3f}\t accuracy: {:2%}".format(step, loss, accu))
    pred = sess.run(prediction
, feed_dict={X: x_data, Y: y_data})

   
for p, y in zip(pred, y_data.flatten()):
       
print("[{}] prediction: {}, label: {}".format(p == int(y), p, y))

 

해당 소스에서 특이한 점은 데이터를 불러와 int32 타입 정의한 부분과, one hot 함수를 사용 부분, 그리고 softmax_cross_entropy함수를 사용 부분, 마지막으로 argmax이다.

 

각각에 대해 설명하면, 우선 int32 타입을 정의한 이유는, one hot 함수를 사용하기 위함이다. One hot 함수는 숫자(자연수) 배열의 형태로 나타내주는 함수이다. 예를 들어 2 one hot 함수로 만들면 [0, 0, 1] 같은 배열의 형태로 만들어준다. 그런데 해당 부분을 float 정의를 하게 되면, 2.5, 3.5 같은 소수의 값이 나타날 있기 때문에 배열로 정의하기가 힘들 이다. 

 

다음 으로 one_hot 함수를 사용한 , reshape 해주는 부분이다. 해당 부분을 쉽게 설명하기 위해, 각각을 호출한 값을 나타내면 아래와 같다.

-- Y

[[0]

 [0]

 [3]

 ...]

 

-- OneHot

[[[ 1.  0.  0.  0.  0.  0.  0.]]

 [[ 1.  0.  0.  0.  0.  0.  0.]]

 [[ 0.  0.  0.  1.  0.  0.  0.]]

 ...]

 

-- OneHot > Reshape

[[ 1.  0.  0.  0.  0.  0.  0.]

 [ 1.  0.  0.  0.  0.  0.  0.]

 [ 0.  0.  0.  1.  0.  0.  0.]

 ...]

 

랭크가 2였던 배열(Y) OneHot함수를 사용하여, 랭크가 3으로 변형되었다. 우리가 원하는 배열() 형태는 랭크가 2 형태이므로, reshape함수를 사용하여, 랭크가 2 배열로 만들어 준다.

 

그리고 기존의 방식과는 달리 softmax_cross_entropy_with_logits 사용하여, cost 함수를 구한다.

 

마지막으로 argmax 최대값의 위치를 찾아주는 함수이다. 예를 들어 [0, 0, 1] argmax 사용하면 2라는 값이 나오게 된다. 가장 값의 위치가 2번째에 있는 1이기 때문이다.

 

해당 소스를 돌려보면 다음과 같은 결과를 확인할 있다.

댓글
공지사항
최근에 올라온 글
링크
«   2024/05   »
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
글 보관함