본문 바로가기

Deep Learning

TensorFlow - Softmax Regression(2)

@markdown

# Fancy Softmax Classification

<br/>

## Animal classification 모델 학습

_____

- 동물이 가지고 있는 특징(클래스) 데이터를 바탕으로 동물의 종을 예측하는 모델

- x_data : 동물이 가지고 있는 특징(클래스) 데이터

- y_data : 종 분류 값(실제값) 0~6까지 

- cost를 구하는데 `softmax_cross_entropy_with_logits` 함수 사용

- y_data를 `one-hot` 데이터로 변형해 사용

### One-Hot encoding

- 통계학에서 여러 개로 분류할 수 있는 데이터를 범주형 변수라고 한다. 

- N개의 숫자로 표현된 범주들을 머신러닝에 활용하기 위해 해당하는 칸의 정보를 1로 표시하고 나머지는 0으로 표시하는 방법을 사용한다.

- 데이터를 0과 1로 표현함으로서 컴퓨터에 편향되지 않는 학습을 시킬 수 있다.

- `TensorFlow`에서는 `one-hot` encoding을 처리해주는 `tf.one_hot()` 함수를 제공한다.

- 이번 예제에서 `one-hot`을 사용해 y_data의 0~6까지 값을 0과 1로 표현되는 `one-hot` 데이터로 변환해준다. 

```python

tf.one_hot(Y, nb_classes)

```

- `tf.one_hot()`은 데이터 Y와 class의 크기 N을 파라미터로 입력 받는다. 

- 주의할 점은 `tf.one_hot()` 데이터로 변환이 이루어질 때 input 행렬의 크기가 rank N이라면 output 결과 값이 rank N+1, 즉 1차원이 더 증가된 결과 만들어진다.

```

rankN = 2

[[0],[3]]

rankN = 3

[[[1 0 0 0 0 0 0 ]], [[0 0 0 1 0 0 0 ]]]

```

- one_hot으로 만들어진 데이터 형식이 3차원이기 때문에 필요한 2차원으로 다시 변형해주는 과정이 필요하다.

- `tf.reshape()` 함수를 사용해 shape 변형을 처리한다.


<pre><code class="python" style="font-size:14px">Y = tf.placeholder(tf.int32, [None, 1])  # 0 ~ 6 (rank N, shape=(?, 1))

Y_one_hot = tf.one_hot(Y, nb_classes)  # one hot data(rank N+1, shape=(?, 1, 7))

Y_one_hot = tf.reshape(Y_one_hot, [-1, nb_classes]) # reshape(?, 7)

</code></pre>


## Softmax animal classifier 구현

____

<pre><code class="python" style="font-size:14px">import tensorflow as tf

import numpy as np

tf.set_random_seed(777)  # for reproducibility


# 다양한 동물의 특징을 기반으로한 동물 종 예측 모델

xy = np.loadtxt('data-04-zoo.csv', delimiter=',', dtype=np.float32)

x_data = xy[:, 0:-1]

y_data = xy[:, [-1]]

print(x_data.shape, y_data.shape)

nb_classes = 7  # 0 ~ 6

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

Y = tf.placeholder(tf.int32, [None, 1])  # 0 ~ 6

Y_one_hot = tf.one_hot(Y, nb_classes)  # one hot

print("one_hot", Y_one_hot)

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

print("reshape", Y_one_hot)


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)

# Cross entropy cost/loss

# softmax_cross_entropy_with_logits 함수를 사용

#cost_i = tf.reduce_mean(-tf.reduce_sum(Y_one_hot * tf.log(hypothesis), axis=1))

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

cost = tf.reduce_mean(cost_i)

# 경사하강법 사용한 minimize

optimizer = 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, tf.float32))

# 학습 시작

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 % 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))

    pred = sess.run(prediction, feed_dict={X: x_data})

    # N차원 데이터 [[ ], [ ]] 형태를 -> [ , , ...] 형태로 만드는 과정

    # 예측한 pred 값과, y_data가 같은지 일대일 비교 후 출력 확인하기 위함

    for p, y in zip(pred, y_data.flatten()):

        print("[{}] Prediction: {} True Y: {}".format(p == int(y), p, int(y)))

</code></pre>


<pre><code class="python" style="font-size:14px">실행결과

(101, 16) (101, 1)

one_hot Tensor("one_hot_14:0", shape=(?, 1, 7), dtype=float32)

reshape Tensor("Reshape_47:0", shape=(?, 7), dtype=float32)

Step:      0 Loss: 3.509 Acc: 23.76%

Step:   100 Loss: 0.656 Acc: 80.20%

...

Step:  1900 Loss: 0.051 Acc: 100.00%

Step:  2000 Loss: 0.048 Acc: 100.00%


[True] Prediction: 0 True Y: 0

[True] Prediction: 0 True Y: 0

[True] Prediction: 3 True Y: 3

[True] Prediction: 0 True Y: 0

[True] Prediction: 0 True Y: 0

...

</code></pre>

- 실행결과 one-hot 텐서의 shape과 reshape 후의 텐서를 확인 할 수 있다.

- loss 값이 줄어들수록, 정확도가 올라가는 것을 확인할 수 있다.

- 학습 횟수를 2001번이 아닌 201번으로 줄이면 정확도가 86% 정도로 낮아지는 것을 확인 할 수 있다.


> 소스코드 - 모두를 위한 머신러닝 김석훈 교수님 강의 참고 : ([https://hunkim.github.io/ml/](https://hunkim.github.io/ml/))