最後は畳み込みニューラルネットワーク(CNN)を実装します。
TensorflowではExpertとしてTutorialに入っているものです。
前回と同様に、MNISTのデータを作成し、Deeplearningしてみます。
コードは前回、前々回のものの一部エンジン部分のみを変更していますので合わせて比較してみるとよくわかるかもしません。
データ作成
まずデータを作成します。こちらの手順を実行します
http://d.hatena.ne.jp/anagotan/20160328/1459156607
train.txtとt10k.txtを作成しておきます
tf_cnn.py
こちらのコードは以下のものを流用させていただきました
http://qiita.com/ikki8412/items/95bc81a744dc377d9119
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 160 161 162 163 164 | #!/bin/env python # -*- coding: utf-8 -*- # http://qiita.com/ikki8412/items/95bc81a744dc377d9119 import tensorflow as tf import numpy as np import random import time import math NUMCLASS=10 NUMPARAM=784 ### データ処理用 def label_data(lines): labels=[] for line in lines: # ラベルを1-of-k方式で用意する tmp = np.zeros(NUMCLASS) tmp[int(line)] = 1 labels.append(tmp) return np.asarray(labels) def image_data(test): test_image=map(lambda n: map(lambda k: float(k)/255.0,n),test[:,1:NUMPARAM+1]) return np.asarray(test_image) # 開始時刻 start_time = time.time() print "開始時刻: " + str(start_time) ### データ取得 ---> # ファイルを開く f = open("train.txt", 'r') # データを入れる配列 train = [] for line in f: # 改行を除いてスペース区切りにする line = line.rstrip() l = line.split(" ") l = map(lambda n: int(n),l) #l=map(lambda n: 0 if n=="0" else 1,l) train.append(l) # numpy形式に変換 train = np.asarray(train) f.close() f = open("t10k.txt", 'r') test = [] for line in f: line = line.rstrip() l = line.split(" ") l = map(lambda n: int(n),l) #l=map(lambda n: 0 if n=="0" else 1,l) test.append(l) test = np.asarray(test) f.close() ### データ取得 ---< # 訓練画像を入れる変数 # 訓練画像は28x28pxであり、これらを1行784列のベクトルに並び替え格納する # Noneとなっているのは訓練画像がいくつでも入れられるようにするため x = tf.placeholder(tf.float32, [None, NUMPARAM], name="x-input") # 交差エントロピー # y_は正解データのラベル # 損失とオプティマイザを定義します y_ = tf.placeholder(tf.float32, [None, NUMCLASS], name="y-input") # hidden1 with tf.name_scope("hidden_layer1") as scope: weights = tf.Variable(tf.truncated_normal([NUMPARAM, 500], stddev=1.0 / math.sqrt(float(NUMPARAM))),name='weights') biases = tf.Variable(tf.zeros([500]),name='biases') hidden1 = tf.nn.sigmoid(tf.matmul(x, weights) + biases) # hidden2 with tf.name_scope("hidden_layer2") as scope: weights = tf.Variable(tf.truncated_normal([500, 300], stddev=1.0 / math.sqrt(float(500))),name='weights') biases = tf.Variable(tf.zeros([300]),name='biases') hidden2 = tf.nn.sigmoid(tf.matmul(hidden1, weights) + biases) # softmax layer with tf.name_scope("softmax_layer") as scope: weights = tf.Variable(tf.truncated_normal([300, NUMCLASS], stddev=1.0 / math.sqrt(float(300))),name='weights') biases = tf.Variable(tf.zeros([NUMCLASS]),name='biases') y = tf.nn.softmax((tf.matmul(hidden2, weights) + biases)) # 更なる name scopes はグラフ表現をクリーンアップしま with tf.name_scope("xent") as scope: cross_entropy = -tf.reduce_sum(y_*tf.log(y)) # TensorBoardで表示するよう指定 tf.scalar_summary("cross_entropy", cross_entropy) # 勾配硬化法を用い交差エントロピーが最小となるようyを最適化する train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy) # 用意した変数Veriableの初期化を実行する init = tf.initialize_all_variables() # Sessionを開始する # runすることで初めて実行開始される(run(init)しないとinitが実行されない) sess = tf.Session() sess.run(init) # TensorBoardで表示する値の設定 summary_op = tf.merge_all_summaries() summary_writer = tf.train.SummaryWriter("/tmp/data", sess.graph_def) # 1000回の訓練(train_step)を実行する # next_batch(100)で100つのランダムな訓練セット(画像と対応するラベル)を選択する # 訓練データは60000点あるので全て使いたいところだが費用つまり時間がかかるのでランダムな100つを使う # 100つでも同じような結果を得ることができる # feed_dictでplaceholderに値を入力することができる print "--- 訓練開始 ---" for i in range(20000): train_sample=np.asarray(random.sample(train,100)) batch_ys=label_data(train_sample[:,0]) batch_xs=image_data(train_sample) train_accuracy=sess.run(train_step, feed_dict={x: batch_xs, y_:batch_ys}) # 1 step終わるたびにTensorBoardに表示する値を追加する summary_str=sess.run(summary_op, feed_dict={x: batch_xs, y_:batch_ys}) summary_writer.add_summary(summary_str, i) print "--- 訓練終了 ---" # 正しいかの予測 # 計算された画像がどの数字であるかの予測yと正解ラベルy_を比較する # 同じ値であればTrueが返される # argmaxは配列の中で一番値の大きい箇所のindexが返される # 一番値が大きいindexということは、それがその数字である確率が一番大きいということ # Trueが返ってくるということは訓練した結果と回答が同じということ with tf.name_scope("test") as scope: correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1)) # 精度の計算 # correct_predictionはbooleanなのでfloatにキャストし、平均値を計算する # Trueならば1、Falseならば0に変換される accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float")) tf.scalar_summary("accuracy", accuracy) # 精度の実行と表示 # テストデータの画像とラベルで精度を確認する # ソフトマックス回帰によってWとbの値が計算されているので、xを入力することでyが計算できる test_label=label_data(test[:,0]) test_image=image_data(test) print "精度" print(sess.run(accuracy, feed_dict={x: test_image, y_: test_label})) # 終了時刻 end_time = time.time() print "終了時刻: " + str(end_time) print "かかった時間: " + str(end_time - start_time) |
実行
1 2 3 4 5 6 7 8 | $ python tf_cnn.py 開始時刻: 1459233406.76 --- 訓練開始 --- --- 訓練終了 --- 精度 0.9806 終了時刻: 1459234272.93 かかった時間: 866.176848888 |
回帰(0.9227)、多層パーセプトロン(0.9562)に比較し0.9806とかなり精度が上がりました