tensorflow,ボリュームニューラルネットワークとmnist

12736 ワード

本文は初心者向けの文章で、本文は主にtensorflow実現基礎の畳み込み神経ネットワークをコード記述に基づいて、mnistデータセットに応用する.

コード#コード#

import tensorflow as tf
import tensorflow.examples.tutorials.mnist.input_data as input_data
import numpy as np

# loss acc
def calc_acc(cnt, train_acc, train_loss):
    sum_loss = 0.0
    sum_acc = 0.0
    for i in range(test_nbatch):
        x_batch,y_batch = get_batch(test_data, test_batch_size, i)
        feed = {x:x_batch,y:y_batch,keep_prob:1.0,keep_prob2:1.0}
        calc_obj = [loss,acc_num]
        calc_ans = sess.run(calc_obj, feed_dict=feed)
        sum_loss += calc_ans[0]
        sum_acc += calc_ans[1]
    avg_loss = sum_loss / test_nbatch
    avg_acc = sum_acc / test_size
    print("{:0>2}:train-loss:{:.4f},acc:{:.4f}   test-loss:{:.4f},acc:{:.4f}".format(cnt,train_loss,train_acc,avg_loss,avg_acc))

# k batch
def get_batch(data, batch_size, k):
    ret = []
    for i in range(2):
        ret.append(data[i][batch_size*k:batch_size*(k+1)])
    return ret

#const and data
image_size = 784
image_len = 28
class_size = 10
epochs = 10
eps = 1e-10

mnist = input_data.read_data_sets("MNIST_DATA/")

train_data = [mnist.train.images,mnist.train.labels]
test_data = [mnist.test.images,mnist.test.labels]

train_batch_size = 50
test_batch_size = 50
train_size = train_data[0].shape[0]
test_size = test_data[0].shape[0]
train_nbatch = train_size // train_batch_size
test_nbatch = test_size // test_batch_size


sess = tf.InteractiveSession()


