Deep Learningの学習モデルが答えを出すメカニズムは、
ブラックボックスと言われます
AIが行う判断の理由は、わからないというわけですね
とは言え、ニューラルネットワークは、紐解けば、
重みとバイアスから構成されるパラメタを使った行列計算です
その計算(=数値の遷移)の中に、
Deep Learningが行う判断の理由があるはずです
それを可視化することで、
Deep Leaningの開発やデバッグを効率化しようと考えました
mnistに戻って調べてみます
mnistのサンプルは、下図のように2層の畳み込み層と、全結合層をつないでいます
以前に作った*1ソースも同じです
それぞれの層での計算結果をテキスト出力します
tensorflowに学習モデルを出力する機能がありますが、
バイナリになるのが嫌いなので、テキストで出します
def inference(x, keep_prob): x = tf.reshape(x, shape=[-1, IMG_SIZE, IMG_SIZE, 1]) with tf.variable_scope("conv_1"): conv_1, model_conv1 = conv2d(x, [5, 5, 1, 32], [32]) pool_1 = max_pool(conv_1) with tf.variable_scope("conv_2"): conv_2, model_conv2 = conv2d(pool_1, [5, 5, 32, 64], [64]) pool_2 = max_pool(conv_2) with tf.variable_scope("fc"): pool_2_flat = tf.reshape(pool_2, [-1, 7*7* 64]) fc_1, model_fc1 = layer(pool_2_flat, [7*7*64, 1024], [1024]) # apply dropout fc_1_drop = tf.nn.dropout(fc_1, keep_prob) with tf.variable_scope("output"): output, model_fc2 = layer(fc_1_drop, [1024, 10], [10]) model = {'W_conv1': model_conv1['Weight'], 'b_conv1': model_conv1['bias'], \ 'W_conv2': model_conv2['Weight'], 'b_conv2': model_conv2['bias'], \ 'W_fc1': model_fc1['Weight'], 'b_fc1': model_fc1['bias'], \ 'W_fc2': model_fc2['Weight'], 'b_fc2': model_fc2['bias']} return output, model def write_result(output, y, model): return output, y, model def write_model(W_conv1, b_conv1, W_conv2, b_conv2, W_fc1, b_fc1, W_fc2, b_fc2, output, label): output_np = np.zeros([TEST_DATA_SIZE, OUTPUT_SIZE]) for k in range(TEST_DATA_SIZE): for j in range(OUTPUT_SIZE): output_np[k, j] = output[k, j] np.savetxt('./model/output.txt', output_np) for k in range(TEST_DATA_SIZE): for j in range(OUTPUT_SIZE): output_np[k, j] = label[k, j] np.savetxt('./model/testLabel.txt', output_np) W_conv1_np = np.zeros(5*5*1*32) for i in range(5): for j in range(5): for k in range(1): for l in range(32): W_conv1_np[i*5 + j + 25*l] = W_conv1[i,j,k,l] np.savetxt('./model/W_conv1.txt', W_conv1_np) (省略) if __name__=='__main__': with tf.device("/gpu:0"): with tf.Graph().as_default(): with tf.variable_scope("scope_model"): (省略) output, model = inference(x, keep_prob) (省略) test_op = write_result(output, y, model) (省略) out, lbl, mdl = sess.run(test_op, feed_dict={x: testImages, y: testLabels, keep_prob: 1}) (省略) write_model(mdl['W_conv1'], mdl['b_conv1'], mdl['W_conv2'], mdl['b_conv2'], mdl['W_fc1'], mdl['b_fc1'], mdl['W_fc2'], mdl['b_fc2'], out, lbl)
placeholderが絡む数値を出力するのに苦戦しました
write_result()という空の関数をSessionに入れ込むことで、
ニューラルネットワークのパラメタを取り出しています
もっとスマートなやり方があるかも知れません
出力したパラメタを使って、この画像を分類してみます
ソースはこっち*2に置きます
各層での計算結果は次のようになりました
畳み込み1層目
Pool 1層目
畳み込み2層目
Pool 2層目
全結合層
出力層
一層目では、"3"という文字を崩さずにむしろ強調処理をかけているように見えます
単純に元画像からの変化が少ないのかも知れませんが、
もし、画像のエッジ処理のようなことをネットワークが自前で構築しているとしたら、
なかなか大した事のように思います
ただ、2層目以降になると、データの流れがわからないですね(汗)
全結像層の計算結果が、出力層(0, 0, 0, 1, 0, 0, 0, 0, 0, 0)になる構造なんて全く理解できません(笑)
ただ、無駄では無かったと思います
前回失敗した傷検出*3では、今回の1層目のように、
傷部分を強調するような途中計算になることが強く予想されます
それを頼りに、デバッグしていけば良いわけです
少し前が開けてきました