seed_test.py 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. import tensorflow as tf
  2. import numpy as np
  3. import sys
  4. import time
  5. sys.path.append('../src')
  6. import facenet
  7. from tensorflow.python.ops import control_flow_ops
  8. from tensorflow.python.ops import array_ops
  9. from six.moves import xrange
  10. tf.app.flags.DEFINE_integer('batch_size', 90,
  11. """Number of images to process in a batch.""")
  12. tf.app.flags.DEFINE_integer('image_size', 96,
  13. """Image size (height, width) in pixels.""")
  14. tf.app.flags.DEFINE_float('alpha', 0.2,
  15. """Positive to negative triplet distance margin.""")
  16. tf.app.flags.DEFINE_float('learning_rate', 0.1,
  17. """Initial learning rate.""")
  18. tf.app.flags.DEFINE_float('moving_average_decay', 0.9999,
  19. """Expontential decay for tracking of training parameters.""")
  20. FLAGS = tf.app.flags.FLAGS
  21. def run_train():
  22. with tf.Graph().as_default():
  23. # Set the seed for the graph
  24. tf.set_random_seed(666)
  25. # Placeholder for input images
  26. images_placeholder = tf.placeholder(tf.float32, shape=(FLAGS.batch_size, FLAGS.image_size, FLAGS.image_size, 3), name='input')
  27. # Build the inference graph
  28. embeddings = inference_conv_test(images_placeholder)
  29. #embeddings = inference_affine_test(images_placeholder)
  30. # Split example embeddings into anchor, positive and negative
  31. anchor, positive, negative = tf.split(0, 3, embeddings)
  32. # Alternative implementation of the split operation
  33. # This produces the same error
  34. #resh1 = tf.reshape(embeddings, [3,int(FLAGS.batch_size/3), 128])
  35. #anchor = resh1[0,:,:]
  36. #positive = resh1[1,:,:]
  37. #negative = resh1[2,:,:]
  38. # Calculate triplet loss
  39. pos_dist = tf.reduce_sum(tf.square(tf.sub(anchor, positive)), 1)
  40. neg_dist = tf.reduce_sum(tf.square(tf.sub(anchor, negative)), 1)
  41. basic_loss = tf.add(tf.sub(pos_dist,neg_dist), FLAGS.alpha)
  42. loss = tf.reduce_mean(tf.maximum(basic_loss, 0.0), 0)
  43. # Build a Graph that trains the model with one batch of examples and updates the model parameters
  44. opt = tf.train.GradientDescentOptimizer(FLAGS.learning_rate)
  45. #opt = tf.train.AdagradOptimizer(FLAGS.learning_rate) # Optimizer does not seem to matter
  46. grads = opt.compute_gradients(loss)
  47. train_op = opt.apply_gradients(grads)
  48. # Initialize the variables
  49. init = tf.global_variables_initializer()
  50. # Launch the graph.
  51. sess = tf.Session()
  52. sess.run(init)
  53. # Set the numpy seed
  54. np.random.seed(666)
  55. with sess.as_default():
  56. grads_eval = []
  57. all_vars = []
  58. for step in xrange(1):
  59. # Generate some random input data
  60. batch = np.random.random((FLAGS.batch_size, FLAGS.image_size, FLAGS.image_size, 3))
  61. feed_dict = { images_placeholder: batch }
  62. # Get the variables
  63. var_names = tf.global_variables()
  64. all_vars += sess.run(var_names, feed_dict=feed_dict)
  65. # Get the gradients
  66. grad_tensors, grad_vars = zip(*grads)
  67. grads_eval += sess.run(grad_tensors, feed_dict=feed_dict)
  68. # Run training
  69. sess.run(train_op, feed_dict=feed_dict)
  70. sess.close()
  71. return (var_names, all_vars, grad_vars, grads_eval)
  72. def _conv(inpOp, nIn, nOut, kH, kW, dH, dW, padType):
  73. kernel = tf.Variable(tf.truncated_normal([kH, kW, nIn, nOut],
  74. dtype=tf.float32,
  75. stddev=1e-1), name='weights')
  76. conv = tf.nn.conv2d(inpOp, kernel, [1, dH, dW, 1], padding=padType)
  77. biases = tf.Variable(tf.constant(0.0, shape=[nOut], dtype=tf.float32),
  78. trainable=True, name='biases')
  79. bias = tf.reshape(tf.nn.bias_add(conv, biases), conv.get_shape())
  80. conv1 = tf.nn.relu(bias)
  81. return conv1
  82. def _affine(inpOp, nIn, nOut):
  83. kernel = tf.Variable(tf.truncated_normal([nIn, nOut],
  84. dtype=tf.float32,
  85. stddev=1e-1), name='weights')
  86. biases = tf.Variable(tf.constant(0.0, shape=[nOut], dtype=tf.float32),
  87. trainable=True, name='biases')
  88. affine1 = tf.nn.relu_layer(inpOp, kernel, biases)
  89. return affine1
  90. def inference_conv_test(images):
  91. conv1 = _conv(images, 3, 64, 7, 7, 2, 2, 'SAME')
  92. resh1 = tf.reshape(conv1, [-1, 147456])
  93. affn = _affine(resh1, 147456, 128) # Affine layer not needed to reproduce the error
  94. return affn
  95. def inference_affine_test(images):
  96. resh1 = tf.reshape(images, [-1, 27648])
  97. affn1 = _affine(resh1, 27648, 1024)
  98. affn2 = _affine(affn1, 1024, 1024)
  99. affn3 = _affine(affn2, 1024, 1024)
  100. affn4 = _affine(affn3, 1024, 128)
  101. return affn4
  102. # Run two sessions with the same seed. These runs should produce the same result.
  103. var_names1, all_vars1, grad_names1, all_grads1 = run_train()
  104. var_names2, all_vars2, grad_names2, all_grads2 = run_train()
  105. all_vars_close = [None] * len(all_vars1)
  106. for i in range(len(all_vars1)):
  107. all_vars_close[i] = np.allclose(all_vars1[i], all_vars2[i], rtol=1.e-16)
  108. print('%d var %s: %s' % (i, var_names1[i].op.name, all_vars_close[i]))
  109. all_grads_close = [None] * len(all_grads1)
  110. for i in range(len(all_grads1)):
  111. all_grads_close[i] = np.allclose(all_grads1[i], all_grads2[i], rtol=1.e-16)
  112. print('%d grad %s: %s' % (i, grad_names1[i].op.name, all_grads_close[i]))
  113. assert all(all_vars_close), 'Variable values differ between the two sessions (with the same seed)'
  114. assert all(all_grads_close), 'Gradient values differ between the two sessions (with the same seed)'