機械学習のデータセットとして有名なものに MNIST というものがあります。
これは手書きの数字画像とその正解データを集めたもので、機械学習の画像認識能力のテストとしてよく利用されます。
今回はこのMNISTを用い、多層パーセプトロンで画像認識を行いました。
MNIST
MNISTは0~9の手書き数字を表す画像のデータベースです。
MNISTは次のようあ画像が含まれています。
MNISTの画像数は70000枚であります。そのうち60000枚は学習用のセットであり、10000枚はテスト用のセットです。
縦28×横28=784要素の配列として登録されています。
TensorFlowからMNISTデータセットにアクセスするには次のような方法があります。
1 2 3 4 5 6 7 8 9 |
from tensorflow.contrib.learn.python.learn.datasets.mnist import read_data_sets data_dir = 'temp' mnist_sets = read_data_sets(data_dir,one_hot=True) test_images = mnist_sets.test.images test_labels = mnist_sets.test.labels train_images, train_labels = mnist_sets.train.next_batch(50) |
使用モデル
使用した多層パーセプトロンのモデルを示します。
- 階層は4とし、各階層のユニット数は入力から、784, 64, 32, 16, 10
- 活性化関数はRelu6関数を使用
- 出力層にはソフトマックスを使用
- 誤差関数には交差エントロピー誤差関数を使用
コード
使用したコードを下記に示します。コードはPython3.6、TensorFlow1.8を用いました。
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 |
import tensorflow as tf import numpy as np import random as rnd from tensorflow.contrib.learn.python.learn.datasets.mnist import read_data_sets ######################################## # MNIST ######################################## data_dir = 'temp' mnist_sets = read_data_sets(data_dir,one_hot=True) test_images = mnist_sets.test.images test_labels = mnist_sets.test.labels ######################################## #parameter ######################################## input_size = test_images.shape[1] label_size = test_labels.shape[1] batch_size = 50 layer_dict = {} net_dict = {} models_nums = 1 layer_dict[0] = np.array([input_size, 64, 32, 16, 10]) #各層のユニット数 #layer_dict[1] = np.array([input_size, 512, 256, 128, 64, 10]) ############################################## # Classs ############################################## class NN_net: def __init__(self, layer_nums, model_num,name = ""): self.w_dict = {} self.b_dict = {} self.layer_size = layer_nums.shape[0] - 1 self.layer_nums = layer_nums self.model_num = model_num self.name = name self.merges = [] def wb_make(self, layer_size,layer_nums, model_num): w_dict = {} b_dict = {} for i in range(layer_size): w_dict[i] = tf.Variable(tf.truncated_normal([layer_nums[i],layer_nums[i+1]],stddev=0.1),name="w{0}".format(i)) b_dict[i] = tf.Variable(tf.truncated_normal([layer_nums[i+1]],stddev=0.1),name="b{0}".format(i)) self.merges.append(tf.summary.histogram("w{0}".format(i),w_dict[i])) self.merges.append(tf.summary.histogram("b{0}".format(i),b_dict[i])) return w_dict, b_dict def make_predicter(self,input_data,w_dict,b_dict,layer_size, model_num): a_dict = {} with tf.name_scope("layer1"): a_dict[0] = tf.nn.relu6(tf.matmul(x,w_dict[0]) + b_dict[0]) with tf.name_scope("layer-hidden"): for i2 in np.arange(1,layer_size-1 ,1): a_dict[i2] = tf.nn.relu6(tf.matmul(a_dict[i2-1],w_dict[i2]) + b_dict[i2]) with tf.name_scope("output"): y = tf.nn.softmax(tf.matmul(a_dict[layer_size-2],w_dict[layer_size-1]) + b_dict[layer_size-1]) return a_dict, y def loss_make(self, y, t, model_num): with tf.name_scope("loss"): loss = tf.reduce_mean(-tf.reduce_sum(t * tf.log(y + 1e-5),axis=[1])) self.merges.append(tf.summary.scalar("loss", loss)) return loss def train_make(self, loss, model_num): with tf.name_scope("train"): train_grad = tf.train.GradientDescentOptimizer(0.1).minimize(loss) return train_grad def accuracy_make(self, y,t,model_num): with tf.name_scope("accuracy"): correct = tf.equal(tf.argmax(y,1),tf.argmax(t,1)) accuracy = tf.reduce_mean(tf.cast(correct,tf.float32)) self.merges.append(tf.summary.scalar("accuracy", accuracy)) return accuracy def make_model(self,x,t): self.w_dict, self.b_dict = self.wb_make(self.layer_size, self.layer_nums, self.model_num) self.a_dict, self.y = self.make_predicter(x, self.w_dict, self.b_dict, self.layer_size, self.model_num) self.loss = self.loss_make(self.y, t, self.model_num) self.train_grad = self.train_make(self.loss, self.model_num) self.accuracy = self.accuracy_make(self.y, t, self.model_num) def model_summary(self): return tf.summary.merge(self.merges) def make_filewriter(self,sess): return tf.summary.FileWriter("logs/model-{0}-{1}".format(self.model_num, rnd.randrange(1000)), sess.graph) # Placeholder x = tf.placeholder(tf.float32,[None,input_size],name="input_data") t = tf.placeholder(tf.float32,[None,label_size],name="input_labels") with tf.name_scope("model"): for i in range(models_nums): net_dict[i] = NN_net(layer_dict[i], i) net_dict[i].make_model(x,t) init = tf.global_variables_initializer() with tf.Session() as sess: sess.run(init) for k in range(models_nums): summary_writer = net_dict[k].make_filewriter(sess) for i in range(1000): step = i + 1 train_images, train_labels = mnist_sets.train.next_batch(batch_size) sess.run(net_dict[k].train_grad,feed_dict={x:train_images, t:train_labels}) if step % 10 == 0: summary_str = sess.run(net_dict[k].model_summary(), feed_dict={x:test_images, t:test_labels}) summary_writer.add_summary(summary_str, step) if step % 50 == 0: print("step : {0}".format(step)) print("End model {0}".format(k+1)) |
結果
実行結果を示します。実行結果として、多層パーセプトロンの誤差関数の値(loss)と多層パーセプトロンの分類結果の正答率(accuracy)を載せています。実行結果はTensorBoardによってデータを取得しました。
実行の結果、多層パーセプトロンはMNISTデータセットを学習し、最終的に正答率としては95%になりました。ハイパラメータの調整を行わず学習した割には良い結果が出たと思います。
まとめ
- TensorFlowから利用できる画像データセットとしてMNISTがある。
- MNISTは手書き数字の画像データセットである。
- MNISTを用い多層パーセプトロンで学習を行い、95%の精度で認識した。
関連記事