#input
x = tf.placeholder('float', shape=[None,image_size])
y = tf.placeholder('int32', shape=[None])
x_image = tf.reshape(x, [-1,image_len,image_len,1])
y_label = tf.one_hot(y, class_size)
keep_prob = tf.placeholder('float')
keep_prob2 = tf.placeholder('float')
#conv1
w_conv1 = tf.Variable(tf.truncated_normal([5,5,1,20], stddev=0.01))
b_conv1 = tf.Variable(tf.constant(0.0, shape=[20]))
y_conv1 = tf.nn.relu(tf.nn.conv2d(x_image, w_conv1, strides=[1,1,1,1], padding='SAME') + b_conv1)
y_pool1 = tf.nn.max_pool(y_conv1, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')
#conv2
w_conv2 = tf.Variable(tf.truncated_normal([5,5,20,50], stddev=0.01))
b_conv2 = tf.Variable(tf.constant(0.0, shape=[50]))
y_conv2 = tf.nn.relu(tf.nn.conv2d(y_pool1, w_conv2, strides=[1,1,1,1], padding='SAME') + b_conv2)
y_pool2 = tf.nn.max_pool(y_conv2, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')
#flat
y_flat = tf.reshape(y_pool2, [-1,7*7*50])
y_flat_drop = tf.nn.dropout(y_flat, keep_prob2)
#fc1
w_fc1 = tf.Variable(tf.truncated_normal([7*7*50,500], stddev=0.01))
b_fc1 = tf.Variable(tf.constant(0.0, shape=[500]))
y_fc1 = tf.nn.relu(tf.matmul(y_flat_drop, w_fc1) + b_fc1)
y_fc1_drop = tf.nn.dropout(y_fc1, keep_prob)
#fc2
w_fc2 = tf.Variable(tf.truncated_normal([500,10], stddev=0.01))
b_fc2 = tf.Variable(tf.constant(0.0, shape=[10]))
y_fc2 = tf.nn.softmax(tf.matmul(y_fc1_drop, w_fc2) + b_fc2) + eps
#loss
loss = -tf.reduce_mean(tf.reduce_sum(y_label*tf.log(y_fc2), reduction_indices=[1]))
grad = tf.train.AdadeltaOptimizer(4.0).minimize(loss)
#acc
corr_pred = tf.equal(tf.argmax(y_label,1), tf.argmax(y_fc2,1))
acc_num = tf.reduce_sum(tf.cast(corr_pred, 'float'))


#run
sess.run(tf.global_variables_initializer())

cnt = 0
for i in range(epochs):
    sum_acc = 0.0
    sum_loss = 0.0
    for j in range(train_nbatch):
        x_batch,y_batch = get_batch(train_data, train_batch_size, j)
        feed = {x:x_batch,y:y_batch,keep_prob:0.5,keep_prob2:0.75}
        calc_obj = [grad,loss,acc_num]
        calc_ans = sess.run(calc_obj, feed_dict=feed)
        sum_acc += calc_ans[2]
        sum_loss += calc_ans[1]
    avg_acc = sum_acc / train_size
    avg_loss = sum_loss / train_nbatch

    cnt += 1
    calc_acc(cnt, avg_acc, avg_loss)

全接続層(fc)


全接続層のパラメータはtensorflowにおいて1つのパラメータ行列W+1つのバイアスベクトルbであるb.行列の行列数はそれぞれ前層のノード数と本層のノード数である、パラメータWと信号Xとの演算の際、X*Wと書かれた行列乗算であり、Xは先に神経ネットワークの公式に合致することに注意する.

コンボリューション層


ボリューム層のパラメータもWとbで構成するが、Wの次元は2次元ではなく4次元である点が異なる、具体的には[width,height,in_channel,out_channel]本書に記載のボリューム層は、複数のボリューム核からなり、各ボリューム核には幅と高さがあり、上述widthとheightの2次元に対応する.各ボリューム照合画像のスキャンにより、次の層に伝達する特徴図が得られる.次の層にとって、ボリュームコアは複数の図に直面する必要があり、これは最初に1枚の画像しかないのとは異なる.したがって,ボリューム層の定義を統一する必要があり,in_を設定した.chとout_chこの2つの次元、in_chは、このレイヤの入力が何枚あるかを示す図(チャネル)、out_chは、そのレイヤが出力何枚の図(チャネル)を示す.これにより、in_が生成されます.ch*out_ch個のボリュームコア、同一out_に属するchのボリュームコアはin_ch個、それらを畳み込んで得られた特徴図を直接加算して1枚の特徴図を得て、このout_chの出力白黒写真では、最初の積層層の1チャネルが入力.カラー写真の場合、第1の畳み込み層は、RGBモードであれば3チャネル入力である.

dropout層


dropoutは一部の信号を直接0にし、破棄の割合はパラメータkeep_に依存する.prob(keep_probは実際には保持する割合であることに注意).また、廃棄後の信号の総強度が弱まるため、総強度の所望の一定を1つの数に乗じて保持する.dropoutはオーバーフィットを抑制する役割を果たすことができ、特に全接続層で顕著に現れる.一般的にdropoutはトレーニング時のみ使用する、テスト時にdropout(keep_prob制御外部入力)は使用しない.そのため、訓練過程の前期にテストセットの精度が訓練セットより高いという異常な状況が発生する.

flatten層


積層層の特徴図を一次元のベクトルとしてfc層に入力.

アクティブ化関数


一般的にrelu活性化関数を採用し、最後の層はsoftmaxを採用する.

loss


平均二乗誤差ではなく交差エントロピーを用いるのが一般的である.

ラーニングマシン


異なる学習器の学習率は一般的に異なる.よく使われる学習器とその学習率は以下の通りです.
ラーニングマシン
説明
学習率
GradientDescentOptimizer
最も一般的な勾配降下
1.0
AdadeltaOptimizer
adaアルゴリズムによる勾配降下
1.0
AdamOptimizer
adamアルゴリズムによる勾配降下
1e-4
上記の学習率は大まかな数級にすぎず、最適な学習率は絶えず調整する必要がある.

注意事項


1.パラメータの初期化


パラメータの初期値をすべて0にすることができず、大きすぎることもできず、初期値の設定が適切でないと訓練できない可能性がある.バイアスパラメータは0とすることができるが、残りの一般的なパラメータは平均値が0であることが好ましく、標準差は0.1を超えないことが好ましい、均一分布や終端の正規分布などを用いて生成することができる.

2.testもbatchが必要


batchが増大すると消費メモリ(メモリ)が増加する、機械が直接テストセット全体を走ることができないことが多いため、テスト時にも1つずつbatchで行うべきである.

3.クロスエントロピーの計算エラー


ニューラルネットワークの出力に1 e-10を強制的に加え、後のlog演算にlog(0)が現れることを避ける.具体的にtensorflow訓練を参考にnanの討論が現れる

実行結果

01:train-loss:0.2149,acc:0.9291   test-loss:0.0469,acc:0.9846
02:train-loss:0.0581,acc:0.9822   test-loss:0.0331,acc:0.9892
03:train-loss:0.0417,acc:0.9876   test-loss:0.0250,acc:0.9918
04:train-loss:0.0355,acc:0.9892   test-loss:0.0242,acc:0.9913
05:train-loss:0.0287,acc:0.9913   test-loss:0.0216,acc:0.9924
06:train-loss:0.0250,acc:0.9924   test-loss:0.0212,acc:0.9929
07:train-loss:0.0227,acc:0.9931   test-loss:0.0210,acc:0.9932
08:train-loss:0.0200,acc:0.9936   test-loss:0.0259,acc:0.9919
09:train-loss:0.0181,acc:0.9943   test-loss:0.0218,acc:0.9924
10:train-loss:0.0166,acc:0.9948   test-loss:0.0221,acc:0.9925