Multinomial Logistic Regression 이라고도 한다.
MNIST는 0부터 9까지의 손글씨 이미지를 가진 데이터베이스인데, 55,000개의 훈련용 이미지와 10,000개의 테스트용 이미지가 있다. 각종 머신러닝 기법들을 테스트하기 위해 많이 쓰이는 데이터이다. 각 이미지는 28 x 28 로 이루어져있다.
영상 처리 공부를 할 때 Lena 사진을 쓰는 것처럼 머신러닝 공부를 하다보면 MNIST를 사용하는 예제를 자주 볼 수 있다.
Lena
MNIST 데이터는 Yann LeCun's website에서 받을 수 있다. TensorFlow는 MNIST 데이터를 다운로드한 후 배열로 읽어들이는 코드를 제공하고 있다.
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
위 코드를 실행하면 mnist에 MNIST 데이터가 들어가게 된다. 만약 위 코드를 실행할 때 UnicodeEncodeError 가 발생한다면 다음과 같은 방식으로 해결한다.
1. 현재 작성 중인 python 스크립트가 있는 폴더의 상위 폴더로 간다.
2. MNIST_data 라는 폴더를 만든다.
3. MNIST_data 폴더에 직접 MNIST데이터를 다운받은 후 압축을 풀지 않은 채 넣는다.
이렇게 하면 아무 에러없이 진행될 것이다.
MNIST 데이터 중 각 이미지가 어떤 숫자를 뜻하는지를 나타내는 label 데이터가 있다. 이 label 데이터를 우리는 one hot vector로 나타내기를 원한다. one hot vector 는 카테고리를 표현할 때 딱 하나의 요소만 1의 값을 나타내는 바이너리 벡터이다. 현재 label 데이터는 0~9를 의미하는데 만약 3을 의미한다면 [0,0,0,1,0,0,0,0,0,0] 로 나타내는 것이다. 따라서 label 데이터는 m x 10 크기를 가진다.
이제 Softmax 모델을 구현할 차례이다. Softmax는 간단히 말해서 해당 데이터가 주어진 데이터 중에 차지하는 비율을 의미한다.
위 식에 의해서 비율을 결정하게 된다. 식에 의해 모든 데이터들의 비를 합하면 1이 된다. 이 성질을 이용해서 각 데이터가 어떤 값일지 추측할 때 후보 추측 값들이 실제 값과 같은 확률을 표현한다. 그 중에 가장 높은 확률을 가진 값을 추측값으로 사용한다.
Softmax는 값을 표현하는 방식만 다를 뿐 Linear Regression의 하나이기 때문에 이전 글들에서 썼던 y=Wx+b 식을 그대로 이용한다. 이 식의 결과값을 softmax 함수의 인자로 넣어주면 된다.
이제 전체 코드를 보면서 설명하겠다.
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_data/", one_hot = True)
x = tf.placeholder(tf.float32, [None, 784])
W = tf.Variable(tf.zeros([784,10]))
b = tf.Variable(tf.zeros([10]))
y = tf.nn.softmax(tf.matmul(x,W)+b) # prediction label
y_ = tf.placeholder(tf.float32, [None, 10])
cross_entropy = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=tf.matmul(x,W)+b))
train_step = tf.train.GradientDescentOptimizer(0.05).minimize(cross_entropy)
sess = tf.InteractiveSession()
tf.global_variables_initializer().run()
for _ in range(1000):
batch_x, batch_y = mnist.train.next_batch(100)
sess.run(train_step, feed_dict={x: batch_x, y_: batch_y})
correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
_accuracy = sess.run(accuracy, feed_dict={x:mnist.test.images, y_:mnist.test.labels})
print(_accuracy)
sess.close()
x = tf.placeholder(tf.float32, [None, 784]) 는 이미지의 개수를 정확하게 모르기 때문에 행을 None으로 두고 각 이미지는 28x28 이기 때문에 열을 784로 두었다.
cross entropy는 비용함수를 의미한다.
식은 위처럼 정의가 되는데 이 식을 구현하는 것보다는 TensorFlow에서 제공하는 tf.nn.softmax_cross_entropy_with_logits함수를 사용하는 것을 권장한다.
cross_entropy = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=tf.matmul(x,W)+b))
위 코드처럼 사용하면된다. labels에는 각 이미지의 실제 label 값을 넣어주고, logits에는 계산을 통해 추측한 값을 넣어준다.
sess = tf.InteractiveSession()
IneractiveSession 과 Session의 차이가 무엇일까? Session은 Tensor 데이터형의 계산을 하기 위해서 생성하는 객체인데 InteractiveSession을 하면 이후의 모든 계산을 한 Session에서 편하게 할 수가 있다. 만약 여러 다른 그래프에 대해 계산을 하려면 Session을 구분해서 쓰는게 좋다. 여기서는 한 그래프에 대해서 계산하니까 편하게 InteractiveSession을 썼다.
correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1))
tf.argmax()는 해당 배열에서 가장 큰 값을 찾아내는 것이다. 첫 번째 인자는 배열이고, 두 번째 인자는 열 방향인지 행방향인지를 구분하는 것이다. 0은 열방향, 1은 행방향을 의미한다.
나머지 코드는 쉽게 이해가 되기 때문에 이것으로 글을 마치겠다.