TensorFlowのMNISTはどうなってるのか?
TensorFlowのチュートリアルのMNISTはどうなってるのか? ソースコードはこれです。
とりあえずデフォルトだと、[0,0,0,128,255…]とかではなく、[0.,0.,0.9..]みたいになっていて、これはdtypeをtf.float32にするとわざわざそうしてくれるらしい。もう一つtf.unit8というのにもできるので、それぞれの出力結果を確認してみようと思います。
import tensorflow as tfimport numpy as npfrom tensorflow.examples.tutorials.mnist import input_datamnist32 = input_data.read_data_sets('.\mnist', one_hot=True, dtype=tf.float32)mnist8 = input_data.read_data_sets('.\mnist', one_hot=True, dtype=tf.uint8)
x32, t32 = mnist32.train.next_batch(1)x8, t8 = mnist8.train.next_batch(1)
print(x32)print(t32)print(x8)print(t8)やっぱり、x32は、0から1の数値が入っております。1次元784列です。 x8は、0から255の数値が入っており、同じく1次元784列です。
x32は、 0. 0. 0. 0. 0. 0. 0. 1. 0. 0.のようになります。next_batchは普通1つだけ抽出することはないので、配列の中に配列が入ってます。0から始まるのでこれは7が正解だと言っています。では画像出力してみます。
from PIL import ImageImage.fromarray(x8.reshape(28, 28)).show()これ7なの?みたいな画像が表示されました。7,3,4,6,1の順で入っていました。画像はそれぞれ下記になります。 




