MNISTデータセットを使用してTensorflowに単純なMLPニューラルネットワークを実装した後、同じ結果が得られることを期待して、Kerasを使用して同じネットワークを実装しようとしました。テンソルフローモデルは約98%のテスト精度を達成しますが、Kerasモデルは96%しか達成しません(ランダムシードによるわずかな変動がありますが、Kerasモデルのパフォーマンスは常に約2%低下します)。
これを正確に引き起こしている原因を突き止めるために、両方のモデルでまったく同じオプティマイザー、アクティブ化関数、損失関数、メトリック、重みとバイアスの初期化子、および入力と出力のプレースホルダーを使用しました。それでも、パフォーマンスには2%の違いが残っています(以前は、それらのネイティブのKeras実装を使用していましたが、結果は同じでした)。
以下は、両方の実装のコードです。
import tensorflow as tf
from tensorflow.contrib.learn.python.learn.datasets import mnist
from datetime import datetime
from numpy import sqrt
# Data
mnist = mnist.read_data_sets('data', one_hot=True)
X_train = mnist.train.images
Y_train = mnist.train.labels
X_test = mnist.test.images
Y_test = mnist.test.labels
# Data meta
in_shape = X_train.shape[1]
out_shape = Y_train.shape[1]
n_train = X_train.shape[0]
n_test = X_test.shape[0]
# Hyperparams
n_neurons = 256
dropout_prob = 0.7
lr = 0.001
training_epochs = 30
batch_size = 100
n_batches = int(n_train / batch_size)
def get_network_utils():
input_placeholder = tf.keras.layers.Input(shape=(in_shape, ))
output_placeholder = tf.placeholder(tf.float32, [None, out_shape], name="output")
dropout_ph = tf.placeholder_with_default(1.0, shape=())
optimizer = tf.train.AdamOptimizer(learning_rate=lr, name='Trainer')
activation = tf.nn.relu
def loss(y_true, y_pred):
return tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y_true, logits=y_pred))
def accuracy(y_true, y_pred):
correct = tf.equal(tf.argmax(y_true, 1), tf.argmax(y_pred, 1))
return tf.reduce_mean(tf.cast(correct, tf.float32))
def weight_initializer(shape, dtype=None, partition_info=None):
init_range = sqrt(6.0 / (shape[0] + shape[1]))
return tf.get_variable('weights', shape=shape, dtype=dtype,
initializer=tf.random_uniform_initializer(-init_range, init_range))
def bias_initializer(shape, dtype=None, partition_info=None):
return tf.Variable(name='bias', initial_value=tf.random_normal(shape))
return (input_placeholder, output_placeholder, dropout_ph, optimizer, activation, loss, accuracy,
weight_initializer, bias_initializer)
def keras_train():
input_placeholder, output_placeholder, _, optimizer, activation, loss, accuracy, weight_initializer, \
bias_initializer = get_network_utils()
def make_layer(name, units, input_shape, activation):
return tf.keras.layers.Dense(units=units, input_shape=input_shape, kernel_initializer=weight_initializer,
bias_initializer=bias_initializer, activation=activation, name=name)
visible_layer = make_layer('VisibleLayer', n_neurons, (in_shape,), activation)(input_placeholder)
dropout = tf.keras.layers.Dropout(dropout_prob)(visible_layer)
hidden_layer_1 = make_layer('HiddenLayer1', n_neurons, (n_neurons,), activation)(dropout)
dropout = tf.keras.layers.Dropout(dropout_prob)(hidden_layer_1)
hidden_layer_2 = make_layer('HiddenLayer2', n_neurons, (n_neurons,), activation)(dropout)
dropout = tf.keras.layers.Dropout(dropout_prob)(hidden_layer_2)
hidden_layer_3 = make_layer('HiddenLayer3', n_neurons, (n_neurons,), activation)(dropout)
dropout = tf.keras.layers.Dropout(dropout_prob)(hidden_layer_3)
output_layer = make_layer('OutputLayer', out_shape, (n_neurons,), 'linear')(dropout)
model = tf.keras.Model(input_placeholder, output_layer)
# Compile
model.compile(loss=loss, optimizer=optimizer, metrics=[accuracy], target_tensors=[output_placeholder])
# Tensorboard graph
tensorboard_callback = tf.keras.callbacks.TensorBoard(log_dir='/tmp/TensorflowLogs/kr_%s'
% datetime.now().strftime('%Y%m%d_%H%M%S'),
write_graph=True)
# Train
def batch_generator():
while True:
yield mnist.train.next_batch(batch_size)
model.fit_generator(generator=batch_generator(), epochs=training_epochs, steps_per_epoch=n_batches,
callbacks=[tensorboard_callback])
print("Testing Accuracy:", model.evaluate(x=X_test, y=Y_test))
def tensorflow_train():
input_placeholder, output_placeholder, dropout_ph, optimizer, activation, loss, accuracy, weight_initializer, \
bias_initializer = get_network_utils()
def make_layer(a, weight_shape, bias_shape, act=None):
op = tf.add(tf.matmul(a, weight_initializer(weight_shape)), bias_initializer(bias_shape))
return op if not act else act(op)
# Model
with tf.variable_scope('VisibleLayer'):
visible_layer = make_layer(input_placeholder, [in_shape, n_neurons], [n_neurons], activation)
dropout = tf.nn.dropout(visible_layer, keep_prob=dropout_ph, name='Dropout1')
with tf.variable_scope('HiddenLayer1'):
hidden_layer_1 = make_layer(dropout, [n_neurons, n_neurons], [n_neurons], activation)
dropout = tf.nn.dropout(hidden_layer_1, keep_prob=dropout_ph, name='Dropout2')
with tf.variable_scope('HiddenLayer2'):
hidden_layer_2 = make_layer(dropout, [n_neurons, n_neurons], [n_neurons], activation)
dropout = tf.nn.dropout(hidden_layer_2, keep_prob=dropout_ph, name='Dropout3')
with tf.variable_scope('HiddenLayer3'):
hidden_layer_3 = make_layer(dropout, [n_neurons, n_neurons], [n_neurons], activation)
dropout = tf.nn.dropout(hidden_layer_3, keep_prob=dropout_ph, name='Dropout4')
with tf.variable_scope('OutputLayer'):
output_layer = make_layer(dropout, [n_neurons, out_shape], [out_shape])
# Loss, Optimizer, Accuracy
with tf.variable_scope('Loss'):
tf_loss = loss(output_placeholder, output_layer)
with tf.variable_scope('Optimizer'):
tf_optimizer = optimizer.minimize(tf_loss)
with tf.variable_scope('Accuracy'):
tf_accuracy = accuracy(output_layer, output_placeholder)
# Train
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
# Tensorboard graph
tf.summary.FileWriter('/tmp/TensorflowLogs/tf_%s' % datetime.now().strftime('%Y%m%d_%H%M%S'),
graph=tf.get_default_graph())
for epoch in range(training_epochs):
sum_loss, sum_acc = 0., 0.
for ii in range(n_batches):
X_batch, Y_batch = mnist.train.next_batch(batch_size)
sess.run(tf_optimizer, feed_dict={input_placeholder: X_batch, output_placeholder: Y_batch, dropout_ph: dropout_prob})
loss_temp, accuracy_temp = sess.run([tf_loss, tf_accuracy], feed_dict={input_placeholder: X_batch, output_placeholder: Y_batch})
sum_loss += loss_temp
sum_acc += accuracy_temp
print('E%d:\t[Loss: %05.5f\tAccuracy: %05.5f]\n' % ((epoch + 1), sum_loss / n_batches, sum_acc / n_batches))
print("Testing Accuracy:[%f, %f]" % (tf_loss.eval({input_placeholder: X_test, output_placeholder: Y_test}),
tf_accuracy.eval({input_placeholder: X_test, output_placeholder: Y_test})))
tf.reset_default_graph()
if __name__ == '__main__':
tensorflow_train()
keras_train()
また、結果を説明できる目に見える違いを見つけることができることを期待して、Tensorboardを使用してグラフをプロットしてみました。
左側はKerasグラフ、右側はTensorflowグラフです。より詳細な検査が必要な場合は、Tensorboardログをここからダウンロードできます。
What I found out by inspectig the graph:
keras_learning_phase
to the others, to make sure that no dropout is applied during evaluation (I'm achieving the same thing in the Tensorflow model using the manually created placeholder dropout_ph
with default value 1.0
).OutputLayer_sample_weights
. Because I did not specify any loss sample weights, they should have value 1.0
and therefore should not influence the results.metrics
somehow has an output to the optimizer? No idea what causes that.Tensorboardグラフにはさらにいくつかの違いがありますが、精度の違いの原因となるものを見つけることができません。手がかりと助けをいただければ幸いです。
ドロップアウトに関して、KerasとTensorFlowの間には重要な違いがあります。
keep_prob
のtf.nn.dropoutは確率設定維持ユニットを。rate
は、ユニットをドロップする確率を設定します。実装では、両方の引数に同じ値を設定しています。あなたはそれを確認する必要がありkeep_prob = 1 - rate
ます。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加