이번 게시물은 logistic_regression에서도 여러 value로 분류하는 Multiple Classification 이다.
import tensorflow as tf
import numpy as np
tf.set_random_seed(777) # for reproducibility
# Predicting animal type based on various features
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)
print(x_data)
'''
(101, 16) (101, 1)
'''
# y_data들의 종류들의 갯수
nb_classes = 7 # 0 ~ 6
X = tf.placeholder(tf.float32, [None, 16])
Y = tf.placeholder(tf.int32, [None, 1]) # 0 ~ 6 까지 담아내는 그릇
numpy를 이용하여 loadtxt 파일을 이용하여 csv파일을 불러올 때, delimiter를 ','으로 나눠서 가져온다.
그 다음 x_data, y_data로 나누고 shape을 꼭 살펴봐야지 나중에 X, Y placeholder의 shape도 정할 수 있다.
xy 불러온 data의 형태는 다음과 같다.
"""
xy data:
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
0,1,1,0,1,0,0,0,1,1,0,0,2,1,1,0,1
0,0,1,0,0,1,1,1,1,0,0,1,0,1,0,0,3
"""
# One_hot function
Y_one_hot = tf.one_hot(Y, nb_classes) # one hot rank 가 n이면 rank n+1로 리턴
print("one_hot:", Y_one_hot)
# reshape([-1, nb_classes]) 여기서 -1은 모든 숫자를 가져온다는 의미
Y_one_hot = tf.reshape(Y_one_hot, [-1, nb_classes])
print("reshape one_hot:", Y_one_hot)
tf.one_hot 메소드는 Y가 [[0],[0],[3],[0],[0],-----] 이런형식이라면,
이를 [ [[1,0,0,0,0,0,0]], [[1,0,0,0,0,0,0]], [[0,0,0,1,0,0,0]] -----] 이런형식으로 바꿔준다.
따라서 y값이 나타내고 있는 부분을 한 array의 index로 생각한다. 이 때 차원이 하나 늘어나기 떄문에!!!!!
항상 reshape를 꼭 해줘야한다.
# Variable
W = tf.Variable(tf.random_normal([16, nb_classes]), name='weight')
b = tf.Variable(tf.random_normal([nb_classes]), name='bias')
# tf.nn.softmax_cross_entropy_with_logits_v2 쓸 때!!
logits = tf.matmul(X, W) + b
hypothesis = tf.nn.softmax(logits)
cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(logits=logits,
labels=tf.stop_gradient([Y_one_hot])))
# 안 쓸때는!!
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)
여기서 우리는 최적화함수를 sigmoid 가 아닌 softmax를 쓴다
softmax란!!
softmax는 y값들을 exponential의 제곱수에 y를 대입하여 모두 합친 값 중에 개별y값이 가지는 값을 나눠준 것으로 이들의 합은 모두 1로 수렴한다. 이는 각각 y들이 모델에 영향을 끼치는 정도를 말한 것이며, 이는 각각이 모델에 끼치는 확률을 말해준다.
sigmoid와 헷갈리는데, sigmoid는 그저 우리가 큰 data를 다루다보면 숫자가 크기 때문에,
이를 방지하기위해 Hypothesis 의 범위를 줄인 것이다. 이는 binary classificatino 할 때 주로 쓴다. 흔히 이를 Activation Function이라고 부른다.
softmax는 각 y값들이 모델에 어느정도로 영향을 끼치는지 확률로써 알기위해 쓰는 함수이며, 장점은 출력확률범위이다.
이는 multi classification 할 때 쓴다.
# tf.nn.softmax_cross_entropy_with_logits_v2 쓸 때!!
logits = tf.matmul(X, W) + b
hypothesis = tf.nn.softmax(logits)
cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(logits=logits,
labels=tf.stop_gradient([Y_one_hot])))
# 안 쓸때는!!
hypothesis = tf.nn.softmax(tf.matmul(X, W) + b)
cost = tf.reduce_mean(-tf.reduce_sum(Y * tf.log(hypothesis), axis=1))
여기서 두 개의 차이점이 존재한다.
tf.nn.softmax_cross_entropy_with_logits_v2(logits=logits, labels=tf.stop_gradient([Y_one_hot])) 는 cost함수를 구현하는 것을 logits 부분에 Hypothesis 전 X와 weight, bias 를 연산한 값만 넣어주고, label에는 tf.stop_gradient([Y_one_hot])을 넣어준다.
tf.stop_gradient(label)은 label이 포함되어있는 값들을 변하지 않고 유지시키는 것을 의미한다.
사실 나는 밑에 부분을 더 선호한다. 위에가 더 짧게 구현할 수는 있지만, 밑에 코드가 더 세분화해서 구현하기 때문에 나중에 내가 코드를 확인할 때 더 세분화해서 확인할 수 있다.
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.1).minimize(cost)
# prediction은 hypothesis에서 axis = 1일때 가장 큰 값을 return한다.
prediction = tf.argmax(hypothesis, 1)
# correct_prediction 은 prediction과 동일한지 비교.
correct_prediction = tf.equal(prediction, tf.argmax(Y_one_hot, 1))
# accuracy 은 tf.cast는 correct_prediction이 True이면 1, False이면 0, 정확도높을수록 1근사.
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
prediction은 예측값으로 hypothesis중에서 axis = 1인 구간에서 제일 큰 값의 index를 return하면서 예측값으로 정한다.
correct_prediction은 prediction과 tf.argmax(Y_one_hot, 1)과 같으면 1을 retunn한다. tf.equal(A,B)가 A, B가 서로 일치하면True, 아니면 False를 return한다.
accuracy은 tf.cast(A)는 A가 True이면 1, A가 False이면 0을 return 한다. 결론은 prediction이 실제 Y_one_hot과 같으면 correct_prediction이 1로 되고 tf.cast가 True이기 때문에 1을 많이 return을 하기 때문에 accuracy는 100을 향해 갈 것이다.
# Launch graph
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
for step in range(2001):
_, cost_val, acc_val = sess.run([optimizer, cost, accuracy], feed_dict={X: x_data, Y: y_data})
if step % 100 == 0:
print("Step: {:5}\tCost: {:.3f}\tAcc: {:.2%}".format(step, cost_val, acc_val))
# Let's see if we can predict
pred = sess.run(prediction, feed_dict={X: x_data})
# y_data: (N,1) = flatten => (N, ) matches pred.shape
"""
flatten : [[1],[0]] - > [1, 0]
zip : 하나의 list로 묶음.
"""
for p, y in zip(pred, y_data.flatten()):
print("[{}] Prediction: {} True Y: {}".format(p == int(y), p, int(y)))
※ 중간에 format 함수에 {:.2%} 는 원래 숫자를 2를 곱해서 %치로 나타내준다.
※ flatten은 reshape과 같은 맥락으로 dimension을 서로 합쳐준다.
'AI' 카테고리의 다른 글
ML07-4-MNIST-data (실제 data 분석) (0) | 2019.10.24 |
---|---|
ML07-4-MNIST-data (0) | 2019.10.24 |
ML05-1-logistic_regression : Binary Classification (0) | 2019.10.23 |
ML04-1-linear-regression(Tensorflow basic) (0) | 2019.10.23 |
Tensorflow : background (6) | 2019.10.23 |
댓글