一応ラベルも確認してみます。
[[ 0. 0. 0. 0. 0. 0. 0. 1. 0. 0.] [ 0. 0. 0. 1. 0. 0. 0. 0. 0. 0.] [ 0. 0. 0. 0. 1. 0. 0. 0. 0. 0.] [ 0. 0. 0. 0. 0. 0. 1. 0. 0. 0.] [ 0. 1. 0. 0. 0. 0. 0. 0. 0. 0.]]あってます。7,3,4,6,1です。
あとは、x32は、x8を255で割っているだけなのか??255は1なはずだから、それだけな気がする。コードは、下記のようになってます。
if dtype == tf.float32: # Convert from [0, 255] -> [0.0, 1.0]. images = images.astype(numpy.float32) images = numpy.multiply(images, 1.0 / 255.0)そのようだな。float32型にしてから、255分の1をかけてるということじゃろう。一応数値を確かめてみよう。
tmp = []for i in range(784): if x8[0][i] != 0: tmp.append([i, x8[0][i], '{0:.2f}'.format(x32[0][i]), '{0:.2f}'.format(x8[0][i] / 255)])print(tmp)結果、下記のようになり、やっぱり一緒になる。
[[207, 97, '0.38', '0.38'], [208, 96, '0.38', '0.38'], [209, 77, '0.30', '0.30'], [210, 118, '0.46', '0.46'], [211, 61, '0.24', '0.24'], [227, 90, '0.35', '0.35'], [228, 138, '0.54', '0.54'], [229, 235, '0.92', '0.92'], [230, 235, '0.92', '0.92'], [231, 235, '0.92', '0.92'], [232, 235, '0.92', '0.92'], [233, 235, '0.92', '0.92'], [234, 235, '0.92', '0.92'], [235, 251, '0.98', '0.98'], [236, 251, '0.98', '0.98'],テストデータはどうなってるのか?
tx32 = mnist32.test.imagestx8 = mnist8.test.imagesprint(tx32.shape)print(tx8.shape)結果
(10000, 784)(10000, 784)tx8は0-255の数字だったし、tx32は0-1の数字で、きちんと設定が反映されております。デフォルトで10000個くれるんだな。
いやー上記は全部想像していた通りなのですが、だったらなぜこれが動かないのでしょうか?
import tensorflow as tfimport numpy as npfrom tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets('.\mnist', one_hot=True, dtype=tf.uint8)
x = tf.placeholder(tf.float32, [None, 784])w = tf.Variable(tf.zeros([784, 10]))b = tf.Variable(tf.zeros([10]))f = tf.matmul(x, w) + by = tf.nn.softmax(f)t = tf.placeholder(tf.float32, [None, 10])loss = -tf.reduce_sum(t * tf.log(y))train_step = tf.train.AdamOptimizer().minimize(loss)correct = tf.equal(tf.argmax(y, 1), tf.argmax(t, 1))accuracy = tf.reduce_mean(tf.cast(correct, tf.float32))
with tf.Session() as sess: sess.run(tf.initialize_all_variables()) i = 0 for _ in range(1500): i += 1 batch_x, batch_t = mnist.train.next_batch(100) sess.run(train_step, feed_dict={x: batch_x, t: batch_t}) if i % 100 == 0: loss_val, acc_val = sess.run([loss, accuracy], feed_dict={x: mnist.test.images, t: mnist.test.labels}) print ('Step: %d, Loss: %f, Accuracy: %f' % (i, loss_val, acc_val))結果は下記になります。
Step: 100, Loss: nan, Accuracy: 0.098000Step: 200, Loss: nan, Accuracy: 0.098000Step: 300, Loss: nan, Accuracy: 0.098000Step: 400, Loss: nan, Accuracy: 0.098000Step: 500, Loss: nan, Accuracy: 0.098000Step: 600, Loss: nan, Accuracy: 0.098000Step: 700, Loss: nan, Accuracy: 0.098000Step: 800, Loss: nan, Accuracy: 0.098000Step: 900, Loss: nan, Accuracy: 0.098000Step: 1000, Loss: nan, Accuracy: 0.098000Step: 1100, Loss: nan, Accuracy: 0.098000Step: 1200, Loss: nan, Accuracy: 0.098000Step: 1300, Loss: nan, Accuracy: 0.098000Step: 1400, Loss: nan, Accuracy: 0.098000Step: 1500, Loss: nan, Accuracy: 0.098000mnist = input_data.read_data_sets(’.\mnist’, one_hot=True, dtype=tf.uint8)を、mnist = input_data.read_data_sets(’.\mnist’, one_hot=True, dtype=tf.float32)にすると、こうなります。
Step: 100, Loss: 7747.070312, Accuracy: 0.848400Step: 200, Loss: 5439.358887, Accuracy: 0.879900Step: 300, Loss: 4556.464355, Accuracy: 0.890900Step: 400, Loss: 4132.033203, Accuracy: 0.896100Step: 500, Loss: 3836.137207, Accuracy: 0.902600Step: 600, Loss: 3662.451416, Accuracy: 0.903300Step: 700, Loss: 3505.859619, Accuracy: 0.908400Step: 800, Loss: 3415.246338, Accuracy: 0.909000Step: 900, Loss: 3291.936035, Accuracy: 0.913200Step: 1000, Loss: 3229.531738, Accuracy: 0.912900Step: 1100, Loss: 3156.712646, Accuracy: 0.913200Step: 1200, Loss: 3110.640625, Accuracy: 0.915800Step: 1300, Loss: 3053.396973, Accuracy: 0.917000Step: 1400, Loss: 3032.461914, Accuracy: 0.915400Step: 1500, Loss: 2984.136719, Accuracy: 0.917200uint8にすると、テスト画像のxはしっかり0-255になるのですが、wとbがnanになってます。結果、fもyもlossもnanになっています。なんでMNISTをuint8形式にするとwとかが取得できないのでしょうか??
下記のような感じで5回だけ回してみました。
mnist = input_data.read_data_sets('.\mnist', one_hot=True, dtype=tf.uint8)
x = tf.placeholder(tf.float32, [None, 784])w = tf.Variable(tf.zeros([784, 10]))b = tf.Variable(tf.zeros([10]))f = tf.matmul(x, w) + by = tf.nn.softmax(f)t = tf.placeholder(tf.float32, [None, 10])loss = -tf.reduce_sum(t * tf.log(y))train_step = tf.train.AdamOptimizer().minimize(loss)correct = tf.equal(tf.argmax(y, 1), tf.argmax(t, 1))accuracy = tf.reduce_mean(tf.cast(correct, tf.float32))
with tf.Session() as sess: sess.run(tf.global_variables_initializer()) for _ in range(5): bx, bt = mnist.train.next_batch(100) fd = {x:bx, t:bt} now_w, now_b, _ = sess.run([w, b, train_step], feed_dict=fd) loss_val, acc_val = sess.run([loss, accuracy], feed_dict=fd) print(now_w) print(now_b) print(loss_val) print(acc_val)結果がこれです。
[[ 0. 0. 0. ..., 0. 0. 0.] [ 0. 0. 0. ..., 0. 0. 0.] [ 0. 0. 0. ..., 0. 0. 0.] ..., [ 0. 0. 0. ..., 0. 0. 0.] [ 0. 0. 0. ..., 0. 0. 0.] [ 0. 0. 0. ..., 0. 0. 0.]][ 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]343.4160.65[[ 0. 0. 0. ..., 0. 0. 0.] [ 0. 0. 0. ..., 0. 0. 0.] [ 0. 0. 0. ..., 0. 0. 0.] ..., [ 0. 0. 0. ..., 0. 0. 0.] [ 0. 0. 0. ..., 0. 0. 0.] [ 0. 0. 0. ..., 0. 0. 0.]][ 0.001 0.001 -0.001 0.001 0.001 -0.001 0.001 -0.00036121 0.001 -0.001 ]245.7570.66[[ 0. 0. 0. ..., 0. 0. 0.] [ 0. 0. 0. ..., 0. 0. 0.] [ 0. 0. 0. ..., 0. 0. 0.] ..., [ 0. 0. 0. ..., 0. 0. 0.] [ 0. 0. 0. ..., 0. 0. 0.] [ 0. 0. 0. ..., 0. 0. 0.]][ 0.0003892 0.00182066 -0.0005059 0.0005982 0.00195108 -0.0005164 0.00037463 0.00038293 0.00030813 -0.00045584]476.4960.54[[ 0. 0. 0. ..., 0. 0. 0.] [ 0. 0. 0. ..., 0. 0. 0.] [ 0. 0. 0. ..., 0. 0. 0.] ..., [ 0. 0. 0. ..., 0. 0. 0.] [ 0. 0. 0. ..., 0. 0. 0.] [ 0. 0. 0. ..., 0. 0. 0.]][ 2.22086237e-04 2.57444754e-03 1.69790001e-04 -8.80775624e-05 1.40353921e-03 1.97276066e-04 1.13845745e-04 8.85801390e-04 1.59423871e-04 2.26144330e-05]nan0.13[[ nan nan nan ..., nan nan nan] [ nan nan nan ..., nan nan nan] [ nan nan nan ..., nan nan nan] ..., [ nan nan nan ..., nan nan nan] [ nan nan nan ..., nan nan nan] [ nan nan nan ..., nan nan nan]][ nan nan nan nan nan nan nan nan nan nan]nan0.1w等のVariableの初期化に失敗してるとかじゃなくて、計算過程でnanに変わってしまいました。学習が発散するとnanになるとかチュートリアルに書いてあったので、それかなあと思いました。にしてもどうして発散するのかな?
参考:http://stackoverflow.com/questions/33712178/tensorflow-nan-bug
交差エントロピーのnp.log(0)が-infを出すことに対する対策が必要だった。ちょうどこれになってるっぽい。clip_by_valueは、第二引数と、第三引数の間に値を調整してくれるようです。
修正版コード
import tensorflow as tfimport numpy as npfrom tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets('.\mnist', one_hot=True, dtype=tf.uint8)
x = tf.placeholder(tf.float32, [None, 784])w = tf.Variable(tf.zeros([784, 10]))b = tf.Variable(tf.zeros([10]))f = tf.matmul(x, w) + by = tf.nn.softmax(f)t = tf.placeholder(tf.float32, [None, 10])loss = -tf.reduce_sum(t * tf.log(tf.clip_by_value(y, 1e-10, 1.0)))train_step = tf.train.AdamOptimizer().minimize(loss)correct = tf.equal(tf.argmax(y, 1), tf.argmax(t, 1))accuracy = tf.reduce_mean(tf.cast(correct, tf.float32))
with tf.Session() as sess: sess.run(tf.global_variables_initializer()) i = 0 for _ in range(10000): i += 1 bx, bt = mnist.train.next_batch(300) now_w, now_b, _ = sess.run([w, b, train_step], feed_dict={x:bx, t:bt}) if not i % 500: loss_val, acc_val = sess.run([loss, accuracy], feed_dict={x:mnist.test.images, t:mnist.test.labels}) print ('Step: %d, Loss: %f, Accuracy: %f' % (i, loss_val, acc_val))結果
Step: 500, Loss: 12224.713867, Accuracy: 0.909800Step: 1000, Loss: 13273.717773, Accuracy: 0.917400Step: 1500, Loss: 14892.584961, Accuracy: 0.909100Step: 2000, Loss: 14022.375000, Accuracy: 0.918800Step: 2500, Loss: 14104.679688, Accuracy: 0.921500Step: 3000, Loss: 13933.588867, Accuracy: 0.926500Step: 3500, Loss: 14054.534180, Accuracy: 0.926300Step: 4000, Loss: 14930.049805, Accuracy: 0.924100Step: 4500, Loss: 14557.189453, Accuracy: 0.924800Step: 5000, Loss: 15464.050781, Accuracy: 0.921000Step: 5500, Loss: 14617.333008, Accuracy: 0.927400Step: 6000, Loss: 14869.592773, Accuracy: 0.924900Step: 6500, Loss: 15666.247070, Accuracy: 0.923500Step: 7000, Loss: 14788.012695, Accuracy: 0.927800Step: 7500, Loss: 15928.329102, Accuracy: 0.921200Step: 8000, Loss: 15767.657227, Accuracy: 0.923200Step: 8500, Loss: 14828.413086, Accuracy: 0.928400Step: 9000, Loss: 15601.589844, Accuracy: 0.924700Step: 9500, Loss: 16263.544922, Accuracy: 0.921700Step: 10000, Loss: 15657.148438, Accuracy: 0.926300