def testCenterLoss(self): batch_size = 16 nrof_features = 2 nrof_classes = 16 alfa = 0.5 with tf.Graph().as_default(): features = tf.compat.v1.placeholder(tf.float32, shape=(batch_size, nrof_features), name='features') labels = tf.compat.v1.placeholder(tf.int32, shape=(batch_size, ), name='labels') # Define center loss center_loss, centers = facenet.center_loss(features, labels, alfa, nrof_classes) label_to_center = np.array([[-3, -3], [-3, -1], [-3, 1], [-3, 3], [-1, -3], [-1, -1], [-1, 1], [-1, 3], [1, -3], [1, -1], [1, 1], [1, 3], [3, -3], [3, -1], [3, 1], [3, 3]]) sess = tf.compat.v1.Session() with sess.as_default(): sess.run(tf.compat.v1.global_variables_initializer()) np.random.seed(seed=666) for _ in range(0, 100): # Create array of random labels lbls = np.random.randint(low=0, high=nrof_classes, size=(batch_size, )) feats = create_features(label_to_center, batch_size, nrof_features, lbls) center_loss_, centers_ = sess.run([center_loss, centers], feed_dict={ features: feats, labels: lbls }) # After a large number of updates the estimated centers should be close to the true ones np.testing.assert_almost_equal( centers_, label_to_center, decimal=5, err_msg='Incorrect estimated centers') np.testing.assert_almost_equal(center_loss_, 0.0, decimal=5, err_msg='Incorrect center loss')
def _build_graph(self, inputs): # with tf.device('/gpu:0'): image, label = inputs image = tf.identity(image, name="NETWORK_INPUT") tf.summary.image('input-image', image, max_outputs=10) # image = (image - 127.5) / 128 image = tf.map_fn(lambda img: tf.image.per_image_standardization(img), image) prelogits, _ = inception_resnet_v1.inference(image, cfg.keep_probability, phase_train=self.train_model, bottleneck_layer_size=cfg.feature_length, weight_decay=cfg.weight_decay) logits = slim.fully_connected(prelogits, cfg.nrof_classes, activation_fn=None, weights_initializer=tf.truncated_normal_initializer(stddev=0.1), weights_regularizer=slim.l2_regularizer(cfg.weight_decay), scope='Logits', reuse=False) #feature for face recognition embeddings = tf.nn.l2_normalize(prelogits, 1, 1e-10, name='embeddings') feature = tf.identity(embeddings, name="FEATURE") # Add center loss if cfg.center_loss_factor>0.0: prelogits_center_loss, _ = facenet.center_loss(prelogits, label, cfg.center_loss_alfa, cfg.nrof_classes) tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES, prelogits_center_loss * cfg.center_loss_factor) # Add cross entropy loss cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits( labels=label, logits=logits, name='cross_entropy_per_example') softmax_loss = tf.reduce_mean(cross_entropy, name='softmax_loss') # tf.add_to_collection('softmax_loss', softmax_loss) # Calculate the total losses center_loss = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES) # tf.summary.scalar('regularization_losses', regularization_losses) loss = tf.add_n([softmax_loss] + center_loss, name='loss') center_loss = tf.identity(center_loss, name='center_loss') if cfg.weight_decay > 0: wd_cost = regularize_cost('.*/W', l2_regularizer(cfg.weight_decay), name='l2_regularize_loss') add_moving_summary(loss, wd_cost) add_moving_summary(softmax_loss) # add_moving_summary(center_loss) self.cost = tf.add_n([loss, wd_cost], name='cost') else: add_moving_summary(softmax_loss) # add_moving_summary(center_loss) self.cost = tf.identity(loss, name='cost')
def tower_loss(scope, image_batch, label_batch, keep_probability, phase_train, bottleneck_layer_size, weight_decay, nrof_classes, center_loss_factor, center_loss_alfa): prelogits, _ = network.inference(image_batch, keep_probability, phase_train, bottleneck_layer_size, weight_decay) logits = slim.fully_connected( prelogits, nrof_classes, activation_fn=None, weights_initializer=tf.truncated_normal_initializer( stddev=0.1), weights_regularizer=slim.l2_regularizer(args.weight_decay), scope='Logits', reuse=False) embeddings = tf.nn.l2_normalize(prelogits, 1, 1e-10, name='embeddings') if center_loss_factor > 0.0: prelogits_center_loss, _ = facenet.center_loss( prelogits, label_batch, center_loss_alfa, nrof_classes) tf.add_to_collection( tf.GraphKeys.REGULARIZATION_LOSSES, prelogits_center_loss * args.center_loss_factor) # Calculate the average cross entropy loss across the batch cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits( labels=label_batch, logits=logits, name='cross_entropy_per_example') cross_entropy_mean = tf.reduce_mean(cross_entropy, name='cross_entropy') tf.add_to_collection('losses', cross_entropy_mean) # Calculate the total losses regularization_losses = tf.get_collection( tf.GraphKeys.REGULARIZATION_LOSSES, scope) total_loss = tf.add_n([cross_entropy_mean] + regularization_losses, name='total_loss') return total_loss, regularization_losses, embeddings
def testCenterLoss(self): batch_size = 16 nrof_features = 2 nrof_classes = 16 alfa = 0.5 with tf.Graph().as_default(): features = tf.placeholder(tf.float32, shape=(batch_size, nrof_features), name='features') labels = tf.placeholder(tf.int32, shape=(batch_size,), name='labels') # Define center loss center_loss, centers = facenet.center_loss(features, labels, alfa, nrof_classes) label_to_center = np.array( [ [-3,-3], [-3,-1], [-3,1], [-3,3], [-1,-3], [-1,-1], [-1,1], [-1,3], [ 1,-3], [ 1,-1], [ 1,1], [ 1,3], [ 3,-3], [ 3,-1], [ 3,1], [ 3,3] ]) sess = tf.Session() with sess.as_default(): sess.run(tf.global_variables_initializer()) np.random.seed(seed=666) for _ in range(0,100): # Create array of random labels lbls = np.random.randint(low=0, high=nrof_classes, size=(batch_size,)) feats = create_features(label_to_center, batch_size, nrof_features, lbls) center_loss_, centers_ = sess.run([center_loss, centers], feed_dict={features:feats, labels:lbls}) # After a large number of updates the estimated centers should be close to the true ones np.testing.assert_almost_equal(centers_, label_to_center, decimal=5, err_msg='Incorrect estimated centers') np.testing.assert_almost_equal(center_loss_, 0.0, decimal=5, err_msg='Incorrect center loss')
def main(args): network = importlib.import_module(args.model_def, 'inference') subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S') log_dir = os.path.join(os.path.expanduser(args.logs_base_dir), subdir) if not os.path.isdir( log_dir): # Create the log directory if it doesn't exist os.makedirs(log_dir) model_dir = os.path.join(os.path.expanduser(args.models_base_dir), subdir) if not os.path.isdir( model_dir): # Create the model directory if it doesn't exist os.makedirs(model_dir) # Store some git revision info in a text file in the log directory src_path, _ = os.path.split(os.path.realpath(__file__)) facenet.store_revision_info(src_path, log_dir, ' '.join(sys.argv)) np.random.seed(seed=args.seed) train_set = facenet.get_dataset(args.data_dir) print('Model directory: %s' % model_dir) print('Log directory: %s' % log_dir) pretrained_model = None if args.pretrained_model: pretrained_model = os.path.expanduser(args.pretrained_model) print('Pre-trained model: %s' % pretrained_model) if args.lfw_dir: print('LFW directory: %s' % args.lfw_dir) # Read the file containing the pairs used for testing pairs = lfw.read_pairs(os.path.expanduser(args.lfw_pairs)) # Get the paths for the corresponding images lfw_paths, actual_issame = lfw.get_paths( os.path.expanduser(args.lfw_dir), pairs, args.lfw_file_ext) with tf.Graph().as_default(): tf.set_random_seed(args.seed) global_step = tf.Variable(0, trainable=False) # Get a list of image paths and their labels image_list, label_list = facenet.get_image_paths_and_labels(train_set) # Read data and apply label preserving distortions image_batch, label_batch = facenet.read_and_augument_data( image_list, label_list, args.image_size, args.batch_size, args.max_nrof_epochs, args.random_crop, args.random_flip, args.nrof_preprocess_threads) print('Total number of classes: %d' % len(train_set)) print('Total number of examples: %d' % len(image_list)) # Node for input images image_batch.set_shape((None, args.image_size, args.image_size, 3)) image_batch = tf.identity(image_batch, name='input') # Placeholder for the learning rate learning_rate_placeholder = tf.placeholder(tf.float32, name='learning_rate') # Placeholder for phase_train phase_train_placeholder = tf.placeholder(tf.bool, name='phase_train') # Build the inference graph prelogits, _ = network.inference(image_batch, args.keep_probability, phase_train=phase_train_placeholder, weight_decay=args.weight_decay) with tf.variable_scope('Logits'): n = int(prelogits.get_shape()[1]) m = len(train_set) w = tf.get_variable( 'w', shape=[n, m], dtype=tf.float32, initializer=tf.truncated_normal_initializer(stddev=0.1), regularizer=slim.l2_regularizer(args.weight_decay), trainable=True) b = tf.get_variable('b', [m], initializer=None, trainable=True) logits = tf.matmul(prelogits, w) + b # Add DeCov regularization loss if args.decov_loss_factor > 0.0: logits_decov_loss = facenet.decov_loss( logits) * args.decov_loss_factor tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES, logits_decov_loss) # Add center loss update_centers = tf.no_op('update_centers') if args.center_loss_factor > 0.0: prelogits_center_loss, update_centers = facenet.center_loss( prelogits, label_batch, args.center_loss_alfa) tf.add_to_collection( tf.GraphKeys.REGULARIZATION_LOSSES, prelogits_center_loss * args.center_loss_factor) embeddings = tf.nn.l2_normalize(prelogits, 1, 1e-10, name='embeddings') learning_rate = tf.train.exponential_decay( learning_rate_placeholder, global_step, args.learning_rate_decay_epochs * args.epoch_size, args.learning_rate_decay_factor, staircase=True) tf.scalar_summary('learning_rate', learning_rate) # Calculate the average cross entropy loss across the batch cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits( logits, label_batch, name='cross_entropy_per_example') cross_entropy_mean = tf.reduce_mean(cross_entropy, name='cross_entropy') tf.add_to_collection('losses', cross_entropy_mean) # Calculate the total losses regularization_losses = tf.get_collection( tf.GraphKeys.REGULARIZATION_LOSSES) total_loss = tf.add_n([cross_entropy_mean] + regularization_losses, name='total_loss') # Build a Graph that trains the model with one batch of examples and updates the model parameters train_op = facenet.train(total_loss, global_step, args.optimizer, learning_rate, args.moving_average_decay, tf.all_variables(), args.log_histograms) # Create a saver save_variables = list(set(tf.all_variables()) - set([w]) - set([b])) saver = tf.train.Saver(save_variables, max_to_keep=3) # Build the summary operation based on the TF collection of Summaries. summary_op = tf.merge_all_summaries() # Start running operations on the Graph. gpu_options = tf.GPUOptions( per_process_gpu_memory_fraction=args.gpu_memory_fraction) sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options, log_device_placement=False)) sess.run(tf.initialize_all_variables()) sess.run(tf.initialize_local_variables()) summary_writer = tf.train.SummaryWriter(log_dir, sess.graph) tf.train.start_queue_runners(sess=sess) with sess.as_default(): if pretrained_model: saver.restore(sess, pretrained_model) # Training and validation loop epoch = 0 while epoch < args.max_nrof_epochs: step = sess.run(global_step, feed_dict=None) epoch = step // args.epoch_size # Train for one epoch train(args, sess, epoch, phase_train_placeholder, learning_rate_placeholder, global_step, total_loss, train_op, summary_op, summary_writer, regularization_losses, args.learning_rate_schedule_file, update_centers) # Save variables and the metagraph if it doesn't exist already save_variables_and_metagraph(sess, saver, summary_writer, model_dir, subdir, step) # Evaluate on LFW if args.lfw_dir: start_time = time.time() _, _, accuracy, val, val_std, far = lfw.validate( sess, lfw_paths, actual_issame, args.seed, args.batch_size, image_batch, phase_train_placeholder, embeddings, nrof_folds=args.lfw_nrof_folds) print('Accuracy: %1.3f+-%1.3f' % (np.mean(accuracy), np.std(accuracy))) print('Validation rate: %2.5f+-%2.5f @ FAR=%2.5f' % (val, val_std, far)) lfw_time = time.time() - start_time # Add validation loss and accuracy to summary summary = tf.Summary() #pylint: disable=maybe-no-member summary.value.add(tag='lfw/accuracy', simple_value=np.mean(accuracy)) summary.value.add(tag='lfw/val_rate', simple_value=val) summary.value.add(tag='time/lfw', simple_value=lfw_time) summary_writer.add_summary(summary, step) with open(os.path.join(log_dir, 'lfw_result.txt'), 'at') as f: f.write('%d\t%.5f\t%.5f\n' % (step, np.mean(accuracy), val)) return model_dir
def main(args): network = importlib.import_module(args.model_def) subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S') log_dir = os.path.join(os.path.expanduser(args.logs_base_dir), subdir) if not os.path.isdir(log_dir): # Create the log directory if it doesn't exist os.makedirs(log_dir) model_dir = os.path.join(os.path.expanduser(args.models_base_dir), subdir) if not os.path.isdir(model_dir): # Create the model directory if it doesn't exist os.makedirs(model_dir) # Write arguments to a text file facenet.write_arguments_to_file(args, os.path.join(log_dir, 'arguments.txt')) # Store some git revision info in a text file in the log directory src_path,_ = os.path.split(os.path.realpath(__file__)) facenet.store_revision_info(src_path, log_dir, ' '.join(sys.argv)) np.random.seed(seed=args.seed) random.seed(args.seed) train_set = facenet.get_dataset(args.data_dir) if args.filter_filename: train_set = filter_dataset(train_set, os.path.expanduser(args.filter_filename), args.filter_percentile, args.filter_min_nrof_images_per_class) nrof_classes = len(train_set) print('Model directory: %s' % model_dir) print('Log directory: %s' % log_dir) pretrained_model = None if args.pretrained_model: pretrained_model = os.path.expanduser(args.pretrained_model) print('Pre-trained model: %s' % pretrained_model) if args.lfw_dir: print('LFW directory: %s' % args.lfw_dir) # Read the file containing the pairs used for testing pairs = lfw.read_pairs(os.path.expanduser(args.lfw_pairs)) # Get the paths for the corresponding images lfw_paths, actual_issame = lfw.get_paths(os.path.expanduser(args.lfw_dir), pairs, args.lfw_file_ext) with tf.Graph().as_default(), tf.device('/cpu:0'): tf.set_random_seed(args.seed) global_step = tf.Variable(0, trainable=False) # Get a list of image paths and their labels image_list, label_list = facenet.get_image_paths_and_labels(train_set) assert len(image_list)>0, 'The dataset should not be empty' # Create a queue that produces indices into the image_list and label_list labels = ops.convert_to_tensor(label_list, dtype=tf.int32) range_size = array_ops.shape(labels)[0] index_queue = tf.train.range_input_producer(range_size, num_epochs=None, shuffle=True, seed=None, capacity=32) index_dequeue_op = index_queue.dequeue_many(args.batch_size*args.epoch_size, 'index_dequeue') learning_rate_placeholder = tf.placeholder(tf.float32, name='learning_rate') batch_size_placeholder = tf.placeholder(tf.int32, name='batch_size') phase_train_placeholder = tf.placeholder(tf.bool, name='phase_train') image_paths_placeholder = tf.placeholder(tf.string, shape=(None,1), name='image_paths') labels_placeholder = tf.placeholder(tf.int64, shape=(None,1), name='labels') input_queue = data_flow_ops.FIFOQueue(capacity=100000, dtypes=[tf.string, tf.int64], shapes=[(1,), (1,)], shared_name=None, name=None) enqueue_op = input_queue.enqueue_many([image_paths_placeholder, labels_placeholder], name='enqueue_op') args.input_queue = input_queue nrof_preprocess_threads = 4 images_and_labels = [] for _ in range(nrof_preprocess_threads): filenames, label = input_queue.dequeue() images = [] for filename in tf.unstack(filenames): file_contents = tf.read_file(filename) image = tf.image.decode_image(file_contents, channels=3) if args.random_rotate: image = tf.py_func(facenet.random_rotate_image, [image], tf.uint8) if args.random_crop: image = tf.random_crop(image, [args.image_size, args.image_size, 3]) else: image = tf.image.resize_image_with_crop_or_pad(image, args.image_size, args.image_size) if args.random_flip: image = tf.image.random_flip_left_right(image) #pylint: disable=no-member image.set_shape((args.image_size, args.image_size, 3)) images.append(tf.image.per_image_standardization(image)) images_and_labels.append([images, label]) image_batch, label_batch = tf.train.batch_join( images_and_labels, batch_size=batch_size_placeholder, shapes=[(args.image_size, args.image_size, 3), ()], enqueue_many=True, capacity=4 * nrof_preprocess_threads * args.batch_size, allow_smaller_final_batch=True) image_batch = tf.identity(image_batch, 'image_batch') image_batch = tf.identity(image_batch, 'input') label_batch = tf.identity(label_batch, 'label_batch') print('Total number of classes: %d' % nrof_classes) print('Total number of examples: %d' % len(image_list)) print('Building training graph') learning_rate = tf.train.exponential_decay(learning_rate_placeholder, global_step, args.learning_rate_decay_epochs*args.epoch_size, args.learning_rate_decay_factor, staircase=True) tf.summary.scalar('learning_rate', learning_rate) # opt = tf.train.GradientDescentOptimizer(learning_rate) total_grads = [] loss_reg = [] loss_cross = [] loss_center = [] images_splits = tf.split(axis=0, num_or_size_splits=args.num_gpus, value=image_batch) labels_splits = tf.split(axis=0, num_or_size_splits=args.num_gpus, value=label_batch) embedding_list = [] with tf.variable_scope(tf.get_variable_scope()): for i in range(args.num_gpus): with tf.device('/gpu:%d' % i): with tf.name_scope('facenet_%d' % (i)) as scope: print('Build training graph on gpu %d' % i) # Build the inference graph prelogits, _ = network.inference(images_splits[i], args.keep_probability, phase_train=phase_train_placeholder, bottleneck_layer_size=args.embedding_size, weight_decay=args.weight_decay) embeddings = tf.nn.l2_normalize(prelogits, 1, 1e-10, name='embeddings') if args.l2_softmax_alpha > 0: prelogits = embeddings * args.l2_softmax_alpha logits = slim.fully_connected(prelogits, len(train_set), activation_fn=None, weights_initializer=tf.truncated_normal_initializer(stddev=0.1), weights_regularizer=slim.l2_regularizer(args.weight_decay), scope='Logits', reuse=False) embedding_list.append(embeddings) regularization_losses = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES) regularization_losses = sum(regularization_losses) loss_reg.append(regularization_losses) tf.add_to_collection('losses', regularization_losses) # Add center loss if args.center_loss_factor>0.0: prelogits_center_loss, _ = facenet.center_loss(prelogits, labels_splits[i], args.center_loss_alfa, nrof_classes) center_loss = tf.identity(prelogits_center_loss * args.center_loss_factor, 'center_loss') loss_center.append(center_loss) tf.add_to_collection('losses', center_loss) # Reuse variables for the next tower. tf.get_variable_scope().reuse_variables() # Calculate the average cross entropy loss across the batch cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits( labels=labels_splits[i], logits=logits, name='cross_entropy_per_example') cross_entropy_mean = tf.reduce_mean(cross_entropy, name='cross_entropy') loss_cross.append(cross_entropy_mean) tf.add_to_collection('losses', cross_entropy_mean) # Calculate the total losses total_loss = cross_entropy_mean + regularization_losses if args.center_loss_factor>0.0: total_loss = total_loss + center_loss total_loss = tf.identity(total_loss, name='total_loss') opt = facenet.optimizer(total_loss, global_step, args.optimizer, learning_rate, args.moving_average_decay, tf.global_variables(), args.log_histograms) grads = opt.compute_gradients(total_loss) total_grads.append(grads) print('Build training total graph') regularization_losses = tf.add_n(loss_reg) / args.num_gpus tf.summary.scalar('loss/regularization', regularization_losses) tf.summary.scalar('loss/center', tf.add_n(loss_center) / args.num_gpus) tf.summary.scalar('loss/cross', tf.add_n(loss_cross) / args.num_gpus) total_loss = tf.add_n(loss_reg + loss_cross + loss_center) / args.num_gpus tf.summary.scalar('loss/total', total_loss) embeddings = tf.concat(axis=0, values=embedding_list) # We must calculate the mean of each gradient. Note that this is the # synchronization point across all towers. grads = average_gradients(total_grads) # Apply the gradients to adjust the shared variables. apply_gradient_op = opt.apply_gradients(grads, global_step=global_step) # Track the moving averages of all trainable variables. variable_averages = tf.train.ExponentialMovingAverage( args.moving_average_decay, global_step) variables_averages_op = variable_averages.apply(tf.trainable_variables()) # Group all updates to into a single train op. train_op = tf.group(apply_gradient_op, variables_averages_op) # Create a saver saver = tf.train.Saver(tf.trainable_variables(), max_to_keep=3) # Build the summary operation based on the TF collection of Summaries. summary_op = tf.summary.merge_all() # Start running operations on the Graph. gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=args.gpu_memory_fraction) sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options, log_device_placement=False)) sess.run(tf.global_variables_initializer()) sess.run(tf.local_variables_initializer()) summary_writer = tf.summary.FileWriter(log_dir, sess.graph) coord = tf.train.Coordinator() tf.train.start_queue_runners(coord=coord, sess=sess) with sess.as_default(): if pretrained_model: print('Restoring pretrained model: %s' % pretrained_model) saver.restore(sess, pretrained_model) # Training and validation loop print('Running training') epoch = 0 while epoch < args.max_nrof_epochs: step = sess.run(global_step, feed_dict=None) epoch = step // args.epoch_size # Train for one epoch train(args, sess, epoch, image_list, label_list, index_dequeue_op, enqueue_op, image_paths_placeholder, labels_placeholder, learning_rate_placeholder, phase_train_placeholder, batch_size_placeholder, global_step, total_loss, train_op, summary_op, summary_writer, regularization_losses, args.learning_rate_schedule_file) # Save variables and the metagraph if it doesn't exist already save_variables_and_metagraph(sess, saver, summary_writer, model_dir, subdir, step) # Evaluate on LFW if args.lfw_dir: evaluate(sess, enqueue_op, image_paths_placeholder, labels_placeholder, phase_train_placeholder, batch_size_placeholder, embeddings, label_batch, lfw_paths, actual_issame, args.lfw_batch_size, args.lfw_nrof_folds, log_dir, step, summary_writer) return model_dir
def main(argv=None): # pylint: disable=unused-argument if FLAGS.self_test: print('Running self-test.') train_data, train_labels = fake_data(256) validation_data, validation_labels = fake_data(EVAL_BATCH_SIZE) test_data, test_labels = fake_data(EVAL_BATCH_SIZE) num_epochs = 1 else: # Get the data. train_data_filename = maybe_download('train-images-idx3-ubyte.gz') train_labels_filename = maybe_download('train-labels-idx1-ubyte.gz') test_data_filename = maybe_download('t10k-images-idx3-ubyte.gz') test_labels_filename = maybe_download('t10k-labels-idx1-ubyte.gz') # Extract it into numpy arrays. train_data = extract_data(train_data_filename, 60000) train_labels = extract_labels(train_labels_filename, 60000) test_data = extract_data(test_data_filename, 10000) test_labels = extract_labels(test_labels_filename, 10000) # Generate a validation set. validation_data = train_data[:VALIDATION_SIZE, ...] validation_labels = train_labels[:VALIDATION_SIZE] train_data = train_data[VALIDATION_SIZE:, ...] train_labels = train_labels[VALIDATION_SIZE:] num_epochs = NUM_EPOCHS train_size = train_labels.shape[0] # This is where training samples and labels are fed to the graph. # These placeholder nodes will be fed a batch of training data at each # training step using the {feed_dict} argument to the Run() call below. train_data_node = tf.compat.v1.placeholder(data_type(), shape=(BATCH_SIZE, IMAGE_SIZE, IMAGE_SIZE, NUM_CHANNELS)) train_labels_node = tf.compat.v1.placeholder(tf.int64, shape=(BATCH_SIZE, )) eval_data = tf.compat.v1.placeholder(data_type(), shape=(EVAL_BATCH_SIZE, IMAGE_SIZE, IMAGE_SIZE, NUM_CHANNELS)) # The variables below hold all the trainable weights. They are passed an # initial value which will be assigned when we call: # {tf.global_variables_initializer().run()} conv1_weights = tf.Variable( tf.truncated_normal( [5, 5, NUM_CHANNELS, 32], # 5x5 filter, depth 32. stddev=0.1, seed=SEED, dtype=data_type())) conv1_biases = tf.Variable(tf.zeros([32], dtype=data_type())) conv2_weights = tf.Variable( tf.truncated_normal([5, 5, 32, 64], stddev=0.1, seed=SEED, dtype=data_type())) conv2_biases = tf.Variable(tf.constant(0.1, shape=[64], dtype=data_type())) fc1_weights = tf.Variable( # fully connected, depth 512. tf.truncated_normal([IMAGE_SIZE // 4 * IMAGE_SIZE // 4 * 64, 512], stddev=0.1, seed=SEED, dtype=data_type())) fc1_biases = tf.Variable(tf.constant(0.1, shape=[512], dtype=data_type())) fc1p_weights = tf.Variable( # fully connected, depth 512. tf.truncated_normal([512, 2], stddev=0.1, seed=SEED, dtype=data_type())) fc1p_biases = tf.Variable(tf.constant(0.1, shape=[2], dtype=data_type())) fc2_weights = tf.Variable( tf.truncated_normal([2, NUM_LABELS], stddev=0.1, seed=SEED, dtype=data_type())) fc2_biases = tf.Variable( tf.constant(0.1, shape=[NUM_LABELS], dtype=data_type())) def batch_norm(x, phase_train): #pylint: disable=unused-variable """ Batch normalization on convolutional maps. Args: x: Tensor, 4D BHWD input maps n_out: integer, depth of input maps phase_train: boolean tf.Variable, true indicates training phase scope: string, variable scope affn: whether to affn-transform outputs Return: normed: batch-normalized maps Ref: http://stackoverflow.com/questions/33949786/how-could-i-use-batch-normalization-in-tensorflow/33950177 """ name = 'batch_norm' with tf.compat.v1.variable_scope(name): phase_train = tf.convert_to_tensor(phase_train, dtype=tf.bool) n_out = int(x.get_shape()[-1]) beta = tf.Variable(tf.constant(0.0, shape=[n_out], dtype=x.dtype), name=name + '/beta', trainable=True, dtype=x.dtype) gamma = tf.Variable(tf.constant(1.0, shape=[n_out], dtype=x.dtype), name=name + '/gamma', trainable=True, dtype=x.dtype) batch_mean, batch_var = tf.nn.moments(x, [0], name='moments') ema = tf.train.ExponentialMovingAverage(decay=0.9) def mean_var_with_update(): ema_apply_op = ema.apply([batch_mean, batch_var]) with tf.control_dependencies([ema_apply_op]): return tf.identity(batch_mean), tf.identity(batch_var) mean, var = control_flow_ops.cond( phase_train, mean_var_with_update, lambda: (ema.average(batch_mean), ema.average(batch_var))) normed = tf.nn.batch_normalization(x, mean, var, beta, gamma, 1e-3) return normed # We will replicate the model structure for the training subgraph, as well # as the evaluation subgraphs, while sharing the trainable parameters. def model(data, train=False): """The Model definition.""" # 2D convolution, with 'SAME' padding (i.e. the output feature map has # the same size as the input). Note that {strides} is a 4D array whose # shape matches the data layout: [image index, y, x, depth]. conv = tf.nn.conv2d(data, conv1_weights, strides=[1, 1, 1, 1], padding='SAME') # Bias and rectified linear non-linearity. relu = tf.nn.relu(tf.nn.bias_add(conv, conv1_biases)) # Max pooling. The kernel size spec {ksize} also follows the layout of # the data. Here we have a pooling window of 2, and a stride of 2. pool = tf.nn.max_pool(relu, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME') conv = tf.nn.conv2d(pool, conv2_weights, strides=[1, 1, 1, 1], padding='SAME') relu = tf.nn.relu(tf.nn.bias_add(conv, conv2_biases)) pool = tf.nn.max_pool(relu, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME') # Reshape the feature map cuboid into a 2D matrix to feed it to the # fully connected layers. pool_shape = pool.get_shape().as_list() #pylint: disable=no-member reshape = tf.reshape( pool, [pool_shape[0], pool_shape[1] * pool_shape[2] * pool_shape[3]]) # Fully connected layer. Note that the '+' operation automatically # broadcasts the biases. hidden = tf.nn.relu(tf.matmul(reshape, fc1_weights) + fc1_biases) # Add a 50% dropout during training only. Dropout also scales # activations such that no rescaling is needed at evaluation time. if train: hidden = tf.nn.dropout(hidden, 0.5, seed=SEED) hidden = tf.matmul(hidden, fc1p_weights) + fc1p_biases return tf.nn.relu(tf.matmul(hidden, fc2_weights) + fc2_biases), hidden # Training computation: logits + cross-entropy loss. logits, hidden = model(train_data_node, True) #logits = batch_norm(logits, True) xent_loss = tf.reduce_mean( tf.nn.sparse_softmax_cross_entropy_with_logits(logits, train_labels_node)) beta = 1e-3 #center_loss, update_centers = center_loss_op(hidden, train_labels_node) center_loss, _ = facenet.center_loss(hidden, train_labels_node, 0.95, NUM_LABELS) loss = xent_loss + beta * center_loss # L2 regularization for the fully connected parameters. regularizers = (tf.nn.l2_loss(fc1_weights) + tf.nn.l2_loss(fc1_biases) + tf.nn.l2_loss(fc2_weights) + tf.nn.l2_loss(fc2_biases)) # Add the regularization term to the loss. loss += 5e-4 * regularizers # Optimizer: set up a variable that's incremented once per batch and # controls the learning rate decay. batch = tf.Variable(0, dtype=data_type()) # Decay once per epoch, using an exponential schedule starting at 0.01. learning_rate = tf.train.exponential_decay( 0.01, # Base learning rate. batch * BATCH_SIZE, # Current index into the dataset. train_size, # Decay step. 0.95, # Decay rate. staircase=True) # Use simple momentum for the optimization. optimizer = tf.train.MomentumOptimizer(learning_rate, 0.9).minimize(loss, global_step=batch) # Predictions for the current training minibatch. train_prediction = tf.nn.softmax(logits) # Predictions for the test and validation, which we'll compute less often. eval_logits, eval_embeddings = model(eval_data) eval_prediction = tf.nn.softmax(eval_logits) # Small utility function to evaluate a dataset by feeding batches of data to # {eval_data} and pulling the results from {eval_predictions}. # Saves memory and enables this to run on smaller GPUs. def eval_in_batches(data, sess): """Get all predictions for a dataset by running it in small batches.""" size = data.shape[0] if size < EVAL_BATCH_SIZE: raise ValueError("batch size for evals larger than dataset: %d" % size) predictions = np.ndarray(shape=(size, NUM_LABELS), dtype=np.float32) for begin in xrange(0, size, EVAL_BATCH_SIZE): end = begin + EVAL_BATCH_SIZE if end <= size: predictions[begin:end, :] = sess.run( eval_prediction, feed_dict={eval_data: data[begin:end, ...]}) else: batch_predictions = sess.run( eval_prediction, feed_dict={eval_data: data[-EVAL_BATCH_SIZE:, ...]}) predictions[begin:, :] = batch_predictions[begin - size:, :] return predictions def calculate_embeddings(data, sess): """Get all predictions for a dataset by running it in small batches.""" size = data.shape[0] if size < EVAL_BATCH_SIZE: raise ValueError("batch size for evals larger than dataset: %d" % size) predictions = np.ndarray(shape=(size, 2), dtype=np.float32) for begin in xrange(0, size, EVAL_BATCH_SIZE): end = begin + EVAL_BATCH_SIZE if end <= size: predictions[begin:end, :] = sess.run( eval_embeddings, feed_dict={eval_data: data[begin:end, ...]}) else: batch_predictions = sess.run( eval_embeddings, feed_dict={eval_data: data[-EVAL_BATCH_SIZE:, ...]}) predictions[begin:, :] = batch_predictions[begin - size:, :] return predictions # Create a local session to run the training. start_time = time.time() with tf.compat.v1.Session() as sess: # Run all the initializers to prepare the trainable parameters. tf.global_variables_initializer().run() #pylint: disable=no-member print('Initialized!') # Loop through training steps. for step in xrange(int(num_epochs * train_size) // BATCH_SIZE): # Compute the offset of the current minibatch in the data. # Note that we could use better randomization across epochs. offset = (step * BATCH_SIZE) % (train_size - BATCH_SIZE) batch_data = train_data[offset:(offset + BATCH_SIZE), ...] batch_labels = train_labels[offset:(offset + BATCH_SIZE)] # This dictionary maps the batch data (as a numpy array) to the # node in the graph it should be fed to. feed_dict = { train_data_node: batch_data, train_labels_node: batch_labels } # Run the graph and fetch some of the nodes. #_, l, lr, predictions = sess.run([optimizer, loss, learning_rate, train_prediction], feed_dict=feed_dict) _, cl, l, lr, predictions = sess.run([ optimizer, center_loss, loss, learning_rate, train_prediction ], feed_dict=feed_dict) if step % EVAL_FREQUENCY == 0: elapsed_time = time.time() - start_time start_time = time.time() print('Step %d (epoch %.2f), %.1f ms' % (step, float(step) * BATCH_SIZE / train_size, 1000 * elapsed_time / EVAL_FREQUENCY)) print('Minibatch loss: %.3f %.3f, learning rate: %.6f' % (l, cl * beta, lr)) print('Minibatch error: %.1f%%' % error_rate(predictions, batch_labels)) print('Validation error: %.1f%%' % error_rate( eval_in_batches(validation_data, sess), validation_labels)) sys.stdout.flush() # Finally print the result! test_error = error_rate(eval_in_batches(test_data, sess), test_labels) print('Test error: %.1f%%' % test_error) if FLAGS.self_test: print('test_error', test_error) assert test_error == 0.0, 'expected 0.0 test_error, got %.2f' % ( test_error, ) train_embeddings = calculate_embeddings(train_data, sess) color_list = ['b', 'g', 'r', 'c', 'm', 'y', 'k', 'b', 'g', 'r', 'c'] plt.figure(1) for n in range(0, 10): idx = np.where(train_labels[0:10000] == n) plt.plot(train_embeddings[idx, 0], train_embeddings[idx, 1], color_list[n] + '.') plt.show()
def main(args): print('args used to train the model:') print(args) # =========================================================================== # # 数据预处理,路径问题等 # =========================================================================== # network = importlib.import_module(args.model_def) image_size = (args.image_size, args.image_size) subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S') # '20180614-100359' subdir += args.dir_postfix log_dir = os.path.join(os.path.expanduser(args.logs_base_dir), subdir) # 本地保存log的路径 log_dir += args.dir_postfix val_log_dir = log_dir # 本地保存validation result的路径 if not os.path.isdir( log_dir): # Create the log directory if it doesn't exist os.makedirs(log_dir) model_dir = os.path.join(os.path.expanduser(args.models_base_dir), subdir) # 本地保存model的路径,最后一层目录用上面生成的日期命名 if not os.path.isdir( model_dir): # Create the model directory if it doesn't exist os.makedirs(model_dir) stat_file_name = os.path.join(log_dir, 'stat.h5') # Write arguments to a text file, 把训练时用的所有参数保存到txt中 facenet.write_arguments_to_file(args, os.path.join(log_dir, 'arguments.txt')) # Store some git revision info in a text file in the log directory src_path, _ = os.path.split(os.path.realpath(__file__)) facenet.store_revision_info(src_path, log_dir, ' '.join(sys.argv)) np.random.seed(seed=args.seed) random.seed(args.seed) # dataset中是多个ImageClass对象,每个对象中有类名(name)和该类所有图片的路径(image_paths) dataset = facenet.get_dataset(args.data_dir) # filter_name default='', 这个训练的时候没用到, 先不管了 if args.filter_filename: dataset = filter_dataset(dataset, os.path.expanduser(args.filter_filename), args.filter_percentile, args.filter_min_nrof_images_per_class) # validation_set_split_ratio default=0.0, 如果需要验证操作的话设置这个 # 划分验证集有两种方式:按类划分和按图片划分(默认) if args.validation_set_split_ratio > 0.0: train_set, val_set = facenet.split_dataset( dataset, args.validation_set_split_ratio, args.min_nrof_val_images_per_class, 'SPLIT_IMAGES') else: train_set, val_set = dataset, [] nrof_classes = len(train_set) print('Model directory: %s' % model_dir) print('Log directory: %s' % log_dir) pretrained_model = None if args.pretrained_model: pretrained_model = os.path.expanduser(args.pretrained_model) print('Pre-trained model: %s' % pretrained_model) if args.lfw_dir: print('LFW directory: %s' % args.lfw_dir) # Read the file containing the pairs used for testing # pairs[0] = ['Abel_Pacheco', '1', '4'] # args.lfw_pairs: data/pairs.txt, 这个文件中每一行或有三个字段或有四个字段 # 如果有三个字段表示从一个人的所有图片中选择两个(正样本, actual_issame=True) # 如果有四个字段表示从两个人的所有图片中各选一个(负样本, actual_issame=False) pairs = lfw.read_pairs(os.path.expanduser(args.lfw_pairs)) # Get the paths for the corresponding images # lfw_paths里的每个值都是一个元组(path0, path1), actual_issame里对应的是这个元组是正样本还是副样本 lfw_paths, actual_issame = lfw.get_paths( os.path.expanduser(args.lfw_dir), pairs) # =========================================================================== # # 下面开始处理TensorFlow相关的东西 # =========================================================================== # with tf.Graph().as_default(): # =========================================================================== # # Input pipeline # =========================================================================== # tf.set_random_seed(args.seed) global_step = tf.Variable(0, trainable=False) # Get a list of image paths and their labels # 这两个list是训练集中的所有数据 image_list, label_list = facenet.get_image_paths_and_labels(train_set) assert len(image_list) > 0, 'The training set should not be empty' val_image_list, val_label_list = facenet.get_image_paths_and_labels( val_set) # Create a queue that produces indices into the image_list and label_list labels = ops.convert_to_tensor(label_list, dtype=tf.int32) range_size = array_ops.shape(labels)[0] # num_epochs=None时,循环生成0到range_size-1的数 index_queue = tf.train.range_input_producer(range_size, num_epochs=None, shuffle=True, seed=None, capacity=32) # 这个op是用来生成索引值的,每次从队列里取出一个epoch中所有图片数量的下标 index_dequeue_op = index_queue.dequeue_many( args.batch_size * args.epoch_size, 'index_dequeue') learning_rate_placeholder = tf.placeholder(tf.float32, name='learning_rate') batch_size_placeholder = tf.placeholder(tf.int32, name='batch_size') phase_train_placeholder = tf.placeholder(tf.bool, name='phase_train') image_paths_placeholder = tf.placeholder(tf.string, shape=(None, 1), name='image_paths') labels_placeholder = tf.placeholder(tf.int32, shape=(None, 1), name='labels') control_placeholder = tf.placeholder(tf.int32, shape=(None, 1), name='control') nrof_preprocess_threads = 4 input_queue = data_flow_ops.FIFOQueue( capacity=2000000, dtypes=[tf.string, tf.int32, tf.int32], shapes=[(1, ), (1, ), (1, )], shared_name=None, name=None) enqueue_op = input_queue.enqueue_many( [image_paths_placeholder, labels_placeholder, control_placeholder], name='enqueue_op') # create input pipeline, 将上面image path中的文件取出来 image_batch, label_batch = facenet.create_input_pipeline( input_queue, image_size, nrof_preprocess_threads, batch_size_placeholder) image_batch = tf.identity(image_batch, 'image_batch') image_batch = tf.identity(image_batch, 'input') label_batch = tf.identity(label_batch, 'label_batch') print('Number of classes in training set: %d' % nrof_classes) print('Number of examples in training set: %d' % len(image_list)) print('Number of classes in validation set: %d' % len(val_set)) print('Number of examples in validation set: %d' % len(val_image_list)) print('Building training graph') ### Build the inference graph # prelogits是128维的向量 prelogits, _ = network.inference( image_batch, args.keep_probability, phase_train=phase_train_placeholder, bottleneck_layer_size=args.embedding_size, weight_decay=args.weight_decay) # TODO: Inject some code here for fine tuning # logits的shape: [None, len(train_set)] logits = slim.fully_connected( prelogits, len(train_set), activation_fn=None, weights_initializer=slim.initializers.xavier_initializer(), weights_regularizer=slim.l2_regularizer(args.weight_decay), scope='Logits', reuse=False) # 这步操作之后在测试时就可以拿到这个值了 logits = tf.identity(logits, name='logits') # axis=1, 是把每行进行normalize, 每行是一个样本, 128维(或512维)的向量 embeddings = tf.nn.l2_normalize(prelogits, 1, 1e-10, name='embeddings') # Norm for the prelogits eps = 1e-4 prelogits_norm = tf.reduce_mean( tf.norm(tf.abs(prelogits) + eps, ord=args.prelogits_norm_p, axis=1)) # 把prelogits进行norm操作得到的是一个数,这个数乘个weight作为loss的一部分,--prelogits_norm_loss_factor 5e-4 tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES, prelogits_norm * args.prelogits_norm_loss_factor) # Add center loss, 这个center loss作为正则化loss的一部分, 出自一篇人脸识别的论文, 先不管 # 这个loss默认权重是0, 文档中给出的训练脚本并没有用这个loss prelogits_center_loss, _ = facenet.center_loss(prelogits, label_batch, args.center_loss_alfa, nrof_classes) tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES, prelogits_center_loss * args.center_loss_factor) learning_rate = tf.train.exponential_decay( learning_rate_placeholder, global_step, args.learning_rate_decay_epochs * args.epoch_size, args.learning_rate_decay_factor, staircase=True) tf.summary.scalar('learning_rate', learning_rate) # Calculate the average cross entropy loss across the batch cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits( labels=label_batch, logits=logits, name='cross_entropy_per_example') cross_entropy_mean = tf.reduce_mean(cross_entropy, name='cross_entropy') tf.add_to_collection('losses', cross_entropy_mean) correct_prediction = tf.cast( tf.equal(tf.argmax(logits, 1), tf.cast(label_batch, tf.int64)), tf.float32) accuracy = tf.reduce_mean(correct_prediction) # Calculate the total losses regularization_losses = tf.get_collection( tf.GraphKeys.REGULARIZATION_LOSSES) # 这个total_loss是ce和regular loss的和,应该是已经把所有loss的值都加起来了 total_loss = tf.add_n([cross_entropy_mean] + regularization_losses, name='total_loss') # Build a Graph that trains the model with one batch of examples and updates the model parameters train_op = facenet.train(total_loss, global_step, args.optimizer, learning_rate, args.moving_average_decay, tf.global_variables(), args.log_histograms) # Create a saver saver = tf.train.Saver(tf.trainable_variables(), max_to_keep=20) # Build the summary operation based on the TF collection of Summaries. summary_op = tf.summary.merge_all() ### Start running operations on the Graph. gpu_options = tf.GPUOptions( per_process_gpu_memory_fraction=args.gpu_memory_fraction) sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options, log_device_placement=False)) sess.run(tf.global_variables_initializer()) sess.run(tf.local_variables_initializer()) summary_writer = tf.summary.FileWriter(log_dir, sess.graph) coord = tf.train.Coordinator() tf.train.start_queue_runners(coord=coord, sess=sess) # =========================================================================== # # Start training # =========================================================================== # with sess.as_default(): if pretrained_model: print('Restoring pretrained model: %s' % pretrained_model) # saver.restore(sess, pretrained_model) if args.checkpoint_exclude_scopes: exclusions = [args.checkpoint_exclude_scopes.split(',')] else: exclusions = [] # load from pre-trained model tf.contrib.framework.assign_from_checkpoint_fn( pretrained_model, [ var for var in tf.trainable_variables() if all(not var.op.name.startswith(exclusion) for exclusion in exclusions) ], ignore_missing_vars=args.ignore_missing_vars)(sess) # Training and validation loop print('Running training') # max_nrof_epochs: number of epochs to run, default=500 # epoch_size: number of batches per epoch,default=1000 nrof_steps = args.max_nrof_epochs * args.epoch_size # total batch number # 在验证集上验证的次数 nrof_val_samples = int( math.ceil(args.max_nrof_epochs / args.validate_every_n_epochs) ) # Validate every validate_every_n_epochs as well as in the last epoch stat = { # 每一个batch记录一次 'loss': np.zeros((nrof_steps, ), np.float32), 'center_loss': np.zeros((nrof_steps, ), np.float32), 'reg_loss': np.zeros((nrof_steps, ), np.float32), 'xent_loss': np.zeros((nrof_steps, ), np.float32), 'prelogits_norm': np.zeros((nrof_steps, ), np.float32), 'accuracy': np.zeros((nrof_steps, ), np.float32), # 每验证一次记录一次 'val_loss': np.zeros((nrof_val_samples, ), np.float32), 'val_xent_loss': np.zeros((nrof_val_samples, ), np.float32), 'val_accuracy': np.zeros((nrof_val_samples, ), np.float32), # 每个epoch记录一次 'lfw_accuracy': np.zeros((args.max_nrof_epochs, ), np.float32), 'lfw_valrate': np.zeros((args.max_nrof_epochs, ), np.float32), 'learning_rate': np.zeros((args.max_nrof_epochs, ), np.float32), 'time_train': np.zeros((args.max_nrof_epochs, ), np.float32), 'time_validate': np.zeros((args.max_nrof_epochs, ), np.float32), 'time_evaluate': np.zeros((args.max_nrof_epochs, ), np.float32), 'prelogits_hist': np.zeros((args.max_nrof_epochs, 1000), np.float32), } for epoch in range(1, args.max_nrof_epochs + 1): step = sess.run(global_step, feed_dict=None) # step = 0 ### Train for one epoch t = time.time() # =========================================================================== # # 一次训练的过程,学习率是在这里设置的,如果参数中的学习率小于0,就用调度文件中的学习率 # =========================================================================== # cont = train( args, sess, epoch, image_list, label_list, index_dequeue_op, enqueue_op, image_paths_placeholder, labels_placeholder, learning_rate_placeholder, phase_train_placeholder, batch_size_placeholder, control_placeholder, global_step, total_loss, train_op, summary_op, summary_writer, regularization_losses, args.learning_rate_schedule_file, stat, cross_entropy_mean, accuracy, learning_rate, prelogits, prelogits_center_loss, args.random_rotate, args.random_crop, args.random_flip, prelogits_norm, args.prelogits_hist_max, args.use_fixed_image_standardization) stat['time_train'][epoch - 1] = time.time() - t if not cont: # 每次结束一轮训练,train函数返回True break ### validate on val_set t = time.time() if len(val_image_list) > 0 and \ (( epoch - 1) % args.validate_every_n_epochs == args.validate_every_n_epochs - 1 or epoch == args.max_nrof_epochs): # =========================================================================== # # 如果验证集不为空 并且 到了设置的每n个epoch验证一次或者到了最后一个epoch, 则进行一次验证 # =========================================================================== # validate(args, sess, epoch, val_image_list, val_label_list, enqueue_op, image_paths_placeholder, labels_placeholder, control_placeholder, phase_train_placeholder, batch_size_placeholder, stat, total_loss, regularization_losses, cross_entropy_mean, accuracy, args.validate_every_n_epochs, args.use_fixed_image_standardization, val_log_dir) stat['time_validate'][epoch - 1] = time.time() - t # Save variables and the metagraph if it doesn't exist save_variables_and_metagraph(sess, saver, summary_writer, model_dir, subdir, epoch) ### Evaluate on LFW t = time.time() if args.lfw_dir: evaluate(sess, enqueue_op, image_paths_placeholder, labels_placeholder, phase_train_placeholder, batch_size_placeholder, control_placeholder, args.lfw_nrof_folds, log_dir, step, summary_writer, stat, epoch, embeddings, label_batch, lfw_paths, actual_issame, args.lfw_batch_size, args.lfw_distance_metric, args.lfw_subtract_mean, args.lfw_use_flipped_images, args.use_fixed_image_standardization) stat['time_evaluate'][epoch - 1] = time.time() - t print('Saving statistics') with h5py.File(stat_file_name, 'w') as f: for key, value in stat.items(): f.create_dataset(key, data=value) return model_dir
def main(args): network = importlib.import_module(args.model_def, 'inference') subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S') log_dir = os.path.join(os.path.expanduser(args.logs_base_dir), subdir) if not os.path.isdir( log_dir): # Create the log directory if it doesn't exist os.makedirs(log_dir) model_dir = os.path.join(os.path.expanduser(args.models_base_dir), subdir) if not os.path.isdir( model_dir): # Create the model directory if it doesn't exist os.makedirs(model_dir) # Store some git revision info in a text file in the log directory src_path, _ = os.path.split(os.path.realpath(__file__)) facenet.store_revision_info(src_path, log_dir, ' '.join(sys.argv)) np.random.seed(seed=args.seed) random.seed(args.seed) #train_set = facenet.get_dataset(args.data_dir) train_set = facenet.get_huge_dataset(args.data_dir, args.trainset_start, args.trainset_end) nrof_classes = len(train_set) # Get a list of image paths and their labels image_list, label_list = facenet.get_image_paths_and_labels(train_set) print('Total number of classes: %d' % nrof_classes) print('Total number of examples: %d' % len(image_list)) if args.filter_filename: print('Filtering...') train_set = filter_dataset(train_set, args.filter_filename, args.filter_percentile, args.filter_min_nrof_images_per_class, args.trainset_start) nrof_classes = len(train_set) # Get a list of image paths and their labels image_list, label_list = facenet.get_image_paths_and_labels(train_set) print('Total number of classes: %d' % nrof_classes) print('Total number of examples: %d' % len(image_list)) print('Model directory: %s' % model_dir) print('Log directory: %s' % log_dir) pretrained_model = None if args.pretrained_model: pretrained_model = os.path.expanduser(args.pretrained_model) meta_file, ckpt_file = facenet.get_model_filenames( os.path.expanduser(args.pretrained_model)) print('Pre-trained model: %s' % pretrained_model) if args.lfw_dir: print('LFW directory: %s' % args.lfw_dir) # Read the file containing the pairs used for testing pairs = lfw.read_pairs(os.path.expanduser(args.lfw_pairs)) # Get the paths for the corresponding images lfw_paths, actual_issame = lfw.get_paths( os.path.expanduser(args.lfw_dir), pairs, args.lfw_file_ext) with tf.Graph().as_default(): tf.set_random_seed(args.seed) global_step = tf.Variable(0, trainable=False) # Create a queue that produces indices into the image_list and label_list labels = ops.convert_to_tensor(label_list, dtype=tf.int32) range_size = array_ops.shape(labels)[0] index_queue = tf.train.range_input_producer(range_size, num_epochs=None, shuffle=True, seed=None, capacity=32) index_dequeue_op = index_queue.dequeue_many( args.batch_size * args.epoch_size, 'index_dequeue') learning_rate_placeholder = tf.placeholder(tf.float32, name='learning_rate') batch_size_placeholder = tf.placeholder(tf.int32, name='batch_size') phase_train_placeholder = tf.placeholder(tf.bool, name='phase_train') image_paths_placeholder = tf.placeholder(tf.string, shape=(None, 1), name='image_paths') labels_placeholder = tf.placeholder(tf.int64, shape=(None, 1), name='labels') input_queue = data_flow_ops.FIFOQueue(capacity=100000, dtypes=[tf.string, tf.int64], shapes=[(1, ), (1, )], shared_name=None, name=None) enqueue_op = input_queue.enqueue_many( [image_paths_placeholder, labels_placeholder], name='enqueue_op') nrof_preprocess_threads = 4 images_and_labels = [] for _ in range(nrof_preprocess_threads): filenames, label = input_queue.dequeue() images = [] for filename in tf.unpack(filenames): file_contents = tf.read_file(filename) image = tf.image.decode_png(file_contents) if args.random_rotate: image = tf.py_func(facenet.random_rotate_image, [image], tf.uint8) if args.random_crop: image = tf.random_crop( image, [args.image_size, args.image_size, 3]) else: image = tf.image.resize_image_with_crop_or_pad( image, args.image_size, args.image_size) if args.random_flip: image = tf.image.random_flip_left_right(image) #pylint: disable=no-member image.set_shape((args.image_size, args.image_size, 3)) images.append(tf.image.per_image_standardization(image)) images_and_labels.append([images, label]) image_batch, label_batch = tf.train.batch_join( images_and_labels, batch_size=batch_size_placeholder, shapes=[(args.image_size, args.image_size, 3), ()], enqueue_many=True, capacity=4 * nrof_preprocess_threads * args.batch_size, allow_smaller_final_batch=True) #image_batch = tf.identity(image_batch, 'image_batch') image_batch = tf.identity(image_batch, 'input') label_batch = tf.identity(label_batch, 'label_batch') print('Building training graph') # Build the inference graph prelogits, _ = network.inference(image_batch, args.keep_probability, phase_train=phase_train_placeholder, weight_decay=args.weight_decay) logits = slim.fully_connected( prelogits, len(train_set), activation_fn=None, weights_initializer=tf.truncated_normal_initializer(stddev=0.1), weights_regularizer=slim.l2_regularizer(args.weight_decay), scope='Logits', reuse=False) embeddings = tf.nn.l2_normalize(prelogits, 1, 1e-10, name='embeddings') # Add center loss if args.center_loss_factor > 0.0: prelogits_center_loss, centers, _, centers_cts_batch_reshape = facenet.center_loss( prelogits, label_batch, args.center_loss_alfa, nrof_classes) #prelogits_center_loss, _ = facenet.center_loss_similarity(prelogits, label_batch, args.center_loss_alfa, nrof_classes) ####Similarity cosine distance, center loss tf.add_to_collection( tf.GraphKeys.REGULARIZATION_LOSSES, prelogits_center_loss * args.center_loss_factor) learning_rate = tf.train.exponential_decay( learning_rate_placeholder, global_step, args.learning_rate_decay_epochs * args.epoch_size, args.learning_rate_decay_factor, staircase=True) tf.summary.scalar('learning_rate', learning_rate) # Calculate the average cross entropy loss across the batch cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits( logits, label_batch, name='cross_entropy_per_example') cross_entropy_mean = tf.reduce_mean(cross_entropy, name='cross_entropy') tf.add_to_collection('losses', cross_entropy_mean) # Calculate the total losses regularization_losses = tf.get_collection( tf.GraphKeys.REGULARIZATION_LOSSES) total_loss = tf.add_n([cross_entropy_mean] + regularization_losses, name='total_loss') #### Training accuracy of softmax: check the underfitting or overfiting ############################# correct_prediction = tf.equal(tf.argmax(logits, 1), label_batch) train_acc = tf.reduce_mean(tf.cast(correct_prediction, tf.float32)) ######################################################################################################## ########## edit mzh ##################### # Create list with variables to restore restore_vars = [] update_gradient_vars = [] if args.pretrained_model: update_gradient_vars = tf.global_variables() for var in tf.global_variables(): if not ('Embeddings/' in var.op.name or 'Centralisation/' in var.op.name or 'centers' in var.op.name or 'centers_cts' in var.op.name): restore_vars.append(var) #else: #update_gradient_vars.append(var) else: restore_vars = tf.global_variables() update_gradient_vars = tf.global_variables() ########## edit mzh ##################### # Build a Graph that trains the model with one batch of examples and updates the model parameters train_op = facenet.train(total_loss, global_step, args.optimizer, learning_rate, args.moving_average_decay, tf.global_variables(), args.log_histograms) # Create a saver restore_saver = tf.train.Saver(restore_vars) ## mzh #saver = tf.train.Saver(tf.trainable_variables(), max_to_keep=3) saver = tf.train.Saver(tf.global_variables(), max_to_keep=3) # Build the summary operation based on the TF collection of Summaries. summary_op = tf.summary.merge_all() # Start running operations on the Graph. gpu_options = tf.GPUOptions( per_process_gpu_memory_fraction=args.gpu_memory_fraction) sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options, log_device_placement=False)) sess.run(tf.global_variables_initializer()) sess.run(tf.local_variables_initializer()) summary_writer = tf.summary.FileWriter(log_dir, sess.graph) tf.train.start_queue_runners(sess=sess) with sess.as_default(): if pretrained_model: print('Restoring pretrained model: %s' % pretrained_model) #saver.restore(sess, pretrained_model) restore_saver.restore( sess, os.path.join(os.path.expanduser(args.pretrained_model), ckpt_file)) # Training and validation loop print('Running training') epoch = 0 acc = 0 val = 0 far = 0 best_acc = 0 while epoch < args.max_nrof_epochs: step = sess.run(global_step, feed_dict=None) epoch = step // args.epoch_size # Train for one epoch train(args, sess, epoch, image_list, label_list, index_dequeue_op, enqueue_op, image_paths_placeholder, labels_placeholder, learning_rate_placeholder, phase_train_placeholder, batch_size_placeholder, global_step, total_loss, train_op, summary_op, summary_writer, regularization_losses, args.learning_rate_schedule_file, prelogits_center_loss, cross_entropy_mean, acc, val, far, centers_cts_batch_reshape, train_acc) # Save variables and the metagraph if it doesn't exist already save_variables_and_metagraph(sess, saver, summary_writer, model_dir, subdir, step) # Evaluate on LFW if args.lfw_dir: acc, val, far = evaluate( sess, enqueue_op, image_paths_placeholder, labels_placeholder, phase_train_placeholder, batch_size_placeholder, embeddings, label_batch, lfw_paths, actual_issame, args.lfw_batch_size, args.lfw_nrof_folds, log_dir, step, summary_writer, args.evaluate_mode) ## saving the best_model if acc > best_acc: best_acc = acc best_model_dir = os.path.join(model_dir, 'best_model') if not os.path.isdir( best_model_dir ): # Create the log directory if it doesn't exist os.makedirs(best_model_dir) if os.listdir(best_model_dir): for file in glob.glob( os.path.join(best_model_dir, '*.*')): os.remove(file) for file in glob.glob(os.path.join(model_dir, '*.*')): shutil.copy(file, best_model_dir) return model_dir
def _build_graph(self, inputs): # with tf.device('/gpu:0'): image, label = inputs image = tf.identity(image, name="NETWORK_INPUT") tf.summary.image('input-image', image, max_outputs=5) image = tf.map_fn(lambda img: tf.image.per_image_standardization(img), image) image = tf.transpose(image, [0, 3, 1, 2]) def shortcut(l, n_in, n_out, stride): if n_in != n_out: return Conv2D('convshortcut', l, n_out, 1, stride=stride) else: return l def basicblock(l, ch_out, stride, preact): ch_in = l.get_shape().as_list()[1] if preact == 'both_preact': l = BNReLU('preact', l) input = l elif preact != 'no_preact': input = l l = BNReLU('preact', l) else: input = l l = Conv2D('conv1', l, ch_out, 3, stride=stride, nl=BNReLU) l = Conv2D('conv2', l, ch_out, 3) return l + shortcut(input, ch_in, ch_out, stride) def bottleneck(l, ch_out, stride, preact): ch_in = l.get_shape().as_list()[1] if preact == 'both_preact': l = BNReLU('preact', l) input = l elif preact != 'no_preact': input = l l = BNReLU('preact', l) else: input = l l = Conv2D('conv1', l, ch_out, 1, nl=BNReLU) l = Conv2D('conv2', l, ch_out, 3, stride=stride, nl=BNReLU) l = Conv2D('conv3', l, ch_out * 4, 1) return l + shortcut(input, ch_in, ch_out * 4, stride) def layer(l, layername, block_func, features, count, stride, first=False): with tf.variable_scope(layername): with tf.variable_scope('block0'): l = block_func(l, features, stride, 'no_preact' if first else 'both_preact') for i in range(1, count): with tf.variable_scope('block{}'.format(i)): l = block_func(l, features, 1, 'default') return l res_cfg = { 18: ([2, 2, 2, 2], basicblock), 34: ([3, 4, 6, 3], basicblock), 50: ([3, 4, 6, 3], bottleneck), 101: ([3, 4, 23, 3], bottleneck) } defs, block_func = res_cfg[self.depth] with argscope(Conv2D, nl=tf.identity, use_bias=False, W_init=variance_scaling_initializer(mode='FAN_OUT')), \ argscope([Conv2D, MaxPooling, GlobalAvgPooling, BatchNorm], data_format='NCHW'): logits = ( LinearWrap(image).Conv2D('conv0', 64, 7, stride=2, nl=BNReLU).MaxPooling( 'pool0', shape=3, stride=2, padding='SAME').apply(layer, 'group0', block_func, 64, defs[0], 1, first=True). apply(layer, 'group1', block_func, 128, defs[1], 2).apply(layer, 'group2', block_func, 256, defs[2], 2).apply( layer, 'group3', block_func, 512, defs[3], 2).BNReLU('bnlast').GlobalAvgPooling('gap') # .FullyConnected("fc1", out_dim=1024 ) .FullyConnected("fc2", out_dim=1024, nl=tf.identity)()) s_net = (LinearWrap(logits).FullyConnected( "fc3", out_dim=cfg.nrof_classes, W_init=tf.truncated_normal_initializer(stddev=0.1), nl=tf.identity)()) # logits = tf.sigmoid(logits) - 0.5 embeddings = tf.nn.l2_normalize(logits, 1, 1e-10, name='embeddings') feature = tf.identity(embeddings, name='FEATURE') # softmax-loss # result_label = tf.reshape(s_net, (-1,cfg.num_class)) softmax_loss = tf.nn.sparse_softmax_cross_entropy_with_logits( logits=s_net, labels=label, name="softmax_loss") softmax_loss = tf.reduce_mean(softmax_loss, name="softmax_loss") # center-loss if cfg.center_loss_factor > 0.0: prelogits_center_loss, _ = facenet.center_loss( logits, label, cfg.center_loss_alfa, cfg.nrof_classes) tf.add_to_collection( tf.GraphKeys.REGULARIZATION_LOSSES, prelogits_center_loss * cfg.center_loss_factor) center_loss = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES) # total loss loss = tf.add_n([softmax_loss] + center_loss, name="loss") if cfg.weight_decay > 0: wd_cost = regularize_cost('.*/W', l2_regularizer(cfg.weight_decay), name='l2_regularize_loss') add_moving_summary(loss, wd_cost) add_moving_summary(softmax_loss) self.cost = tf.add_n([loss, wd_cost], name='cost') else: add_moving_summary(softmax_loss) self.cost = tf.identity(loss, name='cost')
def model_fn(features, labels, mode, params): # Create the input layers from the features feature_columns = list(get_feature_columns().values()) images = tf.feature_column.input_layer( features=features, feature_columns=feature_columns) images = tf.reshape( images, shape=(-1, IMAGE_HEIGHT, IMAGE_WIDTH, IMAGE_DEPTH)) # Calculate logits through CNN network = importlib.import_module(args.model_def) learning_rate_placeholder = tf.placeholder(tf.float32, name='learning_rate') batch_size_placeholder = tf.placeholder(tf.int32, name='batch_size') phase_train_placeholder = tf.placeholder(tf.bool, name='phase_train') image_paths_placeholder = tf.placeholder(tf.string, shape=(None,1), name='image_paths') labels_placeholder = tf.placeholder(tf.int32, shape=(None,1), name='labels') control_placeholder = tf.placeholder(tf.int32, shape=(None,1), name='control') # Build the inference graph prelogits, _ = network.inference(image_batch, args.keep_probability, phase_train=phase_train_placeholder, bottleneck_layer_size=args.embedding_size, weight_decay=args.weight_decay) logits = slim.fully_connected(prelogits, len(train_set), activation_fn=None, weights_initializer=slim.initializers.xavier_initializer(), weights_regularizer=slim.l2_regularizer(args.weight_decay), scope='Logits', reuse=False) embeddings = tf.nn.l2_normalize(prelogits, 1, 1e-10, name='embeddings') # Build a Graph that trains the model with one batch of examples and updates the model parameters train_op = facenet.train(total_loss, global_step, args.optimizer, learning_rate, args.moving_average_decay, tf.global_variables(), args.log_histograms) # Create a saver saver = tf.train.Saver(tf.trainable_variables(), max_to_keep=3) # Build the summary operation based on the TF collection of Summaries. summary_op = tf.summary.merge_all() if mode in (tf.estimator.ModeKeys.PREDICT, tf.estimator.ModeKeys.EVAL): predicted_indices = tf.argmax(input=logits, axis=1) probabilities = tf.nn.softmax(logits, name='softmax_tensor') if mode in (tf.estimator.ModeKeys.TRAIN, tf.estimator.ModeKeys.EVAL): global_step = tf.train.get_or_create_global_step() tf.logging.info("Global Step {}".format(global_step)) # Norm for the prelogits eps = 1e-4 prelogits_norm = tf.reduce_mean(tf.norm(tf.abs(prelogits)+eps, ord=args.prelogits_norm_p, axis=1)) tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES, prelogits_norm * args.prelogits_norm_loss_factor) # Add center loss prelogits_center_loss, _ = facenet.center_loss(prelogits, label_batch, args.center_loss_alfa, nrof_classes) tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES, prelogits_center_loss * args.center_loss_factor) learning_rate = tf.train.exponential_decay(params['learning_rate'], global_step, args.learning_rate_decay_epochs*args.epoch_size, args.learning_rate_decay_factor, staircase=True) tf.summary.scalar('learning_rate', learning_rate) # Calculate the average cross entropy loss across the batch cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits( labels=label_batch, logits=logits, name='cross_entropy_per_example') cross_entropy_mean = tf.reduce_mean(cross_entropy, name='cross_entropy') tf.add_to_collection('losses', cross_entropy_mean) correct_prediction = tf.cast(tf.equal(tf.argmax(logits, 1), tf.cast(label_batch, tf.int64)), tf.float32) accuracy = tf.reduce_mean(correct_prediction) # Calculate the total losses regularization_losses = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES) total_loss = tf.add_n([cross_entropy_mean] + regularization_losses, name='total_loss') label_indices = tf.argmax(input=labels, axis=1) loss = tf.losses.softmax_cross_entropy( onehot_labels=labels, logits=logits) tf.summary.scalar('cross_entropy', loss) if mode == tf.estimator.ModeKeys.PREDICT: predictions = { 'classes': predicted_indices, 'probabilities': probabilities } export_outputs = { 'predictions': tf.estimator.export.PredictOutput(predictions) } return tf.estimator.EstimatorSpec( mode, predictions=predictions, export_outputs=export_outputs) if mode == tf.estimator.ModeKeys.TRAIN: # Build a Graph that trains the model with one batch of examples and updates the model parameters train_op = facenet.train(total_loss, global_step, args.optimizer, learning_rate, args.moving_average_decay, tf.global_variables(), args.log_histograms) # Create a saver saver = tf.train.Saver(tf.trainable_variables(), max_to_keep=3) # Build the summary operation based on the TF collection of Summaries. summary_op = tf.summary.merge_all() subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S') log_dir=params['log_dir'] stat_file_name=params['stat_file_name'] summary.value.add(tag='time/total', simple_value=train_time) summary_hook = tf.train.SummarySaverHook( SAVE_EVERY_N_STEPS, output_dir=log_dir, summary_op=tf.summary.merge_all()) return tf.estimator.EstimatorSpec(mode, loss=loss, train_op=train, training_hooks=[summary_hook]) if mode == tf.estimator.ModeKeys.EVAL: eval_metric_ops = { 'accuracy': tf.metrics.accuracy(label_indices, predicted_indices) } return tf.estimator.EstimatorSpec( mode, loss=loss, eval_metric_ops=eval_metric_ops)
def main(args): network = importlib.import_module(args.model_def) image_size = (args.image_size, args.image_size) subdir = datetime.strftime(datatime.now(), '%Y%m%d-%H%M%S') log_dir = os.path.join(os.path.expanduser(args.logs_base_dir), subdir) if not os.path.isdir(log_dir): os.makedirs(log_dir) model_dir = os.path.join(os.path.expanduser(args.models_base_dir), subdir) if not os.path.isdir(model_dir): os.makedirs(model_dir) stat_file_name = os.path.join(log_dir, 'stat.h5') facenet.write_arguments_to_file(args, os.path.join(log_dir, 'arguments.txt')) src_path,_ = os.path.split(os.path.realpath(__file__)) facenet.store_revision_info(src_path, log_dir, ' '.join(sys.argv)) np.random.seed(seed=args.seed) random.seed(args.seed) dataset = facenet.get_dataset(args.data_dir) if args.validation_set_split_ratio > 0.0: train_set, val_set = facenet.split_dataset(dataset, args.validation_set_split_ratio, args.min_nrof_val_images_per_class, 'SPLIT_IMAGES') else: train_set, val_set = dataset, [] num_classes = len(train_set) print('Model directory: %s' % model_dir) print('Log directory: %s' % log_dir) pretrained_model = None if args.pretrained_model: pretrained_model = os.path.expanduser(args.pretrained_model) print('Pre-trained model: %s' % pretrained_model) if args.lfw_dir: print('LFW directory: %s' % args.lfw_dir) pairs = lfw.read_pairs(os.path.expanduser(args.lfw_pairs)) lfw_paths, actual_issame = lfw.get_paths(os.path.expanduser(args.lfw_dir), pairs) with tf.Graph().as_default(): tf.set_random_state(args.seed) global_step = tf.Variable(0, trainable=False) image_list, label_list = facenet.get_image_paths_and_labels(train_set) assert len(image_list) > 0, 'The training set should not be empty' val_image_list, val_label_list = facenet.get_image_paths_and_labels(val_set) labels = ops.convert_to_tensor(label_list, dtype=tf.int32) range_size = array_ops.shape(labels)[0] index_q = tf.train.range_input_producer(range_size, num_epochs=None, shuffle=True, seed=None, capacity=32) index_deq_op = index_q.dequeue_many(args.batch_size * args.epoch_size, 'index_dequeue') learning_rate_placeholder = tf.placeholder(tf.float32, name='learning_rate') batch_size_placeholder = tf.placeholder(tf.int32, name='batch_size') phase_train_placeholder = tf.placeholder(tf.bool, name='phase_train') image_paths_placeholder = tf.placeholder(tf.string, shape=(None, 1), name='image_paths') labels_placeholder = tf.placeholder(tf.int32, shape=(None, 1), name='labels') control_placeholder = tf.placeholder(tf.int32, shape=(None, 1), name='control') num_preprocess_threads = 4 input_q = data_flow_ops.FIFOQueue(capacity=2000000, shared_name=None, name=None, dtype=[tf.string, tf.int32, tf.int32], shapes=[(1, ), (1, ), (1, )]) enq_op = input_q.enqueue_many([image_paths_placeholder, labels_placeholder, control_placeholder], name='enq_op') image_batch, label_batch = facenet.create_input_pipeline(input_q, image_size, num_preprocess_threads, batch_size_placeholder) image_batch = tf.identity(image_batch, 'image_batch') image_batch = tf.identity(image_batch, 'input') label_batch = tf.identity(label_batch, 'label_batch') print('Number of classes in training set: %d' % nrof_classes) print('Number of examples in training set: %d' % len(image_list)) print('Number of classes in validation set: %d' % len(val_set)) print('Number of examples in validation set: %d' % len(val_image_list)) print('Building training graph') prelogits, _ = network.inference(image_batch, args.keep_probability, phase_train=phase_train_placeholder, bottleneck_layer_size=args.embedding_size, weight_decay=args.weight_decay) logits = slim.fully_connected(prelogits, num_classes, activation_fn=None, reuse=False, scope='Logits', weights_initializer=slim.initializers.xavier_initializer(), weights_regularizer=slim.l2_regularizer(args.weight_decay)) embeddings = tf.nn.l2_normalize(prelogits, 1, 1e-10, name='embeddings') eps = 1e-4 prelogits_norm = tf.reduce_mean(tf.norm(tf.abs(prelogits) + eps, ord=args.prelogits_norm_p, axis=1)) tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES, prelogits_norm * args.prelogits_norm_loss_factor) prelogits_center_loss, _ = facenet.center_loss(prelogits, label_batch, args.center_loss_alfa, num_classes) tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES, prelogits_center_loss * args.center_loss_factor) cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(labels=label_batch, logits=logits, name='cross_entropy_per_example') cross_entropy_mean = tf.reduce_mean(cross_entropy, name='cross_entropy') tf.add_to_collection('losses', cross_entropy_mean) regularization_loss = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES) total_loss = tf.add_n([cross_entropy_mean] + regularization_loss, name='total_loss') correct_prediction = tf.cast(tf.equal(tf.argmax(logits, 1), tf.cast(label_batch, tf.int64)), tf.float32) accuracy = tf.reduce_mean(correct_prediction) learning_rate = tf.train.exponential_decay(learning_rate_placeholder, global_step, args.learning_rate_decay_epochs * args.epoch_size, args.learning_rate_decay_factor, staircase=True,) tf.summary.scalar('learning_rate', learning_rate) train_op = facenet.train(total_loss, global_step, args.optimizer, learning_rate, args.moving_average_decay, tf.global_variables(), args.log_histograms) saver = tf.train.Saver(tf.trainable_variables(), max_to_keep=3) summary_op = tf.summary.merge_all() gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=args.gpu_memory_fraction) sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options, log_device_placement=False)) sess.run(tf.global_variables_initializer()) sess.run(tf.local_variables_initializer()) summary_writer = tf.summary.FileWriter(log_dir, sess.graph) coord = tf.train.Coordinator() tf.train.start_queue_runners(coord=coord, sess=sess) with sess.as_default(): if pretrained_model: print('Restoring pretrained model: %s' % pretrained_model) saver.restore(sess, pretrained_model) print('Running training') num_steps = args.max_nrof_epochs * args.epoch_size num_val_samples = int(math.ceil(args.max_nrof_epochs / args.validate_every_n_epochs)) stat = { 'loss': np.zeros((num_steps,), np.float32), 'center_loss': np.zeros((num_steps,), np.float32), 'reg_loss': np.zeros((num_steps,), np.float32), 'xent_loss': np.zeros((num_steps,), np.float32), 'prelogits_norm': np.zeros((num_steps,), np.float32), 'accuracy': np.zeros((num_steps,), np.float32), 'val_loss': np.zeros((num_val_samples,), np.float32), 'val_xent_loss': np.zeros((num_val_samples,), np.float32), 'val_accuracy': np.zeros((num_val_samples,), np.float32), 'lfw_accuracy': np.zeros((args.max_nrof_epochs,), np.float32), 'lfw_valrate': np.zeros((args.max_nrof_epochs,), np.float32), 'learning_rate': np.zeros((args.max_nrof_epochs,), np.float32), 'time_train': np.zeros((args.max_nrof_epochs,), np.float32), 'time_validate': np.zeros((args.max_nrof_epochs,), np.float32), 'time_evaluate': np.zeros((args.max_nrof_epochs,), np.float32), 'prelogits_hist': np.zeros((args.max_nrof_epochs, 1000), np.float32), } for epoch in range(1, args.max_nrof_epochs + 1): step = sess.run(global_step, feed_dict=None) t = time.time() cont = train(args, sess, epoch, image_list, label_list, index_dequeue_op, enqueue_op, image_paths_placeholder, labels_placeholder, learning_rate_placeholder, phase_train_placeholder, batch_size_placeholder, control_placeholder, global_step, total_loss, train_op, summary_op, summary_writer, regularization_losses, args.learning_rate_schedule_file, stat, cross_entropy_mean, accuracy, learning_rate, prelogits, prelogits_center_loss, args.random_rotate, args.random_crop, args.random_flip, prelogits_norm, args.prelogits_hist_max, args.use_fixed_image_standardization) stat['time_train'][epoch - 1] = time.time() - t if not cont: break t = time.time() if len(val_image_list)>0 and ((epoch-1) % args.validate_every_n_epochs == args.validate_every_n_epochs-1 or epoch==args.max_nrof_epochs): validate(args, sess, epoch, val_image_list, val_label_list, enqueue_op, image_paths_placeholder, labels_placeholder, control_placeholder, phase_train_placeholder, batch_size_placeholder, stat, total_loss, regularization_losses, cross_entropy_mean, accuracy, args.validate_every_n_epochs, args.use_fixed_image_standardization) stat['time_validate'][epoch - 1] = time.time() - t save_variables_and_metagraph(sess, saver, summary_writer, model_dir, subdir, epoch) t = time.time() if args.lfw_dir: evaluate(sess, enqueue_op, image_paths_placeholder, labels_placeholder, phase_train_placeholder, batch_size_placeholder, control_placeholder, embeddings, label_batch, lfw_paths, actual_issame, args.lfw_batch_size, args.lfw_nrof_folds, log_dir, step, summary_writer, stat, epoch, args.lfw_distance_metric, args.lfw_subtract_mean, args.lfw_use_flipped_images, args.use_fixed_image_standardization) stat['time_evaluate'][epoch - 1] = time.time() - t print('Saving statistics') with h5py.File(stat_file_name, 'w') as f: for key, value in stat.items(): f.create_dataset(key, data=value) return model_dir
def main(args): # 模型,定义在inception_resnet_v1 V2里(), --model_def models.inception_resnet_v1 network = importlib.import_module(args.model_def) image_size = (args.image_size, args.image_size) subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S') log_dir = os.path.join(os.path.expanduser(args.logs_base_dir), subdir) if not os.path.isdir(log_dir): # Create the log directory if it doesn't exist os.makedirs(log_dir) model_dir = os.path.join(os.path.expanduser(args.models_base_dir), subdir) if not os.path.isdir(model_dir): # Create the model directory if it doesn't exist os.makedirs(model_dir) stat_file_name = os.path.join(log_dir, 'stat.h5') # Write arguments to a text file facenet.write_arguments_to_file(args, os.path.join(log_dir, 'arguments.txt')) # Store some git revision info in a text file in the log directory src_path,_ = os.path.split(os.path.realpath(__file__)) facenet.store_revision_info(src_path, log_dir, ' '.join(sys.argv)) np.random.seed(seed=args.seed) random.seed(args.seed) dataset = facenet.get_dataset(args.data_dir) if args.filter_filename: dataset = filter_dataset(dataset, os.path.expanduser(args.filter_filename), args.filter_percentile, args.filter_min_nrof_images_per_class) if args.validation_set_split_ratio>0.0: train_set, val_set = facenet.split_dataset(dataset, args.validation_set_split_ratio, args.min_nrof_val_images_per_class, 'SPLIT_IMAGES') else: train_set, val_set = dataset, [] nrof_classes = len(train_set) print('Model directory: %s' % model_dir) print('Log directory: %s' % log_dir) pretrained_model = None if args.pretrained_model: pretrained_model = os.path.expanduser(args.pretrained_model) print('Pre-trained model: %s' % pretrained_model) if args.lfw_dir: print('LFW directory: %s' % args.lfw_dir) # Read the file containing the pairs used for testing pairs = lfw.read_pairs(os.path.expanduser(args.lfw_pairs)) # Get the paths for the corresponding images lfw_paths, actual_issame = lfw.get_paths(os.path.expanduser(args.lfw_dir), pairs) with tf.Graph().as_default(): tf.set_random_seed(args.seed) global_step = tf.Variable(0, trainable=False) # Get a list of image paths and their labels # 训练数据 image_list, label_list = facenet.get_image_paths_and_labels(train_set) assert len(image_list)>0, 'The training set should not be empty' # 测试数据 val_image_list, val_label_list = facenet.get_image_paths_and_labels(val_set) # Create a queue that produces indices into the image_list and label_list # tf.convert_to_tensor用于将不同数据变成张量:比如可以让数组变成张量、也可以让列表变成张量。 labels = ops.convert_to_tensor(label_list, dtype=tf.int32) range_size = array_ops.shape(labels)[0] # 多线程读取数据,shuffle=True表示不是按顺序存储,可以随机获取,并一直循环。 # https://blog.csdn.net/lyg5623/article/details/69387917 index_queue = tf.train.range_input_producer(range_size, num_epochs=None, shuffle=True, seed=None, capacity=32) # epoch 大数据时迭代完一轮时次数,少量数据应该epoch = 全部数据个数/batch index_dequeue_op = index_queue.dequeue_many(args.batch_size*args.epoch_size, 'index_dequeue') learning_rate_placeholder = tf.placeholder(tf.float32, name='learning_rate') batch_size_placeholder = tf.placeholder(tf.int32, name='batch_size') phase_train_placeholder = tf.placeholder(tf.bool, name='phase_train') image_paths_placeholder = tf.placeholder(tf.string, shape=(None,1), name='image_paths') labels_placeholder = tf.placeholder(tf.int32, shape=(None,1), name='labels') control_placeholder = tf.placeholder(tf.int32, shape=(None,1), name='control') nrof_preprocess_threads = 4 input_queue = data_flow_ops.FIFOQueue(capacity=2000000, dtypes=[tf.string, tf.int32, tf.int32], shapes=[(1,), (1,), (1,)], shared_name=None, name=None) enqueue_op = input_queue.enqueue_many([image_paths_placeholder, labels_placeholder, control_placeholder], name='enqueue_op') image_batch, label_batch = facenet.create_input_pipeline(input_queue, image_size, nrof_preprocess_threads, batch_size_placeholder) image_batch = tf.identity(image_batch, 'image_batch') image_batch = tf.identity(image_batch, 'input') label_batch = tf.identity(label_batch, 'label_batch') print('Number of classes in training set: %d' % nrof_classes) print('Number of examples in training set: %d' % len(image_list)) print('Number of classes in validation set: %d' % len(val_set)) print('Number of examples in validation set: %d' % len(val_image_list)) print('Building training graph') # Build the inference graph prelogits, _ = network.inference(image_batch, args.keep_probability, phase_train=phase_train_placeholder, bottleneck_layer_size=args.embedding_size, weight_decay=args.weight_decay) # 因为模型输出的(bottleneck_layer_size)没有计算最后一层(映射到图片类型),这里计算最后一层 logits = slim.fully_connected(prelogits, len(train_set), activation_fn=None, weights_initializer=slim.initializers.xavier_initializer(), weights_regularizer=slim.l2_regularizer(args.weight_decay), scope='Logits', reuse=False) # 按行进行泛化,行的平方求和再求平方根,得到的值按行除每个行的元素,对深度层面泛化? interface里最后一层输出为128个节点,slim.fully_connected(net, bottleneck_layer_size, activation_fn=None, #https://blog.csdn.net/abiggg/article/details/79368982 embeddings = tf.nn.l2_normalize(prelogits, 1, 1e-10, name='embeddings') # 计算loss函数,当然还有其它训练参数也会加到这里来,通过比训练过程中一个weight加到正则化参数里来tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES, weight) # 模型中最后会把这个加到优化的loss中来。 #L= L_softmax + λL_cneter = Softmax(W_i + b_yj) + λ1/2||f(x_i) - c_yj ||_2^2 # Norm for the prelogits eps = 1e-4 prelogits_norm = tf.reduce_mean(tf.norm(tf.abs(prelogits)+eps, ord=args.prelogits_norm_p, axis=1)) # 模型中最后输出(bottleneck_layer_size每个类型的输出值的个数)的平均值加到正则化loss中,但prelogits_norm_loss_factor貌似为0 tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES, prelogits_norm * args.prelogits_norm_loss_factor) # 计算中心损失及增加的正则化loss中 # Add center loss prelogits_center_loss, _ = facenet.center_loss(prelogits, label_batch, args.center_loss_alfa, nrof_classes) tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES, prelogits_center_loss * args.center_loss_factor) learning_rate = tf.train.exponential_decay(learning_rate_placeholder, global_step, args.learning_rate_decay_epochs*args.epoch_size, args.learning_rate_decay_factor, staircase=True) tf.summary.scalar('learning_rate', learning_rate) # Calculate the average cross entropy loss across the batch # 计算预测损失,和上面框架的Softmax(W_i + b_yj) cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits( labels=label_batch, logits=logits, name='cross_entropy_per_example') cross_entropy_mean = tf.reduce_mean(cross_entropy, name='cross_entropy') # 预测损失平均值加到losses变量中 tf.add_to_collection('losses', cross_entropy_mean) correct_prediction = tf.cast(tf.equal(tf.argmax(logits, 1), tf.cast(label_batch, tf.int64)), tf.float32) accuracy = tf.reduce_mean(correct_prediction) #计算总损失,cross_entropy_mean + 前面增加的一些正则化损失(包括模型中增加的),通过tf.GraphKeys.REGULARIZATION_LOSSES获取出来 # Calculate the total losses regularization_losses = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES) total_loss = tf.add_n([cross_entropy_mean] + regularization_losses, name='total_loss') # Build a Graph that trains the model with one batch of examples and updates the model parameters train_op = facenet.train(total_loss, global_step, args.optimizer, learning_rate, args.moving_average_decay, tf.global_variables(), args.log_histograms) # Create a saver saver = tf.train.Saver(tf.trainable_variables(), max_to_keep=3) # Build the summary operation based on the TF collection of Summaries. summary_op = tf.summary.merge_all() # Start running operations on the Graph. gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=args.gpu_memory_fraction) sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options, log_device_placement=False)) sess.run(tf.global_variables_initializer()) sess.run(tf.local_variables_initializer()) summary_writer = tf.summary.FileWriter(log_dir, sess.graph) coord = tf.train.Coordinator() tf.train.start_queue_runners(coord=coord, sess=sess) with sess.as_default(): if pretrained_model: print('Restoring pretrained model: %s' % pretrained_model) saver.restore(sess, pretrained_model) # Training and validation loop print('Running training') nrof_steps = args.max_nrof_epochs*args.epoch_size nrof_val_samples = int(math.ceil(args.max_nrof_epochs / args.validate_every_n_epochs)) # Validate every validate_every_n_epochs as well as in the last epoch stat = { 'loss': np.zeros((nrof_steps,), np.float32), 'center_loss': np.zeros((nrof_steps,), np.float32), 'reg_loss': np.zeros((nrof_steps,), np.float32), 'xent_loss': np.zeros((nrof_steps,), np.float32), 'prelogits_norm': np.zeros((nrof_steps,), np.float32), 'accuracy': np.zeros((nrof_steps,), np.float32), 'val_loss': np.zeros((nrof_val_samples,), np.float32), 'val_xent_loss': np.zeros((nrof_val_samples,), np.float32), 'val_accuracy': np.zeros((nrof_val_samples,), np.float32), 'lfw_accuracy': np.zeros((args.max_nrof_epochs,), np.float32), 'lfw_valrate': np.zeros((args.max_nrof_epochs,), np.float32), 'learning_rate': np.zeros((args.max_nrof_epochs,), np.float32), 'time_train': np.zeros((args.max_nrof_epochs,), np.float32), 'time_validate': np.zeros((args.max_nrof_epochs,), np.float32), 'time_evaluate': np.zeros((args.max_nrof_epochs,), np.float32), 'prelogits_hist': np.zeros((args.max_nrof_epochs, 1000), np.float32), } for epoch in range(1,args.max_nrof_epochs+1): step = sess.run(global_step, feed_dict=None) # Train for one epoch t = time.time() # 训练模型 cont = train(args, sess, epoch, image_list, label_list, index_dequeue_op, enqueue_op, image_paths_placeholder, labels_placeholder, learning_rate_placeholder, phase_train_placeholder, batch_size_placeholder, control_placeholder, global_step, total_loss, train_op, summary_op, summary_writer, regularization_losses, args.learning_rate_schedule_file, stat, cross_entropy_mean, accuracy, learning_rate, prelogits, prelogits_center_loss, args.random_rotate, args.random_crop, args.random_flip, prelogits_norm, args.prelogits_hist_max, args.use_fixed_image_standardization) stat['time_train'][epoch-1] = time.time() - t if not cont: break # 在测试数据上计算正确率 t = time.time() if len(val_image_list)>0 and ((epoch-1) % args.validate_every_n_epochs == args.validate_every_n_epochs-1 or epoch==args.max_nrof_epochs): validate(args, sess, epoch, val_image_list, val_label_list, enqueue_op, image_paths_placeholder, labels_placeholder, control_placeholder, phase_train_placeholder, batch_size_placeholder, stat, total_loss, regularization_losses, cross_entropy_mean, accuracy, args.validate_every_n_epochs, args.use_fixed_image_standardization) stat['time_validate'][epoch-1] = time.time() - t # Save variables and the metagraph if it doesn't exist already save_variables_and_metagraph(sess, saver, summary_writer, model_dir, subdir, epoch) # Evaluate on LFW t = time.time() if args.lfw_dir: evaluate(sess, enqueue_op, image_paths_placeholder, labels_placeholder, phase_train_placeholder, batch_size_placeholder, control_placeholder, embeddings, label_batch, lfw_paths, actual_issame, args.lfw_batch_size, args.lfw_nrof_folds, log_dir, step, summary_writer, stat, epoch, args.lfw_distance_metric, args.lfw_subtract_mean, args.lfw_use_flipped_images, args.use_fixed_image_standardization) stat['time_evaluate'][epoch-1] = time.time() - t print('Saving statistics') with h5py.File(stat_file_name, 'w') as f: for key, value in stat.items(): f.create_dataset(key, data=value) return model_dir
def main(args): network = importlib.import_module(args.model_def, 'inference') subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S') log_dir = os.path.join(os.path.expanduser(args.logs_base_dir), subdir) if not os.path.isdir( log_dir): # Create the log directory if it doesn't exist os.makedirs(log_dir) model_dir = os.path.join(os.path.expanduser(args.models_base_dir), subdir) if not os.path.isdir( model_dir): # Create the model directory if it doesn't exist os.makedirs(model_dir) # Store some git revision info in a text file in the log directory src_path, _ = os.path.split(os.path.realpath(__file__)) facenet.store_revision_info(src_path, log_dir, ' '.join(sys.argv)) np.random.seed(seed=args.seed) train_set = facenet.get_dataset(args.data_dir) nrof_classes = len(train_set) ##mzh # test_list= train_set[0].image_paths + train_set[1].image_paths + train_set[2].image_paths # labels_triplet = facenet.get_label_triplet(test_list) print('Model directory: %s' % model_dir) print('Log directory: %s' % log_dir) if args.pretrained_model: print('Pre-trained model: %s' % os.path.expanduser(args.pretrained_model)) meta_file, ckpt_file = facenet.get_model_filenames( args.pretrained_model) if args.lfw_dir: print('LFW directory: %s' % args.lfw_dir) # Read the file containing the pairs used for testing pairs = lfw.read_pairs(os.path.expanduser(args.lfw_pairs)) # Get the paths for the corresponding images lfw_paths, actual_issame = lfw.get_paths( os.path.expanduser(args.lfw_dir), pairs, args.lfw_file_ext) with tf.Graph().as_default(): tf.set_random_seed(args.seed) global_step = tf.Variable(0, trainable=False) # Placeholder for the learning rate learning_rate_placeholder = tf.placeholder(tf.float32, name='learning_rate') batch_size_placeholder = tf.placeholder(tf.int32, name='batch_size') phase_train_placeholder = tf.placeholder(tf.bool, name='phase_train') image_paths_placeholder = tf.placeholder(tf.string, shape=(None, 3), name='image_paths') labels_placeholder = tf.placeholder(tf.int64, shape=(None, 3), name='labels') input_queue = data_flow_ops.FIFOQueue(capacity=100000, dtypes=[tf.string, tf.int64], shapes=[(3, ), (3, )], shared_name=None, name=None) enqueue_op = input_queue.enqueue_many( [image_paths_placeholder, labels_placeholder]) nrof_preprocess_threads = 4 images_and_labels = [] for _ in range(nrof_preprocess_threads): filenames, label = input_queue.dequeue() images = [] for filename in tf.unpack(filenames): file_contents = tf.read_file(filename) image = tf.image.decode_png(file_contents) if args.random_crop: image = tf.random_crop( image, [args.image_size, args.image_size, 3]) else: image = tf.image.resize_image_with_crop_or_pad( image, args.image_size, args.image_size) if args.random_flip: image = tf.image.random_flip_left_right(image) #pylint: disable=no-member image.set_shape((args.image_size, args.image_size, 3)) images.append(tf.image.per_image_standardization(image)) images_and_labels.append([images, label]) image_batch, labels_batch = tf.train.batch_join( images_and_labels, batch_size=batch_size_placeholder, shapes=[(args.image_size, args.image_size, 3), ()], enqueue_many=True, capacity=4 * nrof_preprocess_threads * args.batch_size, allow_smaller_final_batch=True) # Build the inference graph prelogits, _ = network.inference(image_batch, args.keep_probability, phase_train=phase_train_placeholder, weight_decay=args.weight_decay) ## Aftre the last layer of the networks, adding a full connection layer to reduce the dimension of the embdedding to the args.embedding_size (e.g 128) #pre_embeddings = slim.fully_connected(prelogits, args.embedding_size, activation_fn=None, scope='Embeddings', reuse=False) #embedding_size = 1792 logits = slim.fully_connected( prelogits, len(train_set), activation_fn=None, weights_initializer=tf.truncated_normal_initializer(stddev=0.1), weights_regularizer=slim.l2_regularizer(args.weight_decay), scope='Logits', reuse=False) ## Normalise the output of the full connection layer, then the output are embeddings #embeddings = tf.nn.l2_normalize(pre_embeddings, 1, 1e-10, name='embeddings') embeddings = tf.nn.l2_normalize( prelogits, 1, 1e-10, name='embeddings') #embeddin_size = 1792 # Split embeddings into anchor, positive and negative and calculate triplet loss #anchor, positive, negative = tf.unpack(tf.reshape(embeddings, [-1,3,args.embedding_size]), 3, 1) anchor, positive, negative = tf.unpack( tf.reshape(embeddings, [-1, 3, args.embedding_size]), 3, 1) triplet_loss = facenet.triplet_loss(anchor, positive, negative, args.alpha) # Add center loss if args.center_loss_factor > 0.0: #prelogits_center_loss, _ = facenet.center_loss(prelogits, labels_batch, args.center_loss_alfa, nrof_classes) #### The triplet loss is calculated based on embeddings , the center_loss should also calculate based on embadding. #### However in the facenet_train_classifier (softmax+centerloss) the loss is calculated the output of the network, i.e. prelogits. #### However, facenet_train_classifier's evaluation is based on the normalisatioin of the traind prelogits which are the embedding. prelogits_center_loss, center = facenet.center_loss( embeddings, labels_batch, args.center_loss_alfa, nrof_classes) tf.add_to_collection( tf.GraphKeys.REGULARIZATION_LOSSES, prelogits_center_loss * args.center_loss_factor) # Calculate the average cross entropy loss across the batch cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits( logits, labels_batch, name='cross_entropy_per_example') cross_entropy_mean = tf.reduce_mean(cross_entropy, name='cross_entropy') #tf.add_to_collection('losses', cross_entropy_mean) learning_rate = tf.train.exponential_decay( learning_rate_placeholder, global_step, args.learning_rate_decay_epochs * args.epoch_size, args.learning_rate_decay_factor, staircase=True) tf.summary.scalar('learning_rate', learning_rate) # Calculate the total losses regularization_losses = tf.get_collection( tf.GraphKeys.REGULARIZATION_LOSSES) total_loss = tf.add_n([cross_entropy_mean] + [args.triplet_loss_factor * triplet_loss] + regularization_losses, name='total_loss') # Create list with variables to restore restore_vars = [] update_gradient_vars = [] if args.pretrained_model: update_gradient_vars = tf.global_variables() for var in tf.global_variables(): if not 'Embeddings/' in var.op.name: restore_vars.append(var) #else: #update_gradient_vars.append(var) else: restore_vars = tf.global_variables() update_gradient_vars = tf.global_variables() # Build a Graph that trains the model with one batch of examples and updates the model parameters train_op = facenet.train(total_loss, global_step, args.optimizer, learning_rate, args.moving_average_decay, update_gradient_vars) # Create a saver restore_saver = tf.train.Saver(restore_vars) saver = tf.train.Saver(tf.global_variables(), max_to_keep=3) # Build the summary operation based on the TF collection of Summaries. summary_op = tf.summary.merge_all() # Start running operations on the Graph. gpu_options = tf.GPUOptions( per_process_gpu_memory_fraction=args.gpu_memory_fraction) sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options)) # Initialize variables sess.run(tf.global_variables_initializer(), feed_dict={phase_train_placeholder: True}) sess.run(tf.local_variables_initializer(), feed_dict={phase_train_placeholder: True}) summary_writer = tf.summary.FileWriter(log_dir, sess.graph) tf.train.start_queue_runners(sess=sess) with sess.as_default(): if args.pretrained_model: print('Restoring pretrained model: %s' % args.pretrained_model) #restore_saver.restore(sess, os.path.expanduser(args.pretrained_model)) ## edit by mzh restore_saver.restore( sess, os.path.join(os.path.expanduser(args.pretrained_model), ckpt_file)) # Training and validation loop epoch = 0 while epoch < args.max_nrof_epochs: step = sess.run(global_step, feed_dict=None) epoch = step // args.epoch_size # Train for one epoch train(args, sess, train_set, epoch, image_paths_placeholder, labels_placeholder, labels_batch, batch_size_placeholder, learning_rate_placeholder, phase_train_placeholder, enqueue_op, global_step, embeddings, total_loss, train_op, summary_writer, regularization_losses, args.learning_rate_schedule_file, args.embedding_size, nrof_classes, summary_op) # Save variables and the metagraph if it doesn't exist already save_variables_and_metagraph(sess, saver, summary_writer, model_dir, subdir, step) # Evaluate on LFW if args.lfw_dir: evaluate(sess, lfw_paths, embeddings, labels_batch, image_paths_placeholder, labels_placeholder, batch_size_placeholder, learning_rate_placeholder, phase_train_placeholder, enqueue_op, actual_issame, args.batch_size, args.lfw_nrof_folds, log_dir, step, summary_writer, args.embedding_size) return model_dir
def main(args): network = importlib.import_module(args.model_def, 'inference') subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S') log_dir = os.path.join(os.path.expanduser(args.logs_base_dir), subdir) if not os.path.isdir( log_dir): # Create the log directory if it doesn't exist os.makedirs(log_dir) model_dir = os.path.join(os.path.expanduser(args.models_base_dir), subdir) if not os.path.isdir( model_dir): # Create the model directory if it doesn't exist os.makedirs(model_dir) # Store some git revision info in a text file in the log directory src_path, _ = os.path.split(os.path.realpath(__file__)) facenet.store_revision_info(src_path, log_dir, ' '.join(sys.argv)) np.random.seed(seed=args.seed) train_set = facenet.get_dataset(args.data_dir) nrof_classes = len(train_set) print('Model directory: %s' % model_dir) print('Log directory: %s' % log_dir) pretrained_model = None if args.pretrained_model: pretrained_model = os.path.expanduser(args.pretrained_model) print('Pre-trained model: %s' % pretrained_model) if args.lfw_dir: print('LFW directory: %s' % args.lfw_dir) # Read the file containing the pairs used for testing pairs = lfw.read_pairs(os.path.expanduser(args.lfw_pairs)) # Get the paths for the corresponding images lfw_paths, actual_issame = lfw.get_paths( os.path.expanduser(args.lfw_dir), pairs, args.lfw_file_ext) with tf.Graph().as_default(): tf.set_random_seed(args.seed) global_step = tf.Variable(0, trainable=False) # Get a list of image paths and their labels image_list, label_list = facenet.get_image_paths_and_labels(train_set) # Read data and apply label preserving distortions image_batch, label_batch = facenet.read_and_augument_data( image_list, label_list, args.image_size, args.batch_size, args.max_nrof_epochs, args.random_crop, args.random_flip, args.nrof_preprocess_threads) print('Total number of classes: %d' % nrof_classes) print('Total number of examples: %d' % len(image_list)) print('Building training graph') # Placeholder for the learning rate learning_rate_placeholder = tf.placeholder(tf.float32, name='learning_rate') # Build the inference graph prelogits, _ = network.inference(image_batch, args.keep_probability, phase_train=True, weight_decay=args.weight_decay) logits = slim.fully_connected( prelogits, len(train_set), activation_fn=None, weights_initializer=tf.truncated_normal_initializer(stddev=0.1), weights_regularizer=slim.l2_regularizer(args.weight_decay), scope='Logits', reuse=False) # Add DeCov regularization loss if args.decov_loss_factor > 0.0: logits_decov_loss = facenet.decov_loss( logits) * args.decov_loss_factor tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES, logits_decov_loss) # Add center loss if args.center_loss_factor > 0.0: prelogits_center_loss, _ = facenet.center_loss( prelogits, label_batch, args.center_loss_alfa, nrof_classes) tf.add_to_collection( tf.GraphKeys.REGULARIZATION_LOSSES, prelogits_center_loss * args.center_loss_factor) learning_rate = tf.train.exponential_decay( learning_rate_placeholder, global_step, args.learning_rate_decay_epochs * args.epoch_size, args.learning_rate_decay_factor, staircase=True) tf.scalar_summary('learning_rate', learning_rate) # Calculate the average cross entropy loss across the batch cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits( logits, label_batch, name='cross_entropy_per_example') cross_entropy_mean = tf.reduce_mean(cross_entropy, name='cross_entropy') tf.add_to_collection('losses', cross_entropy_mean) # Calculate the total losses regularization_losses = tf.get_collection( tf.GraphKeys.REGULARIZATION_LOSSES) total_loss = tf.add_n([cross_entropy_mean] + regularization_losses, name='total_loss') # Build a Graph that trains the model with one batch of examples and updates the model parameters train_op = facenet.train(total_loss, global_step, args.optimizer, learning_rate, args.moving_average_decay, tf.all_variables(), args.log_histograms) # Evaluation print('Building evaluation graph') lfw_label_list = range(0, len(lfw_paths)) assert ( len(lfw_paths) % args.lfw_batch_size == 0 ), "The number of images in the LFW test set need to be divisible by the lfw_batch_size" eval_image_batch, eval_label_batch = facenet.read_and_augument_data( lfw_paths, lfw_label_list, args.image_size, args.lfw_batch_size, None, False, False, args.nrof_preprocess_threads, shuffle=False) # Node for input images eval_image_batch.set_shape((None, args.image_size, args.image_size, 3)) eval_image_batch = tf.identity(eval_image_batch, name='input') eval_prelogits, _ = network.inference(eval_image_batch, 1.0, phase_train=False, weight_decay=0.0, reuse=True) eval_embeddings = tf.nn.l2_normalize(eval_prelogits, 1, 1e-10, name='embeddings') # Create a saver saver = tf.train.Saver(tf.all_variables(), max_to_keep=3) # Build the summary operation based on the TF collection of Summaries. summary_op = tf.merge_all_summaries() # Start running operations on the Graph. gpu_options = tf.GPUOptions( per_process_gpu_memory_fraction=args.gpu_memory_fraction) sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options, log_device_placement=False)) sess.run(tf.initialize_all_variables()) sess.run(tf.initialize_local_variables()) summary_writer = tf.train.SummaryWriter(log_dir, sess.graph) tf.train.start_queue_runners(sess=sess) with sess.as_default(): if pretrained_model: print('Restoring pretrained model: %s' % pretrained_model) saver.restore(sess, pretrained_model) # Training and validation loop print('Running training') epoch = 0 while epoch < args.max_nrof_epochs: step = sess.run(global_step, feed_dict=None) epoch = step // args.epoch_size # Train for one epoch train(args, sess, epoch, learning_rate_placeholder, global_step, total_loss, train_op, summary_op, summary_writer, regularization_losses, args.learning_rate_schedule_file) # Save variables and the metagraph if it doesn't exist already save_variables_and_metagraph(sess, saver, summary_writer, model_dir, subdir, step) # Evaluate on LFW if args.lfw_dir: evaluate(sess, eval_embeddings, eval_label_batch, actual_issame, args.lfw_batch_size, args.seed, args.lfw_nrof_folds, log_dir, step, summary_writer) return model_dir
def main(args): network = importlib.import_module(args.model_def) image_size = (args.image_size, args.image_size) subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S') log_dir = os.path.join(os.path.expanduser(args.logs_base_dir), subdir) if not os.path.isdir( log_dir): # Create the log directory if it doesn't exist try: os.makedirs(log_dir) except OSError as exc: print(exc) model_dir = os.path.join(os.path.expanduser(args.models_base_dir), subdir) if not os.path.isdir( model_dir): # Create the model directory if it doesn't exist try: os.makedirs(model_dir) except OSError as exc: print(exc) stat_file_name = os.path.join(log_dir, 'stat.h5') # Write arguments to a text file facenet.write_arguments_to_file(args, os.path.join(log_dir, 'arguments.txt')) # Store some git revision info in a text file in the log directory src_path, _ = os.path.split(os.path.realpath(__file__)) facenet.store_revision_info(src_path, log_dir, ' '.join(sys.argv)) np.random.seed(seed=args.seed) random.seed(args.seed) dataset = facenet.get_dataset(args.data_dir) if args.filter_filename: dataset = filter_dataset(dataset, os.path.expanduser(args.filter_filename), args.filter_percentile, args.filter_min_nrof_images_per_class) if args.validation_set_split_ratio > 0.0: train_set, val_set = facenet.split_dataset( dataset, args.validation_set_split_ratio, args.min_nrof_val_images_per_class, 'SPLIT_IMAGES') else: train_set, val_set = dataset, [] nrof_classes = len(train_set) print('Model directory: %s' % model_dir) print('Log directory: %s' % log_dir) pretrained_model = None if args.pretrained_model: pretrained_model = os.path.expanduser(args.pretrained_model) print('Pre-trained model: %s' % pretrained_model) if args.lfw_dir: print('LFW directory: %s' % args.lfw_dir) # Read the file containing the pairs used for testing pairs = lfw.read_pairs(os.path.expanduser(args.lfw_pairs)) # Get the paths for the corresponding images lfw_paths, actual_issame = lfw.get_paths( os.path.expanduser(args.lfw_dir), pairs) with tf.Graph().as_default(): tf.set_random_seed(args.seed) global_step = tf.Variable(0, trainable=False) # Get a list of image paths and their labels image_list, label_list = facenet.get_image_paths_and_labels(train_set) assert len(image_list) > 0, 'The training set should not be empty' val_image_list, val_label_list = facenet.get_image_paths_and_labels( val_set) # Create a queue that produces indices into the image_list and label_list labels = ops.convert_to_tensor(label_list, dtype=tf.int32) range_size = array_ops.shape(labels)[0] index_queue = tf.train.range_input_producer(range_size, num_epochs=None, shuffle=True, seed=None, capacity=32) index_dequeue_op = index_queue.dequeue_many( args.batch_size * args.epoch_size, 'index_dequeue') learning_rate_placeholder = tf.placeholder(tf.float32, name='learning_rate') batch_size_placeholder = tf.placeholder(tf.int32, name='batch_size') phase_train_placeholder = tf.placeholder(tf.bool, name='phase_train') image_paths_placeholder = tf.placeholder(tf.string, shape=(None, 1), name='image_paths') labels_placeholder = tf.placeholder(tf.int32, shape=(None, 1), name='labels') control_placeholder = tf.placeholder(tf.int32, shape=(None, 1), name='control') nrof_preprocess_threads = 4 input_queue = data_flow_ops.FIFOQueue( capacity=2000000, dtypes=[tf.string, tf.int32, tf.int32], shapes=[(1, ), (1, ), (1, )], shared_name=None, name=None) enqueue_op = input_queue.enqueue_many( [image_paths_placeholder, labels_placeholder, control_placeholder], name='enqueue_op') image_batch, label_batch = facenet.create_input_pipeline( input_queue, image_size, nrof_preprocess_threads, batch_size_placeholder) image_batch = tf.identity(image_batch, 'image_batch') image_batch = tf.identity(image_batch, 'input') label_batch = tf.identity(label_batch, 'label_batch') print('Number of classes in training set: %d' % nrof_classes) print('Number of examples in training set: %d' % len(image_list)) print('Number of classes in validation set: %d' % len(val_set)) print('Number of examples in validation set: %d' % len(val_image_list)) print('Building training graph') # Build the inference graph prelogits, _ = network.inference( image_batch, args.keep_probability, phase_train=phase_train_placeholder, bottleneck_layer_size=args.embedding_size, weight_decay=args.weight_decay) logits = slim.fully_connected( prelogits, len(train_set), activation_fn=None, weights_initializer=slim.initializers.xavier_initializer(), weights_regularizer=slim.l2_regularizer(args.weight_decay), scope='Logits', reuse=False) embeddings = tf.nn.l2_normalize(prelogits, 1, 1e-10, name='embeddings') # Norm for the prelogits eps = 1e-4 prelogits_norm = tf.reduce_mean( tf.norm(tf.abs(prelogits) + eps, ord=args.prelogits_norm_p, axis=1)) tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES, prelogits_norm * args.prelogits_norm_loss_factor) # Add center loss prelogits_center_loss, _ = facenet.center_loss(prelogits, label_batch, args.center_loss_alfa, nrof_classes) tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES, prelogits_center_loss * args.center_loss_factor) learning_rate = tf.train.exponential_decay( learning_rate_placeholder, global_step, args.learning_rate_decay_epochs * args.epoch_size, args.learning_rate_decay_factor, staircase=True) tf.summary.scalar('learning_rate', learning_rate) # Calculate the average cross entropy loss across the batch cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits( labels=label_batch, logits=logits, name='cross_entropy_per_example') cross_entropy_mean = tf.reduce_mean(cross_entropy, name='cross_entropy') tf.add_to_collection('losses', cross_entropy_mean) correct_prediction = tf.cast( tf.equal(tf.argmax(logits, 1), tf.cast(label_batch, tf.int64)), tf.float32) accuracy = tf.reduce_mean(correct_prediction) # Calculate the total losses regularization_losses = tf.get_collection( tf.GraphKeys.REGULARIZATION_LOSSES) total_loss = tf.add_n([cross_entropy_mean] + regularization_losses, name='total_loss') # Build a Graph that trains the model with one batch of examples and updates the model parameters train_op = facenet.train(total_loss, global_step, args.optimizer, learning_rate, args.moving_average_decay, tf.global_variables(), args.log_histograms) # Create a saver saver = tf.train.Saver(tf.trainable_variables(), max_to_keep=3) # Build the summary operation based on the TF collection of Summaries. summary_op = tf.summary.merge_all() # Start running operations on the Graph. gpu_options = tf.GPUOptions( per_process_gpu_memory_fraction=args.gpu_memory_fraction) config = tf.ConfigProto(gpu_options=gpu_options, log_device_placement=False) config.gpu_options.visible_device_list = str(hvd.local_rank()) sess = tf.Session(config=config) sess.run(tf.global_variables_initializer()) sess.run(tf.local_variables_initializer()) # Horovod: broadcast initial variable states from rank 0 to all other processes. # This is necessary to ensure consistent initialization of all workers when # training is started with random weights or restored from a checkpoint. bcast = hvd.broadcast_global_variables(0) summary_writer = tf.summary.FileWriter(log_dir, sess.graph) coord = tf.train.Coordinator() tf.train.start_queue_runners(coord=coord, sess=sess) with sess.as_default(): if pretrained_model: print('Restoring pretrained model: %s' % pretrained_model) saver.restore(sess, pretrained_model) # Training and validation loop print('Running training') nrof_steps = args.max_nrof_epochs * args.epoch_size nrof_val_samples = int( math.ceil(args.max_nrof_epochs / args.validate_every_n_epochs) ) # Validate every validate_every_n_epochs as well as in the last epoch stat = { 'loss': np.zeros((nrof_steps, ), np.float32), 'center_loss': np.zeros((nrof_steps, ), np.float32), 'reg_loss': np.zeros((nrof_steps, ), np.float32), 'xent_loss': np.zeros((nrof_steps, ), np.float32), 'prelogits_norm': np.zeros((nrof_steps, ), np.float32), 'accuracy': np.zeros((nrof_steps, ), np.float32), 'val_loss': np.zeros((nrof_val_samples, ), np.float32), 'val_xent_loss': np.zeros((nrof_val_samples, ), np.float32), 'val_accuracy': np.zeros((nrof_val_samples, ), np.float32), 'lfw_accuracy': np.zeros((args.max_nrof_epochs, ), np.float32), 'lfw_valrate': np.zeros((args.max_nrof_epochs, ), np.float32), 'learning_rate': np.zeros((args.max_nrof_epochs, ), np.float32), 'time_train': np.zeros((args.max_nrof_epochs, ), np.float32), 'time_validate': np.zeros((args.max_nrof_epochs, ), np.float32), 'time_evaluate': np.zeros((args.max_nrof_epochs, ), np.float32), 'prelogits_hist': np.zeros((args.max_nrof_epochs, 1000), np.float32), } for epoch in range(1, args.max_nrof_epochs + 1): step = sess.run(global_step, feed_dict=None) # Train for one epoch t = time.time() cont = train( args, sess, epoch, image_list, label_list, index_dequeue_op, enqueue_op, image_paths_placeholder, labels_placeholder, learning_rate_placeholder, phase_train_placeholder, batch_size_placeholder, control_placeholder, global_step, total_loss, train_op, summary_op, summary_writer, regularization_losses, args.learning_rate_schedule_file, stat, cross_entropy_mean, accuracy, learning_rate, prelogits, prelogits_center_loss, args.random_rotate, args.random_crop, args.random_flip, prelogits_norm, args.prelogits_hist_max, args.use_fixed_image_standardization) stat['time_train'][epoch - 1] = time.time() - t if not cont: break t = time.time() if len(val_image_list) > 0 and ( (epoch - 1) % args.validate_every_n_epochs == args.validate_every_n_epochs - 1 or epoch == args.max_nrof_epochs): validate(args, sess, epoch, val_image_list, val_label_list, enqueue_op, image_paths_placeholder, labels_placeholder, control_placeholder, phase_train_placeholder, batch_size_placeholder, stat, total_loss, regularization_losses, cross_entropy_mean, accuracy, args.validate_every_n_epochs, args.use_fixed_image_standardization) stat['time_validate'][epoch - 1] = time.time() - t # Save variables and the metagraph if it doesn't exist already save_variables_and_metagraph(sess, saver, summary_writer, model_dir, subdir, epoch) # Evaluate on LFW t = time.time() if args.lfw_dir: evaluate(sess, enqueue_op, image_paths_placeholder, labels_placeholder, phase_train_placeholder, batch_size_placeholder, control_placeholder, embeddings, label_batch, lfw_paths, actual_issame, args.lfw_batch_size, args.lfw_nrof_folds, log_dir, step, summary_writer, stat, epoch, args.lfw_distance_metric, args.lfw_subtract_mean, args.lfw_use_flipped_images, args.use_fixed_image_standardization) stat['time_evaluate'][epoch - 1] = time.time() - t print('Saving statistics') with h5py.File(stat_file_name, 'w') as f: for key, value in stat.items(): f.create_dataset(key, data=value) return model_dir
def main(argv=None): # pylint: disable=unused-argument if FLAGS.self_test: print('Running self-test.') train_data, train_labels = fake_data(256) validation_data, validation_labels = fake_data(EVAL_BATCH_SIZE) test_data, test_labels = fake_data(EVAL_BATCH_SIZE) num_epochs = 1 else: # Get the data. train_data_filename = maybe_download('train-images-idx3-ubyte.gz') train_labels_filename = maybe_download('train-labels-idx1-ubyte.gz') test_data_filename = maybe_download('t10k-images-idx3-ubyte.gz') test_labels_filename = maybe_download('t10k-labels-idx1-ubyte.gz') # Extract it into numpy arrays. train_data = extract_data(train_data_filename, 60000) train_labels = extract_labels(train_labels_filename, 60000) test_data = extract_data(test_data_filename, 10000) test_labels = extract_labels(test_labels_filename, 10000) # Generate a validation set. validation_data = train_data[:VALIDATION_SIZE, ...] validation_labels = train_labels[:VALIDATION_SIZE] train_data = train_data[VALIDATION_SIZE:, ...] train_labels = train_labels[VALIDATION_SIZE:] num_epochs = NUM_EPOCHS train_size = train_labels.shape[0] # This is where training samples and labels are fed to the graph. # These placeholder nodes will be fed a batch of training data at each # training step using the {feed_dict} argument to the Run() call below. train_data_node = tf.placeholder( data_type(), shape=(BATCH_SIZE, IMAGE_SIZE, IMAGE_SIZE, NUM_CHANNELS)) train_labels_node = tf.placeholder(tf.int64, shape=(BATCH_SIZE,)) eval_data = tf.placeholder( data_type(), shape=(EVAL_BATCH_SIZE, IMAGE_SIZE, IMAGE_SIZE, NUM_CHANNELS)) # The variables below hold all the trainable weights. They are passed an # initial value which will be assigned when we call: # {tf.initialize_all_variables().run()} conv1_weights = tf.Variable( tf.truncated_normal([5, 5, NUM_CHANNELS, 32], # 5x5 filter, depth 32. stddev=0.1, seed=SEED, dtype=data_type())) conv1_biases = tf.Variable(tf.zeros([32], dtype=data_type())) conv2_weights = tf.Variable(tf.truncated_normal( [5, 5, 32, 64], stddev=0.1, seed=SEED, dtype=data_type())) conv2_biases = tf.Variable(tf.constant(0.1, shape=[64], dtype=data_type())) fc1_weights = tf.Variable( # fully connected, depth 512. tf.truncated_normal([IMAGE_SIZE // 4 * IMAGE_SIZE // 4 * 64, 512], stddev=0.1, seed=SEED, dtype=data_type())) fc1_biases = tf.Variable(tf.constant(0.1, shape=[512], dtype=data_type())) fc1p_weights = tf.Variable( # fully connected, depth 512. tf.truncated_normal([512, 2], stddev=0.1, seed=SEED, dtype=data_type())) fc1p_biases = tf.Variable(tf.constant(0.1, shape=[2], dtype=data_type())) fc2_weights = tf.Variable(tf.truncated_normal([2, NUM_LABELS], stddev=0.1, seed=SEED, dtype=data_type())) fc2_biases = tf.Variable(tf.constant( 0.1, shape=[NUM_LABELS], dtype=data_type())) def batch_norm(x, phase_train): #pylint: disable=unused-variable """ Batch normalization on convolutional maps. Args: x: Tensor, 4D BHWD input maps n_out: integer, depth of input maps phase_train: boolean tf.Variable, true indicates training phase scope: string, variable scope affn: whether to affn-transform outputs Return: normed: batch-normalized maps Ref: http://stackoverflow.com/questions/33949786/how-could-i-use-batch-normalization-in-tensorflow/33950177 """ name = 'batch_norm' with tf.variable_scope(name): phase_train = tf.convert_to_tensor(phase_train, dtype=tf.bool) n_out = int(x.get_shape()[-1]) beta = tf.Variable(tf.constant(0.0, shape=[n_out], dtype=x.dtype), name=name+'/beta', trainable=True, dtype=x.dtype) gamma = tf.Variable(tf.constant(1.0, shape=[n_out], dtype=x.dtype), name=name+'/gamma', trainable=True, dtype=x.dtype) batch_mean, batch_var = tf.nn.moments(x, [0], name='moments') ema = tf.train.ExponentialMovingAverage(decay=0.9) def mean_var_with_update(): ema_apply_op = ema.apply([batch_mean, batch_var]) with tf.control_dependencies([ema_apply_op]): return tf.identity(batch_mean), tf.identity(batch_var) mean, var = control_flow_ops.cond(phase_train, mean_var_with_update, lambda: (ema.average(batch_mean), ema.average(batch_var))) normed = tf.nn.batch_normalization(x, mean, var, beta, gamma, 1e-3) return normed # We will replicate the model structure for the training subgraph, as well # as the evaluation subgraphs, while sharing the trainable parameters. def model(data, train=False): """The Model definition.""" # 2D convolution, with 'SAME' padding (i.e. the output feature map has # the same size as the input). Note that {strides} is a 4D array whose # shape matches the data layout: [image index, y, x, depth]. conv = tf.nn.conv2d(data, conv1_weights, strides=[1, 1, 1, 1], padding='SAME') # Bias and rectified linear non-linearity. relu = tf.nn.relu(tf.nn.bias_add(conv, conv1_biases)) # Max pooling. The kernel size spec {ksize} also follows the layout of # the data. Here we have a pooling window of 2, and a stride of 2. pool = tf.nn.max_pool(relu, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME') conv = tf.nn.conv2d(pool, conv2_weights, strides=[1, 1, 1, 1], padding='SAME') relu = tf.nn.relu(tf.nn.bias_add(conv, conv2_biases)) pool = tf.nn.max_pool(relu, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME') # Reshape the feature map cuboid into a 2D matrix to feed it to the # fully connected layers. pool_shape = pool.get_shape().as_list() #pylint: disable=no-member reshape = tf.reshape( pool, [pool_shape[0], pool_shape[1] * pool_shape[2] * pool_shape[3]]) # Fully connected layer. Note that the '+' operation automatically # broadcasts the biases. hidden = tf.nn.relu(tf.matmul(reshape, fc1_weights) + fc1_biases) # Add a 50% dropout during training only. Dropout also scales # activations such that no rescaling is needed at evaluation time. if train: hidden = tf.nn.dropout(hidden, 0.5, seed=SEED) hidden = tf.matmul(hidden, fc1p_weights) + fc1p_biases return tf.nn.relu(tf.matmul(hidden, fc2_weights) + fc2_biases), hidden # Training computation: logits + cross-entropy loss. logits, hidden = model(train_data_node, True) #logits = batch_norm(logits, True) xent_loss = tf.reduce_mean(tf.nn.sparse_softmax_cross_entropy_with_logits( logits, train_labels_node)) beta = 1e-3 #center_loss, update_centers = center_loss_op(hidden, train_labels_node) center_loss, _ = facenet.center_loss(hidden, train_labels_node, 0.95, NUM_LABELS) loss = xent_loss + beta * center_loss # L2 regularization for the fully connected parameters. regularizers = (tf.nn.l2_loss(fc1_weights) + tf.nn.l2_loss(fc1_biases) + tf.nn.l2_loss(fc2_weights) + tf.nn.l2_loss(fc2_biases)) # Add the regularization term to the loss. loss += 5e-4 * regularizers # Optimizer: set up a variable that's incremented once per batch and # controls the learning rate decay. batch = tf.Variable(0, dtype=data_type()) # Decay once per epoch, using an exponential schedule starting at 0.01. learning_rate = tf.train.exponential_decay( 0.01, # Base learning rate. batch * BATCH_SIZE, # Current index into the dataset. train_size, # Decay step. 0.95, # Decay rate. staircase=True) # Use simple momentum for the optimization. optimizer = tf.train.MomentumOptimizer(learning_rate, 0.9).minimize(loss, global_step=batch) # Predictions for the current training minibatch. train_prediction = tf.nn.softmax(logits) # Predictions for the test and validation, which we'll compute less often. eval_logits, eval_embeddings = model(eval_data) eval_prediction = tf.nn.softmax(eval_logits) # Small utility function to evaluate a dataset by feeding batches of data to # {eval_data} and pulling the results from {eval_predictions}. # Saves memory and enables this to run on smaller GPUs. def eval_in_batches(data, sess): """Get all predictions for a dataset by running it in small batches.""" size = data.shape[0] if size < EVAL_BATCH_SIZE: raise ValueError("batch size for evals larger than dataset: %d" % size) predictions = np.ndarray(shape=(size, NUM_LABELS), dtype=np.float32) for begin in xrange(0, size, EVAL_BATCH_SIZE): end = begin + EVAL_BATCH_SIZE if end <= size: predictions[begin:end, :] = sess.run( eval_prediction, feed_dict={eval_data: data[begin:end, ...]}) else: batch_predictions = sess.run( eval_prediction, feed_dict={eval_data: data[-EVAL_BATCH_SIZE:, ...]}) predictions[begin:, :] = batch_predictions[begin - size:, :] return predictions def calculate_embeddings(data, sess): """Get all predictions for a dataset by running it in small batches.""" size = data.shape[0] if size < EVAL_BATCH_SIZE: raise ValueError("batch size for evals larger than dataset: %d" % size) predictions = np.ndarray(shape=(size, 2), dtype=np.float32) for begin in xrange(0, size, EVAL_BATCH_SIZE): end = begin + EVAL_BATCH_SIZE if end <= size: predictions[begin:end, :] = sess.run( eval_embeddings, feed_dict={eval_data: data[begin:end, ...]}) else: batch_predictions = sess.run( eval_embeddings, feed_dict={eval_data: data[-EVAL_BATCH_SIZE:, ...]}) predictions[begin:, :] = batch_predictions[begin - size:, :] return predictions # Create a local session to run the training. start_time = time.time() with tf.Session() as sess: # Run all the initializers to prepare the trainable parameters. tf.initialize_all_variables().run() #pylint: disable=no-member print('Initialized!') # Loop through training steps. for step in xrange(int(num_epochs * train_size) // BATCH_SIZE): # Compute the offset of the current minibatch in the data. # Note that we could use better randomization across epochs. offset = (step * BATCH_SIZE) % (train_size - BATCH_SIZE) batch_data = train_data[offset:(offset + BATCH_SIZE), ...] batch_labels = train_labels[offset:(offset + BATCH_SIZE)] # This dictionary maps the batch data (as a numpy array) to the # node in the graph it should be fed to. feed_dict = {train_data_node: batch_data, train_labels_node: batch_labels} # Run the graph and fetch some of the nodes. #_, l, lr, predictions = sess.run([optimizer, loss, learning_rate, train_prediction], feed_dict=feed_dict) _, cl, l, lr, predictions = sess.run([optimizer, center_loss, loss, learning_rate, train_prediction], feed_dict=feed_dict) if step % EVAL_FREQUENCY == 0: elapsed_time = time.time() - start_time start_time = time.time() print('Step %d (epoch %.2f), %.1f ms' % (step, float(step) * BATCH_SIZE / train_size, 1000 * elapsed_time / EVAL_FREQUENCY)) print('Minibatch loss: %.3f %.3f, learning rate: %.6f' % (l, cl*beta, lr)) print('Minibatch error: %.1f%%' % error_rate(predictions, batch_labels)) print('Validation error: %.1f%%' % error_rate( eval_in_batches(validation_data, sess), validation_labels)) sys.stdout.flush() # Finally print the result! test_error = error_rate(eval_in_batches(test_data, sess), test_labels) print('Test error: %.1f%%' % test_error) if FLAGS.self_test: print('test_error', test_error) assert test_error == 0.0, 'expected 0.0 test_error, got %.2f' % ( test_error,) train_embeddings = calculate_embeddings(train_data, sess) color_list = ['b', 'g', 'r', 'c', 'm', 'y', 'k', 'b', 'g', 'r', 'c' ] plt.figure(1) for n in range(0,10): idx = np.where(train_labels[0:10000]==n) plt.plot(train_embeddings[idx,0], train_embeddings[idx,1], color_list[n]+'.') plt.show()
def main(args): network = importlib.import_module(args.model_def, 'inference') subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S') log_dir = os.path.join(os.path.expanduser(args.logs_base_dir), subdir) # 创建模型文件夹 if not os.path.isdir(log_dir): # Create the log directory if it doesn't exist os.makedirs(log_dir) model_dir = os.path.join(os.path.expanduser(args.models_base_dir), subdir) if not os.path.isdir(model_dir): # Create the model directory if it doesn't exist os.makedirs(model_dir) # Store some git revision info in a text file in the log directory src_path, _ = os.path.split(os.path.realpath(__file__)) facenet.store_revision_info(src_path, log_dir, ' '.join(sys.argv)) np.random.seed(seed=args.seed) train_set = facenet.get_dataset(args.data_dir) nrof_classes = len(train_set) print('Model directory: %s' % model_dir) print('Log directory: %s' % log_dir) pretrained_model = None if args.pretrained_model: pretrained_model = os.path.expanduser(args.pretrained_model) print('Pre-trained model: %s' % pretrained_model) if args.lfw_dir: print('LFW directory: %s' % args.lfw_dir) # Read the file containing the pairs used for testing pairs = lfw.read_pairs(os.path.expanduser(args.lfw_pairs)) # Get the paths for the corresponding images lfw_paths, actual_issame = lfw.get_paths(os.path.expanduser(args.lfw_dir), pairs, args.lfw_file_ext) if args.baihe_pack_file: print('load baihe dataset') lfw_paths, actual_issame = msgpack_numpy.load(open(args.baihe_pack_file)) with tf.Graph().as_default(): tf.set_random_seed(args.seed) # 迭代轮数, 不同的轮数可以使用不同的学习率 global_step = tf.Variable(0, trainable=False) # Get a list of image paths and their labels image_list, label_list = facenet.get_image_paths_and_labels(train_set) # Read data and apply label preserving distortions image_batch, label_batch = facenet.read_and_augment_data(image_list, label_list, args.image_size, args.batch_size, args.max_nrof_epochs, args.random_crop, args.random_flip, args.random_rotate, args.nrof_preprocess_threads) print('Total number of classes: %d' % nrof_classes) print('Total number of examples: %d' % len(image_list)) print('Building training graph') # Placeholder for the learning rate learning_rate_placeholder = tf.placeholder(tf.float32, name='learning_rate') # Build the inference graph, 返回的是网络结构 prelogits, _ = network.inference(image_batch, args.keep_probability, phase_train=True, weight_decay=args.weight_decay) # 初始化采用截断的正态分布噪声, 标准差为0.1 # tf.truncated_normal_initializer(stddev=0.1) logits = slim.fully_connected(prelogits, len(train_set), activation_fn=None, weights_initializer=tf.truncated_normal_initializer(stddev=0.1), weights_regularizer=slim.l2_regularizer(args.weight_decay), scope='Logits', reuse=False) # Add DeCov regularization loss if args.decov_loss_factor > 0.0: logits_decov_loss = facenet.decov_loss(logits) * args.decov_loss_factor # 将decov_loss加入到名字为tf.GraphKeys.REGULARIZATION_LOSSES的集合当中来 tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES, logits_decov_loss) # Add center loss (center_loss作为一个正则项加入到collections) if args.center_loss_factor > 0.0: prelogits_center_loss, _ = facenet.center_loss(prelogits, label_batch, args.center_loss_alfa, nrof_classes) # 将center加入到名字为tf.GraphKeys.REGULARIZATION_LOSSES的集合当中来 tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES, prelogits_center_loss * args.center_loss_factor) # 对学习率进行指数衰退 learning_rate = tf.train.exponential_decay(learning_rate_placeholder, global_step, args.learning_rate_decay_epochs*args.epoch_size, args.learning_rate_decay_factor, staircase=True) tf.scalar_summary('learning_rate', learning_rate) # Calculate the average cross entropy loss across the batch # 将softmax和交叉熵一起做,得到最后的损失函数,提高效率 cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits( logits, label_batch, name='cross_entropy_per_example') cross_entropy_mean = tf.reduce_mean(cross_entropy, name='cross_entropy') tf.add_to_collection('losses', cross_entropy_mean) # Calculate the total losses # 获取正则loss regularization_losses = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES) total_loss = tf.add_n([cross_entropy_mean] + regularization_losses, name='total_loss') # Build a Graph that trains the model with one batch of examples and updates the model parameters train_op = facenet.train(total_loss, global_step, args.optimizer, learning_rate, args.moving_average_decay, tf.all_variables(), args.log_histograms) # Evaluation print('Building evaluation graph') lfw_label_list = range(0, len(lfw_paths)) assert (len(lfw_paths) % args.lfw_batch_size == 0), \ "The number of images in the LFW test set need to be divisible by the lfw_batch_size" eval_image_batch, eval_label_batch = facenet.read_and_augment_data(lfw_paths, lfw_label_list, args.image_size, args.lfw_batch_size, None, False, False, False, args.nrof_preprocess_threads, shuffle=False) # Node for input images eval_image_batch.set_shape((None, args.image_size, args.image_size, 3)) eval_image_batch = tf.identity(eval_image_batch, name='input') eval_prelogits, _ = network.inference(eval_image_batch, 1.0, phase_train=False, weight_decay=0.0, reuse=True) eval_embeddings = tf.nn.l2_normalize(eval_prelogits, 1, 1e-10, name='embeddings') # Create a saver saver = tf.train.Saver(tf.all_variables(), max_to_keep=10) # saver = tf.train.Saver(tf.global_variables(), max_to_keep=10) # Build the summary operation based on the TF collection of Summaries. summary_op = tf.merge_all_summaries() # Start running operations on the Graph. gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=args.gpu_memory_fraction) sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options, log_device_placement=False)) # sess.run(tf.global_variables_initializer()) # sess.run(tf.local_variables_initializer()) sess.run(tf.initialize_all_variables()) sess.run(tf.initialize_local_variables()) summary_writer = tf.train.SummaryWriter(log_dir, sess.graph) tf.train.start_queue_runners(sess=sess) # 将队列runner启动,队列就开始运行,返回启动的线程 # 注意input_queue是先入列,再出列,由于入列的时候输入是place holder,因此到后的线程的时候,会阻塞, # 直到下train中sess run (enqueue_op)的时候, 会向队列中载入值,后面的出列才有对象,才在各自的队列中开始执行 with sess.as_default(): if pretrained_model: print('Restoring pretrained model: %s' % pretrained_model) saver.restore(sess, pretrained_model) # Training and validation loop print('Running training') epoch = 0 while epoch < args.max_nrof_epochs: try: step = sess.run(global_step, feed_dict=None) epoch = step // args.epoch_size # Train for one epoch train(args, sess, epoch, learning_rate_placeholder, global_step, total_loss, train_op, summary_op, summary_writer, regularization_losses, args.learning_rate_schedule_file) # Save variables and the metagraph if it doesn't exist already save_variables_and_metagraph(sess, saver, summary_writer, model_dir, subdir, step) # Evaluate on LFW if args.lfw_dir: evaluate(sess, eval_embeddings, eval_label_batch, actual_issame, args.lfw_batch_size, args.seed, args.lfw_nrof_folds, log_dir, step, summary_writer) # Evaluate on baihe_data if args.baihe_pack_file: evaluate(sess, eval_embeddings, eval_label_batch, actual_issame, args.lfw_batch_size, args.seed, args.lfw_nrof_folds, log_dir, step, summary_writer) except: traceback.print_exc() continue return model_dir
def main(args): #define three networks network_G = importlib.import_module(args.model_def) #import G Network network_D = importlib.import_module(args.discriminator_def) #import D Network (connected with G) network_F = importlib.import_module(args.Net_def) #F network(same with G) #model dir subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S') #model name (named by time)1 log_dir = os.path.join(os.path.expanduser(args.logs_base_dir), subdir) if not os.path.isdir(log_dir): # Create the log directory if it doesn't exist 1 os.makedirs(log_dir) model_dir = os.path.join(os.path.expanduser(args.models_base_dir), subdir) if not os.path.isdir(model_dir): # Create the model directory if it doesn't exist 1 os.makedirs(model_dir) # Write arguments to a text file 1 facenet.write_arguments_to_file(args, os.path.join(log_dir, 'arguments.txt')) #mark arguments # Store some git revision info in a text file in the log directory 1 src_path,_ = os.path.split(os.path.realpath(__file__)) facenet.store_revision_info(src_path, log_dir, ' '.join(sys.argv)) np.random.seed(seed=args.seed) random.seed(args.seed) train_set = facenet.get_dataset(args.data_dir) #get train dataset if args.filter_filename: #not used train_set = filter_dataset(train_set, os.path.expanduser(args.filter_filename), args.filter_percentile, args.filter_min_nrof_images_per_class) nrof_classes = len(train_set) print('Model directory: %s' % model_dir) print('Log directory: %s' % log_dir) pretrained_model = None if args.pretrained_model: pretrained_model = os.path.expanduser(args.pretrained_model) #facenet model print('Pre-trained model: %s' % pretrained_model) # not used here if args.lfw_dir: print('LFW directory: %s' % args.lfw_dir) # Read the file containing the pairs used for testing pairs = lfw.read_pairs(os.path.expanduser(args.lfw_pairs)) # Get the paths for the corresponding images lfw_paths, actual_issame = lfw.get_paths(os.path.expanduser(args.lfw_dir), pairs, args.lfw_file_ext) # copy from faceNet def get_image_paths_and_labels(dataset): image_paths_flat = [] labels_flat = [] for i in range(len(dataset)): image_paths_flat += dataset[i].image_paths #print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')#++++++++++++++++++++++++++++++++ #print(dataset[i].image_paths)#++++++++++++++++++++++++++++++++ labels_flat += [i] * len(dataset[i].image_paths)#labels_flat=age?????????????????????????????????????? return image_paths_flat, labels_flat with tf.Graph().as_default(): tf.set_random_seed(args.seed) global_step = tf.Variable(0, trainable=False) # Get a list of image paths and their labels image_list, label_list = get_image_paths_and_labels(train_set) #[path, path, ..., path], [1,1,2,2,2,3,3,4,...,9] assert len(image_list)>0, 'The dataset should not be empty' # Create a queue that produces indices into the image_list and label_list #labels and images into queue labels = ops.convert_to_tensor(label_list, dtype=tf.int32) range_size = array_ops.shape(labels)[0] index_queue = tf.train.range_input_producer(range_size, num_epochs=None, shuffle=True, seed=None, capacity=32) index_dequeue_op = index_queue.dequeue_many(args.batch_size*args.epoch_size, 'index_dequeue') #placeholder learning_rate_placeholder = tf.placeholder(tf.float32, name='learning_rate') batch_size_placeholder = tf.placeholder(tf.int32, name='batch_size') phase_train_placeholder = tf.placeholder(tf.bool, name='phase_train') #connected to validate image_paths_placeholder = tf.placeholder(tf.string, shape=(None,1), name='image_paths') image_embeddings_placeholder = tf.placeholder(tf.float32, shape=(None,1,args.embedding_size), name='image_embs') labels_placeholder = tf.placeholder(tf.int64, shape=(None,1), name='labels') input_queue = data_flow_ops.FIFOQueue(capacity=100000, dtypes=[tf.string, tf.int64,tf.float32], shapes=[(1,), (1,),(1,args.embedding_size,)], shared_name=None, name=None) #(image path, labels, embedding) enqueue_op = input_queue.enqueue_many([image_paths_placeholder, labels_placeholder,image_embeddings_placeholder], name='enqueue_op') nrof_preprocess_threads = 4 images_and_labels = [] #preprocess some images to extend database for _ in range(nrof_preprocess_threads): filenames, label ,image_embeddings= input_queue.dequeue() #get (image path, labels, embedding) from queue print('filenames.shape, label.shape, image_embeddings.shape:') print(filenames.shape,label.shape,image_embeddings.shape) #print(filenames[1,1]) #queueeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeecheck images = [] for filename in tf.unstack(filenames): file_contents = tf.read_file(filename) image = tf.image.decode_image(file_contents, channels=3) #BGR, , Decode .PNG read an image from filename=image path if args.random_rotate: image = tf.py_func(facenet.random_rotate_image, [image], tf.uint8) if args.random_crop: image = tf.random_crop(image, [args.image_size, args.image_size, 3]) else: #run here image = tf.image.resize_image_with_crop_or_pad(image, args.image_size, args.image_size) if args.random_flip: image = tf.image.random_flip_left_right(image) #pylint: disable=no-member image.set_shape((args.image_size, args.image_size, 3)) images.append(tf.image.per_image_standardization(image)) #add into image set named images #print(len(images)) #1????? images_and_labels.append([images, label,image_embeddings]) #from queue into batch image_batch, label_batch ,embeddings_batch= tf.train.batch_join( images_and_labels, batch_size=batch_size_placeholder, shapes=[(args.image_size, args.image_size, 3), (),(128)], enqueue_many=True, capacity=4 * nrof_preprocess_threads * args.batch_size, allow_smaller_final_batch=True) print('Shape of embeddings_batch:') print(embeddings_batch.shape) image_batch = tf.identity(image_batch, 'image_batch') image_batch = tf.identity(image_batch, 'input') label_batch = tf.identity(label_batch, 'label_batch') embeddings_batch = tf.identity(embeddings_batch, 'emb_batch') print('Total number of classes:%d' %nrof_classes) print('Length of image list:%d' % len(image_list)) print('Building training graph ...') # Build the inference graph, from inception resnet.py prelogits, ep = network_G.inference(image_batch, args.keep_probability, phase_train=phase_train_placeholder, bottleneck_layer_size=args.embedding_size, weight_decay=args.weight_decay) prelogits2, _ = network_D.inference(prelogits,ep, args.keep_probability, phase_train=phase_train_placeholder, bottleneck_layer_size=args.embedding_size, weight_decay=args.weight_decay) prelogits3, ep2 = network_F.inference(image_batch, args.keep_probability, phase_train=phase_train_placeholder, bottleneck_layer_size=args.embedding_size, weight_decay=args.weight_decay) logits = slim.fully_connected(prelogits2, len(train_set), activation_fn=None, weights_initializer=tf.truncated_normal_initializer(stddev=0.1), weights_regularizer=slim.l2_regularizer(args.weight_decay), scope='DiscriminatorLogits', reuse=False) embeddings = tf.nn.l2_normalize(prelogits, 1, 1e-10, name='embeddings') #G feature embeddings2 = tf.nn.l2_normalize(prelogits3, 1, 1e-10, name='embeddings2') #F feature labels = tf.nn.l2_normalize(prelogits2, 1, 1e-10, name='labels') #D decision print('embeddingsshape:',embeddings.shape,embeddings_batch.shape) emb_loss = args.beta * tf.reduce_mean(tf.square(embeddings - embeddings_batch)) #!!!!!!!!!!!!!!!!!!!!!!!emb_loss=pretrained feature-F feature #print('emb_loss') #print(np.sum(emb_loss)) # Add center loss for D center_loss_all=0.0 if args.center_loss_factor>0.0: prelogits_center_loss, _ = facenet.center_loss(prelogits2, label_batch, args.center_loss_alfa, nrof_classes) center_loss_all = prelogits_center_loss * args.center_loss_factor # Do not add the center loss to regularization #regularization_losses = tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES) learning_rate = tf.train.exponential_decay(learning_rate_placeholder, global_step, args.learning_rate_decay_epochs*args.epoch_size, args.learning_rate_decay_factor, staircase=True) tf.summary.scalar('learning_rate', learning_rate) # Calculate the average cross entropy loss across the batch 1 cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits( labels=label_batch, logits=logits, name='cross_entropy_per_example') cross_entropy_mean = tf.reduce_mean(cross_entropy, name='cross_entropy') tf.add_to_collection('losses', cross_entropy_mean) # Calculate the reg losses regularization_losses = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES) #********************************************consistency_loss************************************************************************ consistency_loss_G = args.betaG * tf.reduce_mean(tf.square(embeddings - embeddings2)) consistency_loss_F = args.betaF * tf.reduce_mean(tf.square(embeddings - embeddings2)) #different coefficients #*******************************************unsupervised id loss********************************************************************* #anchor, positive, negative = tf.unstack(tf.reshape(embeddings, [-1,3,args.embedding_size]), 3, 1) anchor = embeddings positive = embeddings2 negative = embeddings id_loss = args.betaI * identity_loss(anchor, positive, negative, args.alpha, args.batch_size) #************************************************************************************************************************************ # losses of three networks total_loss_G = tf.add_n([-cross_entropy_mean] +[-center_loss_all]+ [emb_loss]+[consistency_loss_G]+ regularization_losses, name='total_loss_G') # loss of G_network, to decrease the discriminant # of age while not change embeddings total_loss_D = tf.add_n([cross_entropy_mean] +[center_loss_all]+ regularization_losses, name='total_loss_D') total_loss_F = tf.add_n([id_loss]+ [consistency_loss_F]+ regularization_losses, name='total_loss_F') #optimizer########################################################################################################################### optimizer=args.optimizer loss_averages_op1 = facenet._add_loss_summaries(total_loss_D) loss_averages_op2 = facenet._add_loss_summaries(total_loss_G) loss_averages_op3 = facenet._add_loss_summaries(total_loss_F) #just add an op? learning_rate2=learning_rate learning_rate3=learning_rate if optimizer=='ADAGRAD': opt1 = tf.train.AdagradOptimizer(learning_rate) opt2 = tf.train.AdagradOptimizer(learning_rate2) opt3 = tf.train.AdagradOptimizer(learning_rate3) elif optimizer=='ADADELTA': opt1 = tf.train.AdadeltaOptimizer(learning_rate, rho=0.9, epsilon=1e-6) opt2 = tf.train.AdadeltaOptimizer(learning_rate2, rho=0.9, epsilon=1e-6) opt3 = tf.train.AdadeltaOptimizer(learning_rate3, rho=0.9, epsilon=1e-6) elif optimizer=='ADAM': opt1 = tf.train.AdamOptimizer(learning_rate, beta1=0.9, beta2=0.999, epsilon=0.1) opt2 = tf.train.AdamOptimizer(learning_rate2, beta1=0.9, beta2=0.999, epsilon=0.1) opt3 = tf.train.AdadeltaOptimizer(learning_rate3, beta1=0.9, beta2=0.999, epsilon=0.1) elif optimizer=='RMSPROP': opt1 = tf.train.RMSPropOptimizer(learning_rate, decay=0.9, momentum=0.9, epsilon=1.0) opt2 = tf.train.RMSPropOptimizer(learning_rate2, decay=0.9, momentum=0.9, epsilon=1.0) opt3 = tf.train.AdadeltaOptimizer(learning_rate3, decay=0.9, momentum=0.9, epsilon=1.0) elif optimizer=='MOM': opt1 = tf.train.MomentumOptimizer(learning_rate, 0.9, use_nesterov=True) opt2 = tf.train.MomentumOptimizer(learning_rate2, 0.9, use_nesterov=True) opt3 = tf.train.AdadeltaOptimizer(learning_rate3, 0.9, use_nesterov=True) else: raise ValueError('Invalid optimization algorithm2') t_vars=tf.trainable_variables() varlog=open('tvar.txt','w') for var in t_vars: varlog.write(var.name+'\n') varlog.close() #variables d_vars=[var for var in t_vars if 'Discriminator' in var.name] g_vars=[var for var in t_vars if 'InceptionResnetV1' in var.name] #Generator? how to f_vars=[var for var in t_vars if 'InceptionResnetV2' in var.name] #Generator? how to #true loss for age discriminator and false loss for generator dt_grads = opt1.compute_gradients(total_loss_D, d_vars) df_grads = opt2.compute_gradients(total_loss_G, g_vars) di_grads = opt3.compute_gradients(total_loss_F, f_vars) dt_train_op = opt1.apply_gradients(dt_grads, global_step=global_step) df_train_op = opt2.apply_gradients(df_grads, global_step=global_step) di_train_op = opt3.apply_gradients(di_grads, global_step=global_step) for var in tf.trainable_variables(): tf.summary.histogram(var.op.name, var) # Add histograms for gradients. copy from train2 for grad, var in dt_grads: if grad is not None: tf.summary.histogram(var.op.name + '/gradients', grad) for grad, var in df_grads: if grad is not None: tf.summary.histogram(var.op.name + '/gradients', grad) for grad, var in di_grads: if grad is not None: tf.summary.histogram(var.op.name + '/gradients', grad) # Track the moving averages of all trainable variables. variable_averages = tf.train.ExponentialMovingAverage( args.moving_average_decay, global_step) variables_averages_op = variable_averages.apply(tf.trainable_variables()) with tf.control_dependencies([dt_train_op,df_train_op, variables_averages_op]): train_op = tf.no_op(name='train') # Create a saver saver = tf.train.Saver(tf.trainable_variables(), max_to_keep=3) # save all variables++++++++++++++++++++++++++++++++++++0 saver_G = tf.train.Saver(g_vars, max_to_keep=3) #only save G variables0 saver_F = tf.train.Saver(f_vars, max_to_keep=3) #only save G variables0 # Build the summary operation based on the TF collection of Summaries. 1 summary_op = tf.summary.merge_all() # Start running operations on the Graph. 1 gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=args.gpu_memory_fraction) sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options, log_device_placement=False)) sess.run(tf.global_variables_initializer()) sess.run(tf.local_variables_initializer()) summary_writer = tf.summary.FileWriter(log_dir, sess.graph) coord = tf.train.Coordinator() tf.train.start_queue_runners(coord=coord, sess=sess) with sess.as_default(): if pretrained_model: print('Restoring pretrained model: %s' % pretrained_model) saver_G.restore(sess, pretrained_model) print('Running pretrain embeddings')#see embs********************************** len_all=len(label_list) #*****This is ok 397459 #print('len_all=') #print(len_all) emb_list=np.zeros((len_all,args.embedding_size)) print(len_all//(args.batch_size*args.epoch_size)+1) #obtain pretain feature for ii in range(0,len_all//(args.batch_size*args.epoch_size)+1): emb_list=first_train(args, sess, 0, image_list, label_list, index_dequeue_op, enqueue_op, image_paths_placeholder, labels_placeholder, image_embeddings_placeholder,emb_list,embeddings,label_batch, learning_rate_placeholder, phase_train_placeholder, batch_size_placeholder, global_step, total_loss_D, train_op, summary_op, summary_writer, regularization_losses, args.learning_rate_schedule_file) for ii in range(0,len_all): #print('pretrain embeddings') #print(np.sum(emb_list[ii,:]),file=f) #cannot be printed,why~~~~~~~~~~~~~~~~~~~~~~~~~~~~~! print(emb_list[ii,:],file=f) # Training and validation loop print('Running training') epoch = 0 while epoch < args.max_nrof_epochs: step = sess.run(global_step, feed_dict=None) epoch = step // args.epoch_size//2 # Train for one epoch train(args, sess, epoch, image_list, label_list, index_dequeue_op, enqueue_op, image_paths_placeholder, labels_placeholder, image_embeddings_placeholder,emb_list, learning_rate_placeholder, phase_train_placeholder, batch_size_placeholder, global_step, total_loss_D, train_op, summary_op, summary_writer, regularization_losses, args.learning_rate_schedule_file, anchor, positive, negative, id_loss, consistency_loss_G, emb_loss) # Save variables and the metagraph if it doesn't exist already 1 save_variables_and_metagraph(sess, saver, summary_writer, model_dir, subdir, step) # Evaluate on LFW 1 if args.lfw_dir: evaluate(sess, enqueue_op, image_paths_placeholder, labels_placeholder, phase_train_placeholder, batch_size_placeholder, embeddings, label_batch, lfw_paths, actual_issame, args.lfw_batch_size, args.lfw_nrof_folds, log_dir, step, summary_writer) return model_dir
def main(args): network = importlib.import_module(args.model_def) subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S') log_dir = os.path.join(os.path.expanduser(args.logs_base_dir), subdir) if not os.path.isdir( log_dir): # Create the log directory if it doesn't exist os.makedirs(log_dir) model_dir = os.path.join(os.path.expanduser(args.models_base_dir), subdir) if not os.path.isdir( model_dir): # Create the model directory if it doesn't exist os.makedirs(model_dir) # Write arguments to a text file facenet.write_arguments_to_file(args, os.path.join(log_dir, 'arguments.txt')) # Store some git revision info in a text file in the log directory src_path, _ = os.path.split(os.path.realpath(__file__)) facenet.store_revision_info(src_path, log_dir, ' '.join(sys.argv)) np.random.seed(seed=args.seed) random.seed(args.seed) train_set = facenet.get_dataset(args.data_dir) if args.filter_filename: train_set = filter_dataset(train_set, os.path.expanduser(args.filter_filename), args.filter_percentile, args.filter_min_nrof_images_per_class) nrof_classes = len(train_set) #------------------------------------------------------------------------------------------------------------------- test_set = facenet.get_dataset(args.lfw_dir) if args.filter_filename: test_set = filter_dataset(test_set, os.path.expanduser(args.filter_filename), args.filter_percentile, args.filter_min_nrof_images_per_class) nrof_classes = len(test_set) #---------------------------------------------------------------------------------------------------------------- image_test_list, label_test_list = facenet.get_image_paths_and_labels( test_set) assert len(image_test_list) > 0, 'The dataset should not be empty' #----------------------------------------------------------------------------------------------------------------- #------------------------------------------------------------------------------------------------------------------- print('Model directory: %s' % model_dir) print('Log directory: %s' % log_dir) pretrained_model = None if args.pretrained_model: pretrained_model = os.path.expanduser(args.pretrained_model) print('Pre-trained model: %s' % pretrained_model) if args.lfw_dir: print('LFW directory: %s' % args.lfw_dir) # Read the file containing the pairs used for testing pairs = lfw.read_pairs(os.path.expanduser(args.lfw_pairs)) # Get the paths for the corresponding images lfw_paths, actual_issame = lfw.get_paths( os.path.expanduser(args.lfw_dir), pairs, args.lfw_file_ext) with tf.Graph().as_default(): tf.set_random_seed(args.seed) global_step = tf.Variable(0, trainable=False) # Get a list of image paths and their labels image_list, label_list = facenet.get_image_paths_and_labels(train_set) assert len(image_list) > 0, 'The dataset should not be empty' # Create a queue that produces indices into the image_list and label_list labels = ops.convert_to_tensor(label_list, dtype=tf.int32) range_size = array_ops.shape(labels)[0] index_queue = tf.train.range_input_producer(range_size, num_epochs=None, shuffle=True, seed=None, capacity=32) index_dequeue_op = index_queue.dequeue_many( args.batch_size * args.epoch_size, 'index_dequeue') learning_rate_placeholder = tf.placeholder(tf.float32, name='learning_rate') batch_size_placeholder = tf.placeholder(tf.int32, name='batch_size') phase_train_placeholder = tf.placeholder(tf.bool, name='phase_train') image_paths_placeholder = tf.placeholder(tf.string, shape=(None, 1), name='image_paths') labels_placeholder = tf.placeholder(tf.int64, shape=(None, 1), name='labels') input_queue = data_flow_ops.FIFOQueue(capacity=100000, dtypes=[tf.string, tf.int64], shapes=[(1, ), (1, )], shared_name=None, name=None) enqueue_op = input_queue.enqueue_many( [image_paths_placeholder, labels_placeholder], name='enqueue_op') #------------------------------------------------------------------------------------------------------------------------ test_labels = ops.convert_to_tensor(label_test_list, dtype=tf.int32) test_range_size = array_ops.shape(test_labels)[0] test_index_queue = tf.train.range_input_producer(test_range_size, num_epochs=None, shuffle=True, seed=None, capacity=32) test_index_dequeue_op = test_index_queue.dequeue_many( args.batch_size * args.epoch_size, 'index_dequeue') learning_rate_placeholder = tf.placeholder(tf.float32, name='learning_rate') batch_size_placeholder = tf.placeholder(tf.int32, name='batch_size') phase_train_placeholder = tf.placeholder(tf.bool, name='phase_train') test_image_paths_placeholder = tf.placeholder(tf.string, shape=(None, 1), name='test_image_paths') test_labels_placeholder = tf.placeholder(tf.int64, shape=(None, 1), name='test_labels') input_test_queue = data_flow_ops.FIFOQueue( capacity=8000000, dtypes=[tf.string, tf.int64], shapes=[(1, ), (1, )], shared_name=None, name=None) vali_enqueue_op = input_test_queue.enqueue_many( [test_image_paths_placeholder, test_labels_placeholder], name='vali_enqueue_op') #----------------------------------------------------------------------------------------------------------------------- nrof_preprocess_threads = 4 images_and_labels = [] for _ in range(nrof_preprocess_threads): filenames, label = input_queue.dequeue() images = [] for filename in tf.unstack(filenames): file_contents = tf.read_file(filename) image = tf.image.decode_image(file_contents, channels=3) if args.random_rotate: image = tf.py_func(facenet.random_rotate_image, [image], tf.uint8) if args.random_crop: image = tf.random_crop( image, [args.image_size, args.image_size, 3]) else: image = tf.image.resize_image_with_crop_or_pad( image, args.image_size, args.image_size) if args.random_flip: image = tf.image.random_flip_left_right(image) #pylint: disable=no-member image.set_shape((args.image_size, args.image_size, 3)) images.append(tf.image.per_image_standardization(image)) images_and_labels.append([images, label]) #-------------------------------------------------------------------------------------------------------------------------------- test_images_and_labels = [] test_filenames, test_label = input_test_queue.dequeue() test_images = [] for test_filename in tf.unstack(test_filenames): test_file_contents = tf.read_file(test_filename) test_image = tf.image.decode_image(test_file_contents, channels=3) test_image.set_shape((args.image_size, args.image_size, 3)) test_images.append(tf.image.per_image_standardization(test_image)) test_images_and_labels.append([test_images, test_label]) test_image_batch, test_label_batch = tf.train.batch_join( test_images_and_labels, batch_size=batch_size_placeholder, shapes=[(args.image_size, args.image_size, 3), ()], enqueue_many=True, capacity=4 * args.batch_size, allow_smaller_final_batch=True) test_image_batch = tf.identity(test_image_batch, 'test_image_batch') test_image_batch = tf.identity(test_image_batch, 'test_input') test_label_batch = tf.identity(test_label_batch, 'test_label_batch') #--------------------------------------------------------------------------------------------------------------------------------- image_batch, label_batch = tf.train.batch_join( images_and_labels, batch_size=batch_size_placeholder, shapes=[(args.image_size, args.image_size, 3), ()], enqueue_many=True, capacity=4 * nrof_preprocess_threads * args.batch_size, allow_smaller_final_batch=True) print(image_batch) image_batch = tf.identity(image_batch, 'image_batch') image_batch = tf.identity(image_batch, 'input') label_batch = tf.identity(label_batch, 'label_batch') print('Total number of classes: %d' % nrof_classes) print('Total number of examples: %d' % len(image_list)) print('Building training graph') # Build the inference graph prelogits, _ = network.inference( image_batch, args.keep_probability, phase_train=phase_train_placeholder, bottleneck_layer_size=args.embedding_size, weight_decay=args.weight_decay) logits = slim.fully_connected( prelogits, len(train_set), activation_fn=None, weights_initializer=tf.truncated_normal_initializer(stddev=0.1), weights_regularizer=slim.l2_regularizer(args.weight_decay), scope='Logits', reuse=False) logits = tf.identity(logits, 'final_Logits') #trainable=False, #---------------------------------------------------------------------------------------------------------------------------------- test_prelogits, _ = network.inference( test_image_batch, 1, phase_train=phase_train_placeholder, bottleneck_layer_size=args.embedding_size, weight_decay=args.weight_decay, reuse=True) test_logits = slim.fully_connected( test_prelogits, len(test_set), activation_fn=None, weights_initializer=tf.truncated_normal_initializer(stddev=0.1), weights_regularizer=slim.l2_regularizer(args.weight_decay), scope='Logits', reuse=True) with tf.name_scope('accuracy'): onehot_labels = tf.one_hot(test_label_batch, 7) correct_prediction = tf.equal(tf.argmax(test_logits, 1), tf.argmax(onehot_labels, 1)) correct_prediction = tf.cast(correct_prediction, tf.float32) accuracy_ = tf.cast(tf.reduce_mean(correct_prediction), tf.float32) #print(accuracy_) with tf.name_scope('confusion'): confusion = tf.contrib.metrics.confusion_matrix(test_label_batch, tf.argmax( test_logits, 1), num_classes=7) #print(confusion) #----------------------------------------------------------------------------------------------------------------------------------- embeddings = tf.nn.l2_normalize(prelogits, 1, 1e-10, name='embeddings') # Add center loss if args.center_loss_factor > 0.0: prelogits_center_loss, _ = facenet.center_loss( prelogits, label_batch, args.center_loss_alfa, nrof_classes) tf.add_to_collection( tf.GraphKeys.REGULARIZATION_LOSSES, prelogits_center_loss * args.center_loss_factor) learning_rate = tf.train.exponential_decay( learning_rate_placeholder, global_step, args.learning_rate_decay_epochs * args.epoch_size, args.learning_rate_decay_factor, staircase=True) tf.summary.scalar('learning_rate', learning_rate) # Calculate the average cross entropy loss across the batch cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits( labels=label_batch, logits=logits, name='cross_entropy_per_example') cross_entropy_mean = tf.reduce_mean(cross_entropy, name='cross_entropy') # cross_entropy_mean = focal_loss(onehot_labels=label_batch, cls_preds=logits, # alpha=0.25, gamma=2, name=None, scope=None) tf.add_to_collection('losses', cross_entropy_mean) # Calculate the total losses regularization_losses = tf.get_collection( tf.GraphKeys.REGULARIZATION_LOSSES) total_loss = tf.add_n([cross_entropy_mean] + regularization_losses, name='total_loss') # Build a Graph that trains the model with one batch of examples and updates the model parameters train_op = facenet.train(total_loss, global_step, args.optimizer, learning_rate, args.moving_average_decay, tf.global_variables(), args.log_histograms) # Create a saver saver1 = tf.train.Saver(tf.trainable_variables()[0:-1], max_to_keep=200) saver = tf.train.Saver(max_to_keep=200) # Build the summary operation based on the TF collection of Summaries. summary_op = tf.summary.merge_all() # Start running operations on the Graph. gpu_options = tf.GPUOptions( per_process_gpu_memory_fraction=args.gpu_memory_fraction) sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options, log_device_placement=False)) sess.run(tf.global_variables_initializer()) sess.run(tf.local_variables_initializer()) summary_writer = tf.summary.FileWriter(log_dir, sess.graph) coord = tf.train.Coordinator() tf.train.start_queue_runners(coord=coord, sess=sess) with sess.as_default(): if pretrained_model: print('Restoring pretrained model: %s' % pretrained_model) # init_0 = tf.global_variables_initializer() # sess.run(init_0) # var_names = [] # name2var = dict(zip(map(lambda x:x.name.split(':')[0], tf.global_variables()),tf.global_variables())) # with tf.variable_scope('',reuse=True): # for var_name, saved_var_name in var_names[:-1]: # curr_var = name2var[saved_var_name] # var_shape = curr_var.get_shape().as_list() # if var_shape == saved_shapes[saved_var_name]: # restore_vars.append(curr_var) # saver = tf.train.Saver(restore_vars,max_to_keep=3) saver1.restore(sess, pretrained_model) # Training and validation loop print('Running training') epoch = 0 while epoch < args.max_nrof_epochs: step = sess.run(global_step, feed_dict=None) epoch = step // args.epoch_size # print(step) # Train for one epoch train(args, sess, epoch, image_list, label_list, index_dequeue_op, enqueue_op, image_paths_placeholder, labels_placeholder, learning_rate_placeholder, phase_train_placeholder, batch_size_placeholder, global_step, total_loss, train_op, summary_op, summary_writer, regularization_losses, args.learning_rate_schedule_file) sum_ = 0 confusion_m = tf.zeros((7, 7)) for i in range(7): acc, m = test( confusion, accuracy_, args, sess, epoch, image_test_list, label_test_list, index_dequeue_op, vali_enqueue_op, test_image_paths_placeholder, test_labels_placeholder, learning_rate_placeholder, phase_train_placeholder, batch_size_placeholder, global_step, total_loss, train_op, summary_op, summary_writer, regularization_losses, args.learning_rate_schedule_file) sum_ = sum_ + acc confusion_m = confusion_m + m avg = sum_ / 7 confusion_m = confusion_m / tf.reduce_sum(confusion_m, 1) print(avg) np.set_printoptions(precision=4) print(confusion_m.eval()) summary = tf.Summary() #pylint: disable=maybe-no-member summary.value.add(tag='lfw/accuracy', simple_value=avg) #summary.value.add(tag='lfw/c_matrix', simple_value=m) summary_writer.add_summary(summary, step) with open(os.path.join(log_dir, 'lfw_result.txt'), 'at') as f: f.write('\n%d\t%.5f\t\n' % (step, avg)) f.write(np.array_str(confusion_m.eval())) # Save variables and the metagraph if it doesn't exist already save_variables_and_metagraph(sess, saver, summary_writer, model_dir, subdir, step) # # Evaluate on LFW # if args.lfw_dir: # evaluate(sess, enqueue_op, image_paths_placeholder, labels_placeholder, phase_train_placeholder, batch_size_placeholder, # embeddings, label_batch, lfw_paths, actual_issame, args.lfw_batch_size, args.lfw_nrof_folds, log_dir, step, summary_writer) return model_dir
def train_facenet(config_): # display the model parameters config_.display() # Get the image_size image_size = (config_.im_height, config_.im_width) preprocess(config_) # Create dirs to save the logs and checkpoints subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S') log_dir = os.path.join(os.path.expanduser(config_.logs_base_dir), subdir) if not os.path.isdir( log_dir): # Create the log directory if it doesn't exist os.makedirs(log_dir) model_dir = os.path.join(os.path.expanduser(config_.models_base_dir), subdir) if not os.path.isdir( model_dir): # Create the model directory if it doesn't exist os.makedirs(model_dir) # random seed for reproducability np.random.seed(seed=config_.seed) random.seed(config_.seed) # get the training dataset, the dir should have structure # person1 # person1_image_1 # person1_image_2 # . # . # person 2 # person2_image_1 # . # . dataset = facenet.get_dataset(config_.data_dir) # get train and test dataset if config_.validation_set_split_ratio > 0.0: train_set, val_set = facenet.split_dataset( dataset, config_.validation_set_split_ratio, config_.min_nrof_val_images_per_class, 'SPLIT_IMAGES') else: train_set, val_set = dataset, [] nrof_classes = len(train_set) print('Model directory: %s' % model_dir) print('Log directory: %s' % log_dir) pretrained_model = None if config_.pretrained_model: pretrained_model = os.path.expanduser(config_.pretrained_model) print('Pre-trained model: %s' % pretrained_model) # get the image pairs to test the quality of embedding if config_.lfw_dir: print('LFW directory: %s' % config_.lfw_dir) # Read the file containing the pairs used for testing pairs = lfw.read_pairs(os.path.expanduser(config_.lfw_pairs)) # Get the paths for the corresponding images lfw_paths, actual_issame = lfw.get_paths( os.path.expanduser(config_.lfw_dir), pairs) with tf.Graph().as_default(): tf.set_random_seed(config_.seed) global_step = tf.Variable(0, trainable=False) # Get a list of image paths and their labels image_list, label_list = facenet.get_image_paths_and_labels(train_set) assert len(image_list) > 0, 'The training set should not be empty' val_image_list, val_label_list = facenet.get_image_paths_and_labels( val_set) # Create a queue that produces indices into the image_list and label_list labels = ops.convert_to_tensor(label_list, dtype=tf.int32) range_size = array_ops.shape(labels)[0] index_queue = tf.train.range_input_producer(range_size, num_epochs=None, shuffle=True, seed=None, capacity=32) index_dequeue_op = index_queue.dequeue_many( config_.batch_size * config_.epoch_size, 'index_dequeue') learning_rate_placeholder = tf.placeholder(tf.float32, name='learning_rate') batch_size_placeholder = tf.placeholder(tf.int32, name='batch_size') phase_train_placeholder = tf.placeholder(tf.bool, name='phase_train') image_paths_placeholder = tf.placeholder(tf.string, shape=(None, 1), name='image_paths') labels_placeholder = tf.placeholder(tf.int32, shape=(None, 1), name='labels') control_placeholder = tf.placeholder(tf.int32, shape=(None, 1), name='control') nrof_preprocess_threads = 4 input_queue = data_flow_ops.FIFOQueue( capacity=2000000, dtypes=[tf.string, tf.int32, tf.int32], shapes=[(1, ), (1, ), (1, )], shared_name=None, name=None) enqueue_op = input_queue.enqueue_many( [image_paths_placeholder, labels_placeholder, control_placeholder], name='enqueue_op') image_batch, label_batch = facenet.create_input_pipeline( input_queue, image_size, nrof_preprocess_threads, batch_size_placeholder) image_batch = tf.identity(image_batch, 'image_batch') image_batch = tf.identity(image_batch, 'input') label_batch = tf.identity(label_batch, 'label_batch') print('Number of classes in training set: %d' % nrof_classes) print('Number of examples in training set: %d' % len(image_list)) print('Number of classes in validation set: %d' % len(val_set)) print('Number of examples in validation set: %d' % len(val_image_list)) print('Building training graph') # Build the inference graph prelogits, _ = network.inference( image_batch, config_.keep_probability, phase_train=phase_train_placeholder, bottleneck_layer_size=config_.embedding_size, weight_decay=config_.weight_decay) # logits needed for training, we can ignore this in testing phase logits = slim.fully_connected( prelogits, len(train_set), activation_fn=None, weights_initializer=slim.initializers.xavier_initializer(), weights_regularizer=slim.l2_regularizer(config_.weight_decay), scope='Logits', reuse=False) # learned embeddings, will be used to assess the similarity between two images embeddings = tf.nn.l2_normalize(prelogits, 1, 1e-10, name='embeddings') # Norm for the prelogits eps = 1e-4 prelogits_norm = tf.reduce_mean( tf.norm(tf.abs(prelogits) + eps, ord=config_.prelogits_norm_p, axis=1)) tf.add_to_collection( tf.GraphKeys.REGULARIZATION_LOSSES, prelogits_norm * config_.prelogits_norm_loss_factor) # Add center loss prelogits_center_loss, _ = facenet.center_loss( prelogits, label_batch, config_.center_loss_alfa, nrof_classes) tf.add_to_collection( tf.GraphKeys.REGULARIZATION_LOSSES, prelogits_center_loss * config_.center_loss_factor) learning_rate = tf.train.exponential_decay( learning_rate_placeholder, global_step, config_.learning_rate_decay_epochs * config_.epoch_size, config_.learning_rate_decay_factor, staircase=True) tf.summary.scalar('learning_rate', learning_rate) # Calculate the average cross entropy loss across the batch cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits( labels=label_batch, logits=logits, name='cross_entropy_per_example') cross_entropy_mean = tf.reduce_mean(cross_entropy, name='cross_entropy') tf.add_to_collection('losses', cross_entropy_mean) correct_prediction = tf.cast( tf.equal(tf.argmax(logits, 1), tf.cast(label_batch, tf.int64)), tf.float32) accuracy = tf.reduce_mean(correct_prediction) # Calculate the total losses regularization_losses = tf.get_collection( tf.GraphKeys.REGULARIZATION_LOSSES) total_loss = tf.add_n([cross_entropy_mean] + regularization_losses, name='total_loss') # Build a Graph that trains the model with one batch of examples and updates the model parameters train_op = facenet.train(total_loss, global_step, config_.optimizer, learning_rate, config_.moving_average_decay, tf.global_variables(), config_.log_histograms) # Create a saver all_vars = tf.trainable_variables() var_to_restore = [ v for v in all_vars if not v.name.startswith('Logits') ] saver = tf.train.Saver(var_to_restore, max_to_keep=5, keep_checkpoint_every_n_hours=1.0) #saver = tf.train.Saver(tf.trainable_variables(), max_to_keep=3) # Build the summary operation based on the TF collection of Summaries. summary_op = tf.summary.merge_all() # Start running operations on the Graph. gpu_options = tf.GPUOptions( per_process_gpu_memory_fraction=config_.gpu_memory_fraction) sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options, log_device_placement=False)) sess.run(tf.global_variables_initializer()) sess.run(tf.local_variables_initializer()) summary_writer = tf.summary.FileWriter(log_dir, sess.graph) coord = tf.train.Coordinator() tf.train.start_queue_runners(coord=coord, sess=sess) with sess.as_default(): if pretrained_model: try: print('Restoring pretrained model: %s' % pretrained_model) #saver.restore(sess, pretrained_model) facenet.load_model(pretrained_model) except: print( 'Error loading model(maybe checkpoint path is wrong).. training from scratch' ) # Training and validation loop print('Running training') nrof_steps = config_.max_nrof_epochs * config_.epoch_size nrof_val_samples = int( math.ceil(config_.max_nrof_epochs / config_.validate_every_n_epochs) ) # Validate every validate_every_n_epochs as well as in the last epoch stat = { 'loss': np.zeros((nrof_steps, ), np.float32), 'center_loss': np.zeros((nrof_steps, ), np.float32), 'reg_loss': np.zeros((nrof_steps, ), np.float32), 'xent_loss': np.zeros((nrof_steps, ), np.float32), 'prelogits_norm': np.zeros((nrof_steps, ), np.float32), 'accuracy': np.zeros((nrof_steps, ), np.float32), 'val_loss': np.zeros((nrof_val_samples, ), np.float32), 'val_xent_loss': np.zeros((nrof_val_samples, ), np.float32), 'val_accuracy': np.zeros((nrof_val_samples, ), np.float32), 'lfw_accuracy': np.zeros((config_.max_nrof_epochs, ), np.float32), 'lfw_valrate': np.zeros((config_.max_nrof_epochs, ), np.float32), 'learning_rate': np.zeros((config_.max_nrof_epochs, ), np.float32), 'time_train': np.zeros((config_.max_nrof_epochs, ), np.float32), 'time_validate': np.zeros((config_.max_nrof_epochs, ), np.float32), 'time_evaluate': np.zeros((config_.max_nrof_epochs, ), np.float32), 'prelogits_hist': np.zeros((config_.max_nrof_epochs, 1000), np.float32), } for epoch in range(1, config_.max_nrof_epochs + 1): step = sess.run(global_step, feed_dict=None) # Train for one epoch t = time.time() cont = train( config_, sess, epoch, image_list, label_list, index_dequeue_op, enqueue_op, image_paths_placeholder, labels_placeholder, learning_rate_placeholder, phase_train_placeholder, batch_size_placeholder, control_placeholder, global_step, total_loss, train_op, summary_op, summary_writer, regularization_losses, config_.learning_rate_schedule_file, stat, cross_entropy_mean, accuracy, learning_rate, prelogits, prelogits_center_loss, config_.random_rotate, config_.random_crop, config_.random_flip, prelogits_norm, config_.prelogits_hist_max, config_.use_fixed_image_standardization) stat['time_train'][epoch - 1] = time.time() - t if not cont: break t = time.time() if len(val_image_list) > 0 and ( (epoch - 1) % config_.validate_every_n_epochs == config_.validate_every_n_epochs - 1 or epoch == config_.max_nrof_epochs): validate(config_, sess, epoch, val_image_list, val_label_list, enqueue_op, image_paths_placeholder, labels_placeholder, control_placeholder, phase_train_placeholder, batch_size_placeholder, stat, total_loss, regularization_losses, cross_entropy_mean, accuracy, config_.validate_every_n_epochs, config_.use_fixed_image_standardization) stat['time_validate'][epoch - 1] = time.time() - t # Save variables and the metagraph if it doesn't exist already save_variables_and_metagraph(sess, saver, summary_writer, model_dir, subdir, epoch) # Evaluate on LFW t = time.time() if config_.lfw_dir: evaluate(sess, enqueue_op, image_paths_placeholder, labels_placeholder, phase_train_placeholder, batch_size_placeholder, control_placeholder, embeddings, label_batch, lfw_paths, actual_issame, config_.lfw_batch_size, config_.lfw_nrof_folds, log_dir, step, summary_writer, stat, epoch, config_.lfw_distance_metric, config_.lfw_subtract_mean, config_.lfw_use_flipped_images, config_.use_fixed_image_standardization) stat['time_evaluate'][epoch - 1] = time.time() - t print('Saving statistics') return model_dir
def main(args): network = importlib.import_module(args.model_def) image_size = (args.image_size, args.image_size) subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S') log_dir = os.path.join(os.path.expanduser(args.logs_base_dir), subdir) if not os.path.isdir(log_dir): # Create the log directory if it doesn't exist os.makedirs(log_dir) model_dir = os.path.join(os.path.expanduser(args.models_base_dir), subdir) if not os.path.isdir(model_dir): # Create the model directory if it doesn't exist os.makedirs(model_dir) stat_file_name = os.path.join(log_dir, 'stat.h5') # Write arguments to a text file facenet.write_arguments_to_file(args, os.path.join(log_dir, 'arguments.txt')) # Store some git revision info in a text file in the log directory src_path,_ = os.path.split(os.path.realpath(__file__)) facenet.store_revision_info(src_path, log_dir, ' '.join(sys.argv)) np.random.seed(seed=args.seed) random.seed(args.seed) dataset = facenet.get_dataset(args.data_dir) if args.filter_filename: dataset = filter_dataset(dataset, os.path.expanduser(args.filter_filename), args.filter_percentile, args.filter_min_nrof_images_per_class) if args.validation_set_split_ratio>0.0: train_set, val_set = facenet.split_dataset(dataset, args.validation_set_split_ratio, args.min_nrof_val_images_per_class, 'SPLIT_IMAGES') else: train_set, val_set = dataset, [] nrof_classes = len(train_set) print('Model directory: %s' % model_dir) print('Log directory: %s' % log_dir) pretrained_model = None if args.pretrained_model: pretrained_model = os.path.expanduser(args.pretrained_model) print('Pre-trained model: %s' % pretrained_model) if args.lfw_dir: print('LFW directory: %s' % args.lfw_dir) # Read the file containing the pairs used for testing pairs = lfw.read_pairs(os.path.expanduser(args.lfw_pairs)) # Get the paths for the corresponding images lfw_paths, actual_issame = lfw.get_paths(os.path.expanduser(args.lfw_dir), pairs) with tf.Graph().as_default(): tf.set_random_seed(args.seed) global_step = tf.Variable(0, trainable=False) # Get a list of image paths and their labels image_list, label_list = facenet.get_image_paths_and_labels(train_set) assert len(image_list)>0, 'The training set should not be empty' val_image_list, val_label_list = facenet.get_image_paths_and_labels(val_set) # Create a queue that produces indices into the image_list and label_list labels = ops.convert_to_tensor(label_list, dtype=tf.int32) range_size = array_ops.shape(labels)[0] index_queue = tf.train.range_input_producer(range_size, num_epochs=None, shuffle=True, seed=None, capacity=32) index_dequeue_op = index_queue.dequeue_many(args.batch_size*args.epoch_size, 'index_dequeue') learning_rate_placeholder = tf.placeholder(tf.float32, name='learning_rate') batch_size_placeholder = tf.placeholder(tf.int32, name='batch_size') phase_train_placeholder = tf.placeholder(tf.bool, name='phase_train') image_paths_placeholder = tf.placeholder(tf.string, shape=(None,1), name='image_paths') labels_placeholder = tf.placeholder(tf.int32, shape=(None,1), name='labels') control_placeholder = tf.placeholder(tf.int32, shape=(None,1), name='control') nrof_preprocess_threads = 4 input_queue = data_flow_ops.FIFOQueue(capacity=2000000, dtypes=[tf.string, tf.int32, tf.int32], shapes=[(1,), (1,), (1,)], shared_name=None, name=None) enqueue_op = input_queue.enqueue_many([image_paths_placeholder, labels_placeholder, control_placeholder], name='enqueue_op') image_batch, label_batch = facenet.create_input_pipeline(input_queue, image_size, nrof_preprocess_threads, batch_size_placeholder) image_batch = tf.identity(image_batch, 'image_batch') image_batch = tf.identity(image_batch, 'input') label_batch = tf.identity(label_batch, 'label_batch') print('Number of classes in training set: %d' % nrof_classes) print('Number of examples in training set: %d' % len(image_list)) print('Number of classes in validation set: %d' % len(val_set)) print('Number of examples in validation set: %d' % len(val_image_list)) print('Building training graph') # Build the inference graph prelogits, _ = network.inference(image_batch, args.keep_probability, phase_train=phase_train_placeholder, bottleneck_layer_size=args.embedding_size, weight_decay=args.weight_decay) logits = slim.fully_connected(prelogits, len(train_set), activation_fn=None, weights_initializer=slim.initializers.xavier_initializer(), weights_regularizer=slim.l2_regularizer(args.weight_decay), scope='Logits', reuse=False) embeddings = tf.nn.l2_normalize(prelogits, 1, 1e-10, name='embeddings') # Norm for the prelogits eps = 1e-4 prelogits_norm = tf.reduce_mean(tf.norm(tf.abs(prelogits)+eps, ord=args.prelogits_norm_p, axis=1)) tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES, prelogits_norm * args.prelogits_norm_loss_factor) # Add center loss prelogits_center_loss, _ = facenet.center_loss(prelogits, label_batch, args.center_loss_alfa, nrof_classes) tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES, prelogits_center_loss * args.center_loss_factor) learning_rate = tf.train.exponential_decay(learning_rate_placeholder, global_step, args.learning_rate_decay_epochs*args.epoch_size, args.learning_rate_decay_factor, staircase=True) tf.summary.scalar('learning_rate', learning_rate) # Calculate the average cross entropy loss across the batch cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits( labels=label_batch, logits=logits, name='cross_entropy_per_example') cross_entropy_mean = tf.reduce_mean(cross_entropy, name='cross_entropy') tf.add_to_collection('losses', cross_entropy_mean) correct_prediction = tf.cast(tf.equal(tf.argmax(logits, 1), tf.cast(label_batch, tf.int64)), tf.float32) accuracy = tf.reduce_mean(correct_prediction) # Calculate the total losses regularization_losses = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES) total_loss = tf.add_n([cross_entropy_mean] + regularization_losses, name='total_loss') # Build a Graph that trains the model with one batch of examples and updates the model parameters train_op = facenet.train(total_loss, global_step, args.optimizer, learning_rate, args.moving_average_decay, tf.global_variables(), args.log_histograms) # Create a saver saver = tf.train.Saver(tf.trainable_variables(), max_to_keep=3) # Build the summary operation based on the TF collection of Summaries. summary_op = tf.summary.merge_all() # Start running operations on the Graph. gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=args.gpu_memory_fraction) sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options, log_device_placement=False)) sess.run(tf.global_variables_initializer()) sess.run(tf.local_variables_initializer()) summary_writer = tf.summary.FileWriter(log_dir, sess.graph) coord = tf.train.Coordinator() tf.train.start_queue_runners(coord=coord, sess=sess) with sess.as_default(): if pretrained_model: print('Restoring pretrained model: %s' % pretrained_model) saver.restore(sess, pretrained_model) # Training and validation loop print('Running training') nrof_steps = args.max_nrof_epochs*args.epoch_size nrof_val_samples = int(math.ceil(args.max_nrof_epochs / args.validate_every_n_epochs)) # Validate every validate_every_n_epochs as well as in the last epoch stat = { 'loss': np.zeros((nrof_steps,), np.float32), 'center_loss': np.zeros((nrof_steps,), np.float32), 'reg_loss': np.zeros((nrof_steps,), np.float32), 'xent_loss': np.zeros((nrof_steps,), np.float32), 'prelogits_norm': np.zeros((nrof_steps,), np.float32), 'accuracy': np.zeros((nrof_steps,), np.float32), 'val_loss': np.zeros((nrof_val_samples,), np.float32), 'val_xent_loss': np.zeros((nrof_val_samples,), np.float32), 'val_accuracy': np.zeros((nrof_val_samples,), np.float32), 'lfw_accuracy': np.zeros((args.max_nrof_epochs,), np.float32), 'lfw_valrate': np.zeros((args.max_nrof_epochs,), np.float32), 'learning_rate': np.zeros((args.max_nrof_epochs,), np.float32), 'time_train': np.zeros((args.max_nrof_epochs,), np.float32), 'time_validate': np.zeros((args.max_nrof_epochs,), np.float32), 'time_evaluate': np.zeros((args.max_nrof_epochs,), np.float32), 'prelogits_hist': np.zeros((args.max_nrof_epochs, 1000), np.float32), } for epoch in range(1,args.max_nrof_epochs+1): step = sess.run(global_step, feed_dict=None) # Train for one epoch t = time.time() cont = train(args, sess, epoch, image_list, label_list, index_dequeue_op, enqueue_op, image_paths_placeholder, labels_placeholder, learning_rate_placeholder, phase_train_placeholder, batch_size_placeholder, control_placeholder, global_step, total_loss, train_op, summary_op, summary_writer, regularization_losses, args.learning_rate_schedule_file, stat, cross_entropy_mean, accuracy, learning_rate, prelogits, prelogits_center_loss, args.random_rotate, args.random_crop, args.random_flip, prelogits_norm, args.prelogits_hist_max, args.use_fixed_image_standardization) stat['time_train'][epoch-1] = time.time() - t if not cont: break t = time.time() if len(val_image_list)>0 and ((epoch-1) % args.validate_every_n_epochs == args.validate_every_n_epochs-1 or epoch==args.max_nrof_epochs): validate(args, sess, epoch, val_image_list, val_label_list, enqueue_op, image_paths_placeholder, labels_placeholder, control_placeholder, phase_train_placeholder, batch_size_placeholder, stat, total_loss, regularization_losses, cross_entropy_mean, accuracy, args.validate_every_n_epochs, args.use_fixed_image_standardization) stat['time_validate'][epoch-1] = time.time() - t # Save variables and the metagraph if it doesn't exist already save_variables_and_metagraph(sess, saver, summary_writer, model_dir, subdir, epoch) # Evaluate on LFW t = time.time() if args.lfw_dir: evaluate(sess, enqueue_op, image_paths_placeholder, labels_placeholder, phase_train_placeholder, batch_size_placeholder, control_placeholder, embeddings, label_batch, lfw_paths, actual_issame, args.lfw_batch_size, args.lfw_nrof_folds, log_dir, step, summary_writer, stat, epoch, args.lfw_distance_metric, args.lfw_subtract_mean, args.lfw_use_flipped_images, args.use_fixed_image_standardization) stat['time_evaluate'][epoch-1] = time.time() - t print('Saving statistics') with h5py.File(stat_file_name, 'w') as f: for key, value in stat.iteritems(): f.create_dataset(key, data=value) return model_dir
def main(args): TEMPORAL_DIM = int(args.image_w / 5) SPATIAL_DIM = int(args.image_h / 5) seed_batch_idx = args.seed_batch_idx network = importlib.import_module(args.model_def) subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S') log_dir = os.path.join(os.path.expanduser(args.logs_base_dir), subdir) if not os.path.isdir( log_dir): # Create the log directory if it doesn't exist os.makedirs(log_dir) model_dir = os.path.join(os.path.expanduser(args.models_base_dir), subdir) if not os.path.isdir( model_dir): # Create the model directory if it doesn't exist os.makedirs(model_dir) # Write arguments to a text file facenet.write_arguments_to_file(args, os.path.join(log_dir, 'arguments.txt')) # Store some git revision info in a text file in the log directory src_path, _ = os.path.split(os.path.realpath(__file__)) facenet.store_revision_info(src_path, log_dir, ' '.join(sys.argv)) np.random.seed(seed=args.seed) random.seed(args.seed) train_set = facenet.get_dataset(args.data_dir) nrof_classes = len(train_set) print('Model directory: %s' % model_dir) print('Log directory: %s' % log_dir) pretrained_model = None if args.pretrained_model: pretrained_model = os.path.expanduser(args.pretrained_model) print('Pre-trained model: %s' % pretrained_model) with tf.Graph().as_default(): tf.set_random_seed(args.seed) global_step = tf.Variable(0, trainable=False) # Get a list of image paths and their labels action_list, label_list = get_image_paths_and_labels( dataPath=args.dataPath, s_ID=None, is_training=True, x_type=args.x_type) assert len(action_list) > 0, 'The dataset should not be empty' ## create input pipeline queue_input_data = tf.placeholder( tf.float32, shape=[None, args.image_h, args.image_w, 3]) queue_input_label = tf.placeholder(tf.int64, shape=[None, 1]) queue = tf.FIFOQueue(capacity=20000, dtypes=[tf.float32, tf.int64], shapes=[[args.image_h, args.image_w, 3], [1]]) enqueue_op = queue.enqueue_many([queue_input_data, queue_input_label]) dequeue_data, dequeue_lab = queue.dequeue() dequeue_image = tf.image.per_image_standardization(dequeue_data) # Create a queue that produces indices into the action_list and label_list labels = ops.convert_to_tensor(label_list, dtype=tf.int32) range_size = array_ops.shape(labels)[0] index_queue = tf.train.range_input_producer(range_size, num_epochs=None, shuffle=True, seed=None, capacity=32) #index_dequeue_op = index_queue.dequeue_many(args.batch_size*args.epoch_size, 'index_dequeue') index_dequeue_op = index_queue.dequeue_many(args.batch_size * 100, 'index_dequeue') learning_rate_placeholder = tf.placeholder(tf.float32, name='learning_rate') batch_size_placeholder = tf.placeholder(tf.int32, name='batch_size') phase_train_placeholder = tf.placeholder(tf.bool, name='phase_train') image_paths_placeholder = tf.placeholder(tf.string, shape=(None, 1), name='image_paths') labels_placeholder = tf.placeholder(tf.int64, shape=(None, 1), name='labels') #image_batch, label_batch = tf.train.batch([dequeue_image, dequeue_lab], batch_size=args.batch_size, capacity=100) image_batch, label_batch = tf.train.batch( [dequeue_image, dequeue_lab], batch_size=batch_size_placeholder, capacity=1000) label_batch = tf.squeeze(label_batch) image_batch = tf.identity(image_batch, 'input') label_batch = tf.identity(label_batch, 'label_batch') tf.summary.image("input_image", image_batch, max_outputs=4) print('Total number of classes: %d' % nrof_classes) print('Total number of examples: %d' % len(action_list)) print('Building training graph') # Build the inference graph prelogits, _ = network.inference( image_batch, args.keep_probability, phase_train=phase_train_placeholder, bottleneck_layer_size=args.embedding_size, weight_decay=args.weight_decay) logits = slim.fully_connected( prelogits, len(train_set), activation_fn=None, weights_initializer=tf.truncated_normal_initializer(stddev=0.1), weights_regularizer=slim.l2_regularizer(args.weight_decay), scope='Logits', reuse=False) embeddings = tf.nn.l2_normalize(prelogits, 1, 1e-10, name='embeddings') # Add center loss if args.center_loss_factor > 0.0: prelogits_center_loss, _ = facenet.center_loss( prelogits, label_batch, args.center_loss_alfa, nrof_classes) tf.add_to_collection( tf.GraphKeys.REGULARIZATION_LOSSES, prelogits_center_loss * args.center_loss_factor) learning_rate = tf.train.exponential_decay( learning_rate_placeholder, global_step, args.learning_rate_decay_epochs * args.epoch_size, args.learning_rate_decay_factor, staircase=True) tf.summary.scalar('learning_rate', learning_rate) # Calculate the average cross entropy loss across the batch cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits( labels=label_batch, logits=logits, name='cross_entropy_per_example') cross_entropy_mean = tf.reduce_mean(cross_entropy, name='cross_entropy') tf.add_to_collection('losses', cross_entropy_mean) # Calculate batch accuracy correct_prediction = tf.equal(tf.argmax(logits, axis=1), label_batch) batch_accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32), name='batch_accuracy') tf.summary.scalar('batch_accuracy', batch_accuracy) # Calculate the total losses regularization_losses = tf.get_collection( tf.GraphKeys.REGULARIZATION_LOSSES) total_loss = tf.add_n([cross_entropy_mean] + regularization_losses, name='total_loss') # Build a Graph that trains the model with one 0batch of examples and updates the model parameters train_op = facenet.train(total_loss, global_step, args.optimizer, learning_rate, args.moving_average_decay, tf.global_variables(), args.log_histograms) # Create a saver saver = tf.train.Saver(tf.trainable_variables(), max_to_keep=10) # Build the summary operation based on the TF collection of Summaries. summary_op = tf.summary.merge_all() # Start running operations on the Graph. gpu_options = tf.GPUOptions( per_process_gpu_memory_fraction=args.gpu_memory_fraction) sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options, log_device_placement=False)) sess.run(tf.global_variables_initializer()) sess.run(tf.local_variables_initializer()) summary_writer = tf.summary.FileWriter(log_dir, sess.graph) coord = tf.train.Coordinator() threads = tf.train.start_queue_runners(coord=coord, sess=sess) enqueue_thread = threading.Thread(target=enqueue, args=[ sess, index_dequeue_op, enqueue_op, action_list, label_list, queue_input_data, queue_input_label, TEMPORAL_DIM, SPATIAL_DIM, seed_batch_idx ]) enqueue_thread.isDaemon() enqueue_thread.start() with sess.as_default(): if pretrained_model: print('Restoring pretrained model: %s' % pretrained_model) saver.restore(sess, pretrained_model) # Training and validation loop print('Running training') epoch = 0 while epoch < args.max_nrof_epochs: step = sess.run(global_step, feed_dict=None) epoch = step // args.epoch_size # Train for one epoch train( args, sess, epoch, #image_list, label_list, index_dequeue_op, enqueue_op, image_paths_placeholder, labels_placeholder, learning_rate_placeholder, phase_train_placeholder, batch_size_placeholder, global_step, total_loss, train_op, summary_op, summary_writer, regularization_losses, args.learning_rate_schedule_file) # Save variables and the metagraph if it doesn't exist already save_variables_and_metagraph(sess, saver, summary_writer, model_dir, subdir, step) # Evaluate on LFW if args.lfw_dir: evaluate(sess, enqueue_op, image_paths_placeholder, labels_placeholder, phase_train_placeholder, batch_size_placeholder, embeddings, label_batch, lfw_paths, actual_issame, args.lfw_batch_size, args.lfw_nrof_folds, log_dir, step, summary_writer) sess.run(queue.close(cancel_pending_enqueues=True)) coord.request_stop() coord.join(threads) sess.close() return model_dir
def main(args): network = importlib.import_module( args.model_def) # --model_def models.inception_resnet_v1 subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S') log_dir = os.path.join(os.path.expanduser(args.logs_base_dir), subdir) # 日志的地址 if not os.path.isdir( log_dir): # Create the log directory if it doesn't exist os.makedirs(log_dir) model_dir = os.path.join(os.path.expanduser(args.models_base_dir), subdir) # 训练模型存储地址 if not os.path.isdir( model_dir): # Create the model directory if it doesn't exist os.makedirs(model_dir) # Write arguments to a text file facenet.write_arguments_to_file(args, os.path.join(log_dir, 'arguments.txt')) # Store some git revision info in a text file in the log directory src_path, _ = os.path.split(os.path.realpath(__file__)) facenet.store_revision_info(src_path, log_dir, ' '.join(sys.argv)) np.random.seed(seed=args.seed) random.seed(args.seed) train_set = facenet.get_dataset(args.data_dir) # 读取训练图片的路径 if args.filter_filename: train_set = filter_dataset(train_set, os.path.expanduser(args.filter_filename), args.filter_percentile, args.filter_min_nrof_images_per_class) # train set中是元组,一个标签,对应一个或多个路径 # 所以这里返回的nrof_classes是样本类别个数 nrof_classes = len(train_set) print('Model directory: %s' % model_dir) print('Log directory: %s' % log_dir) pretrained_model = None if args.pretrained_model: pretrained_model = os.path.expanduser(args.pretrained_model) print('Pre-trained model: %s' % pretrained_model) if args.lfw_dir: print('LFW directory: %s' % args.lfw_dir) # Read the file containing the pairs used for testing pairs = lfw.read_pairs(os.path.expanduser(args.lfw_pairs)) # Get the paths for the corresponding images lfw_paths, actual_issame = lfw.get_paths( os.path.expanduser(args.lfw_dir), pairs, args.lfw_file_ext) with tf.Graph().as_default(): tf.set_random_seed(args.seed) # global_step对应的是全局批的个数,根据这个参数可以更新学习率 global_step = tf.Variable(0, trainable=False) # global_step经常在滑动平均,学习速率变化的时候需要用到,系统会自动更新这个参数的值,从1开始。 # Get a list of image paths and their labels image_list, label_list = facenet.get_image_paths_and_labels(train_set) assert len(image_list) > 0, 'The dataset should not be empty' # Create a queue that produces indices into the image_list and label_list labels = ops.convert_to_tensor(label_list, dtype=tf.int32) # range_size的大小和样本个数一样 range_size = array_ops.shape(labels)[0] # QueueRunner:保存的是队列中的入列操作,保存在一个list当中,其中每个enqueue运行在一个线程当中 # range_input_producer:返回的是一个队列,队列中有打乱的整数,范围是从0到range size # range_size大小和总的样本个数一样 # 并将一个QueueRunner添加到当前图的QUEUE_RUNNER集合中 index_queue = tf.train.range_input_producer(range_size, num_epochs=None, shuffle=True, seed=None, capacity=32) # 返回的是一个出列操作,每次出列一个epoch中需要用到的样本个数 index_dequeue_op = index_queue.dequeue_many( args.batch_size * args.epoch_size, 'index_dequeue') # tf.placeholder:用于得到传递进来的真实的训练样本: # 不必指定初始值,可在运行时,通过 Session.run的函数的feed_dict参数指定; # 学习率 learning_rate_placeholder = tf.placeholder(tf.float32, name='learning_rate') # 批大小 batch_size_placeholder = tf.placeholder(tf.int32, name='batch_size') # 用于判断是训练还是测试 phase_train_placeholder = tf.placeholder(tf.bool, name='phase_train') # 图像路径 image_paths_placeholder = tf.placeholder(tf.string, shape=(None, 1), name='image_paths') # 图像标签 labels_placeholder = tf.placeholder(tf.int64, shape=(None, 1), name='labels') # 上面的队列是一个样本索引的出列队列,只用来出列 # 用来每次出列一个epoch中需要用到的样本 # 这里是第二个队列,这个队列用来入列,队列的大小为10万,每个元素的大小为shapes=[(1,), (1,)], input_queue = data_flow_ops.FIFOQueue(capacity=100000, dtypes=[tf.string, tf.int64], shapes=[(1, ), (1, )], shared_name=None, name=None) # 这时一个入列的操作,这个操作将在session run的时候用到 # 每次入列的是image_paths_placeholder, labels_placeholder对 # 注意,这里只有2个队列,一个用来出列打乱的元素序号 # 一个根据对应的需要读取指定的文件 enqueue_op = input_queue.enqueue_many( [image_paths_placeholder, labels_placeholder], name='enqueue_op') # 4个线程 # 在不同的线程中入列不同的tensor需要入列的样本在images_and_labels中 # 创建的线程个数为len(images_and_labels) # 在这里应该是有4个入列线程,因为images_and_labels只append4次 # 线程i入列张量images_and_labels[i] nrof_preprocess_threads = 4 images_and_labels = [] for _ in range(nrof_preprocess_threads): filenames, label = input_queue.dequeue() images = [] for filename in tf.unstack(filenames): file_contents = tf.read_file(filename) image = tf.image.decode_image(file_contents, channels=3) if args.random_rotate: image = tf.py_func(facenet.random_rotate_image, [image], tf.uint8) if args.random_crop: image = tf.random_crop( image, [args.image_size, args.image_size, 3]) else: image = tf.image.resize_image_with_crop_or_pad( image, args.image_size, args.image_size) if args.random_flip: image = tf.image.random_flip_left_right(image) # pylint: disable=no-member image.set_shape((args.image_size, args.image_size, 3)) images.append(tf.image.per_image_standardization(image)) images_and_labels.append([images, label]) # batch_join的作用是创建样本批,用于批处理 # capacity控制着用于增长队列的预取的个数 # batch_size用于出列的一个批的大小 # enqueue_many表示一次出列多个数据 # shapes:样本的shape,默认根据images_and_labels[i]推断出来 image_batch, label_batch = tf.train.batch_join( images_and_labels, batch_size=batch_size_placeholder, shapes=[(args.image_size, args.image_size, 3), ()], enqueue_many=True, capacity=4 * nrof_preprocess_threads * args.batch_size, allow_smaller_final_batch=True) image_batch = tf.identity(image_batch, 'image_batch') image_batch = tf.identity(image_batch, 'input') label_batch = tf.identity(label_batch, 'label_batch') print('Total number of classes: %d' % nrof_classes) print('Total number of examples: %d' % len(image_list)) print('Building training graph') # Build the inference graph # 创建网络图:除了全连接层和损失层 prelogits, _ = network.inference( image_batch, args.keep_probability, phase_train=phase_train_placeholder, bottleneck_layer_size=args.embedding_size, weight_decay=args.weight_decay) logits = slim.fully_connected( prelogits, len(train_set), activation_fn=None, weights_initializer=tf.truncated_normal_initializer(stddev=0.1), weights_regularizer=slim.l2_regularizer(args.weight_decay), scope='Logits', reuse=False) embeddings = tf.nn.l2_normalize(prelogits, 1, 1e-10, name='embeddings') # Add center loss --center_loss_factor 1e-2 if args.center_loss_factor > 0.0: prelogits_center_loss, _ = facenet.center_loss( prelogits, label_batch, args.center_loss_alfa, nrof_classes) # 将center加入到名字为tf.GraphKeys.REGULARIZATION_LOSSES的集合当中来 tf.add_to_collection( tf.GraphKeys.REGULARIZATION_LOSSES, prelogits_center_loss * args.center_loss_factor) # 将指数衰减应用到学习率上 learning_rate = tf.train.exponential_decay( learning_rate_placeholder, global_step, args.learning_rate_decay_epochs * args.epoch_size, args.learning_rate_decay_factor, staircase=True) tf.summary.scalar('learning_rate', learning_rate) # Calculate the average cross entropy loss across the batch # 将softmax和交叉熵一起做,得到最后的损失函数,提高效率 cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits( labels=label_batch, logits=logits, name='cross_entropy_per_example') cross_entropy_mean = tf.reduce_mean(cross_entropy, name='cross_entropy') # tf.reduce_mean(x) ==> 2.5 #如果不指定第二个参数,那么就在所有的元素中取平均值 tf.add_to_collection('losses', cross_entropy_mean) # Calculate the total losses # 根据REGULARIZATION_LOSSES返回一个收集器中所收集的值的列表 regularization_losses = tf.get_collection( tf.GraphKeys.REGULARIZATION_LOSSES) # 我们选择L2-正则化来实现这一点,L2正则化将网络中所有权重的平方和加到损失函数。如果模型使用大权重,则对应重罚分,并且如果模型使用小权重,则小罚分。 # 这就是为什么我们在定义权重时使用了regularizer参数,并为它分配了一个l2_regularizer。这告诉了TensorFlow要跟踪 # l2_regularizer这个变量的L2正则化项(并通过参数reg_constant对它们进行加权)。 # 所有正则化项被添加到一个损失函数可以访问的集合——tf.GraphKeys.REGULARIZATION_LOSSES。 # 将所有正则化损失的总和与先前计算的triplet_loss相加,以得到我们的模型的总损失。 total_loss = tf.add_n([cross_entropy_mean] + regularization_losses, name='total_loss') # Build a Graph that trains the model with one batch of examples and updates the model parameters # 确定优化方法并求根据损失函数求梯度,在这里面,每更新一次参数,global_step会加1 train_op = facenet.train(total_loss, global_step, args.optimizer, learning_rate, args.moving_average_decay, tf.global_variables(), args.log_histograms) set_A_vars = [ v for v in tf.trainable_variables() if v.name.startswith('InceptionResnetV1') ] # 加载官方预训练模型 saver_set_A = tf.train.Saver(set_A_vars, max_to_keep=200) # 加载官方预训练模型,一共加三行代码 # Create a saver # 创建一个saver用于保存或从内存中恢复一个模型参数 saver = tf.train.Saver(tf.trainable_variables(), max_to_keep=200) # Build the summary operation based on the TF collection of Summaries. summary_op = tf.summary.merge_all() # Start running operations on the Graph. # 能够在gpu上分配的最大内存 gpu_options = tf.GPUOptions( per_process_gpu_memory_fraction=args.gpu_memory_fraction) sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options, log_device_placement=False)) sess.run(tf.global_variables_initializer()) sess.run(tf.local_variables_initializer()) summary_writer = tf.summary.FileWriter(log_dir, sess.graph) coord = tf.train.Coordinator() tf.train.start_queue_runners(coord=coord, sess=sess) with sess.as_default(): if pretrained_model: print('Restoring pretrained model: %s' % pretrained_model) saver_set_A.restore(sess, pretrained_model) # 加载官方预训练模型 # saver.restore(sess, pretrained_model)#可以加载以前训练的softmax模型 # Training and validation loop,max_nrof_epochs = 80,epoch_size = 默认default=1000 print('Running training') epoch = 0 while epoch < args.max_nrof_epochs: # step可以看做是全局的批处理个数 step = sess.run(global_step, feed_dict=None) # epoch_size是一个epoch中批的个数 # 这个epoch是全局的批处理个数除以一个epoch中批的个数得到epoch epoch = step // args.epoch_size # 双斜杠为取整的5//3 = 1 # Train for one epoch train(args, sess, epoch, image_list, label_list, index_dequeue_op, enqueue_op, image_paths_placeholder, labels_placeholder, learning_rate_placeholder, phase_train_placeholder, batch_size_placeholder, global_step, total_loss, train_op, summary_op, summary_writer, regularization_losses, args.learning_rate_schedule_file) # Save variables and the metagraph if it doesn't exist already,存储模型 save_variables_and_metagraph(sess, saver, summary_writer, model_dir, subdir, step) # Evaluate on LFW if args.lfw_dir: evaluate(sess, enqueue_op, image_paths_placeholder, labels_placeholder, phase_train_placeholder, batch_size_placeholder, embeddings, label_batch, lfw_paths, actual_issame, args.lfw_batch_size, args.lfw_nrof_folds, log_dir, step, summary_writer) return model_dir
def main(args): # 主函数入口 # 从model模块中选择要使用的训练结构 network = importlib.import_module(args.model_def) # 日志路径和模型保存路径的子目录命名结构 subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S') log_dir = os.path.join(os.path.expanduser(args.logs_base_dir), subdir) if not os.path.isdir(log_dir): # Create the log directory if it doesn't exist os.makedirs(log_dir) model_dir = os.path.join(os.path.expanduser(args.models_base_dir), subdir) if not os.path.isdir(model_dir): # Create the model directory if it doesn't exist os.makedirs(model_dir) # Store some git revision info in a text file in the log directory # 当前脚本的的绝对路径,存储相关信息到log文件中 src_path,_ = os.path.split(os.path.realpath(__file__)) facenet.store_revision_info(src_path, log_dir, ' '.join(sys.argv)) # 用参数初始化numpy随机器 np.random.seed(seed=args.seed) random.seed(args.seed) # 获取训练数据 train_set = facenet.get_dataset(args.data_dir) if args.filter_filename: train_set = filter_dataset(train_set, os.path.expanduser(args.filter_filename), args.filter_percentile, args.filter_min_nrof_images_per_class) # 训练数据子类别数目 nrof_classes = len(train_set) # 打印模型和log保存路径,如果有预训练模型需要加载即加载 print('Model directory: %s' % model_dir) print('Log directory: %s' % log_dir) pretrained_model = None if args.pretrained_model: pretrained_model = os.path.expanduser(args.pretrained_model) print('Pre-trained model: %s' % pretrained_model) # 如果指定了lfw验证数据路径即打印,并且加载lfw数据配对文件及相关信息 if args.lfw_dir: print('LFW directory: %s' % args.lfw_dir) # Read the file containing the pairs used for testing pairs = lfw.read_pairs(os.path.expanduser(args.lfw_pairs)) # Get the paths for the corresponding images lfw_paths, actual_issame = lfw.get_paths(os.path.expanduser(args.lfw_dir), pairs, args.lfw_file_ext) # 新建一个图,将该图作为默认图,进入上下文管理器 with tf.Graph().as_default(): # 设置随机种子和全局 tf.set_random_seed(args.seed) global_step = tf.Variable(0, trainable=False) # Get a list of image paths and their labels # 得到训练数据的列表和相对应的标签列表 image_list, label_list = facenet.get_image_paths_and_labels(train_set) assert len(image_list)>0, 'The dataset should not be empty' # Create a queue that produces indices into the image_list and label_list # 将标签列表转化为tensor形式的列表,并获取tensor的范围 labels = ops.convert_to_tensor(label_list, dtype=tf.int32) range_size = array_ops.shape(labels)[0] # index_queue = tf.train.range_input_producer(range_size, num_epochs=None, shuffle=True, seed=None, capacity=32) # 构建训练标签队列,并设置训练中的参数 index_dequeue_op = index_queue.dequeue_many(args.batch_size*args.epoch_size, 'index_dequeue') learning_rate_placeholder = tf.placeholder(tf.float32, name='learning_rate') batch_size_placeholder = tf.placeholder(tf.int32, name='batch_size') phase_train_placeholder = tf.placeholder(tf.bool, name='phase_train') image_paths_placeholder = tf.placeholder(tf.string, shape=(None,1), name='image_paths') labels_placeholder = tf.placeholder(tf.int64, shape=(None,1), name='labels') # 构建训练数据的队列,训练数据,训练标签配对 input_queue = data_flow_ops.FIFOQueue(capacity=100000, dtypes=[tf.string, tf.int64], shapes=[(1,), (1,)], shared_name=None, name=None) enqueue_op = input_queue.enqueue_many([image_paths_placeholder, labels_placeholder], name='enqueue_op') # 数据预处理线程数 nrof_preprocess_threads = 4 images_and_labels = [] # 使用线程去并行处理数据 for _ in range(nrof_preprocess_threads): filenames, label = input_queue.dequeue() images = [] # 读取队列中的配对数据,读取训练图像和训练标签,并对数据进行预处理 for filename in tf.unstack(filenames): file_contents = tf.read_file(filename) image = tf.image.decode_png(file_contents) if args.random_rotate: image = tf.py_func(facenet.random_rotate_image, [image], tf.uint8) # 如果没开启随机截取的开关,即选择图像正中的位置进行训练 if args.random_crop: image = tf.random_crop(image, [args.image_size, args.image_size, 3]) else: image = tf.image.resize_image_with_crop_or_pad(image, args.image_size, args.image_size) if args.random_flip: image = tf.image.random_flip_left_right(image) #pylint: disable=no-member # 再一次确认图像分辨率 image.set_shape((args.image_size, args.image_size, 3)) images.append(tf.image.per_image_standardization(image)) images_and_labels.append([images, label]) # 配置训练batch的参数 image_batch, label_batch = tf.train.batch_join( images_and_labels, batch_size=batch_size_placeholder, shapes=[(args.image_size, args.image_size, 3), ()], enqueue_many=True, capacity=4 * nrof_preprocess_threads * args.batch_size, allow_smaller_final_batch=True) image_batch = tf.identity(image_batch, 'image_batch') image_batch = tf.identity(image_batch, 'input') label_batch = tf.identity(label_batch, 'label_batch') # 打印最终处理完的数据信息 print('Total number of classes: %d' % nrof_classes) print('Total number of examples: %d' % len(image_list)) print('Building training graph') # Build the inference graph # 构建TensorFlow数据流图 prelogits, _ = network.inference(image_batch, args.keep_probability, phase_train=phase_train_placeholder, bottleneck_layer_size=args.embedding_size, weight_decay=args.weight_decay) # 连接全连接层 logits = slim.fully_connected(prelogits, len(train_set), activation_fn=None, weights_initializer=tf.truncated_normal_initializer(stddev=0.1), weights_regularizer=slim.l2_regularizer(args.weight_decay), scope='Logits', reuse=False) # 对特征维度(128维)做一个L2正则化处理 embeddings = tf.nn.l2_normalize(prelogits, 1, 1e-10, name='embeddings') # Add center loss # 添加center loss if args.center_loss_factor>0.0: prelogits_center_loss, _ = facenet.center_loss(prelogits, label_batch, args.center_loss_alfa, nrof_classes) # tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES, prelogits_center_loss * args.center_loss_factor) learning_rate = tf.train.exponential_decay(learning_rate_placeholder, global_step, args.learning_rate_decay_epochs*args.epoch_size, args.learning_rate_decay_factor, staircase=True) tf.summary.scalar('learning_rate', learning_rate) # Calculate the average cross entropy loss across the batch # 计算交叉熵 cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits( labels=label_batch, logits=logits, name='cross_entropy_per_example') cross_entropy_mean = tf.reduce_mean(cross_entropy, name='cross_entropy') tf.add_to_collection('losses', cross_entropy_mean) # Calculate the total losses # 计算总的loss regularization_losses = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES) total_loss = tf.add_n([cross_entropy_mean] + regularization_losses, name='total_loss') # Build a Graph that trains the model with one batch of examples and updates the model parameters # 构建总的训练方式 train_op = facenet.train(total_loss, global_step, args.optimizer, learning_rate, args.moving_average_decay, tf.global_variables(), args.log_histograms) # Create a saver # 构建一个保存对象 saver = tf.train.Saver(tf.trainable_variables(), max_to_keep=3) # Build the summary operation based on the TF collection of Summaries. # 构建一个总的训练摘要对象 summary_op = tf.summary.merge_all() # Start running operations on the Graph. # 开始训练,配置GPU使用参数 gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=args.gpu_memory_fraction) sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options, log_device_placement=False)) sess.run(tf.global_variables_initializer()) sess.run(tf.local_variables_initializer()) summary_writer = tf.summary.FileWriter(log_dir, sess.graph) coord = tf.train.Coordinator() tf.train.start_queue_runners(coord=coord, sess=sess) with sess.as_default(): if pretrained_model: print('Restoring pretrained model: %s' % pretrained_model) saver.restore(sess, pretrained_model) # Training and validation loop # 开始训练循环 print('Running training') epoch = 0 while epoch < args.max_nrof_epochs: step = sess.run(global_step, feed_dict=None) epoch = step // args.epoch_size # Train for one epoch train(args, sess, epoch, image_list, label_list, index_dequeue_op, enqueue_op, image_paths_placeholder, labels_placeholder, learning_rate_placeholder, phase_train_placeholder, batch_size_placeholder, global_step, total_loss, train_op, summary_op, summary_writer, regularization_losses, args.learning_rate_schedule_file) # Save variables and the metagraph if it doesn't exist already save_variables_and_metagraph(sess, saver, summary_writer, model_dir, subdir, step) # Evaluate on LFW if args.lfw_dir: evaluate(sess, enqueue_op, image_paths_placeholder, labels_placeholder, phase_train_placeholder, batch_size_placeholder, embeddings, label_batch, lfw_paths, actual_issame, args.lfw_batch_size, args.lfw_nrof_folds, log_dir, step, summary_writer) sess.close() return model_dir
def main(args): logging.info('###### all args #####: %s' % args) network = importlib.import_module(args.model_def) subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S') log_dir = os.path.join(os.path.expanduser(args.logs_base_dir), subdir) if not os.path.isdir( log_dir): # Create the log directory if it doesn't exist os.makedirs(log_dir) model_dir = os.path.join(os.path.expanduser(args.models_base_dir), subdir) if not os.path.isdir( model_dir): # Create the model directory if it doesn't exist os.makedirs(model_dir) # Store some git revision info in a text file in the log directory if not args.no_store_revision_info: src_path, _ = os.path.split(os.path.realpath(__file__)) facenet.store_revision_info(src_path, log_dir, ' '.join(sys.argv)) np.random.seed(seed=args.seed) random.seed(args.seed) train_set = facenet.get_dataset(args.data_dir) if args.filter_filename: train_set = filter_dataset(train_set, args.filter_filename, args.filter_percentile, args.filter_min_nrof_images_per_class) nrof_classes = len(train_set) logging.info('Model directory: %s' % model_dir) logging.info('Log directory: %s' % log_dir) pretrained_model = None if args.pretrained_model: pretrained_model = os.path.expanduser(args.pretrained_model) logging.info('Pre-trained model: %s' % pretrained_model) if args.lfw_dir: logging.info('LFW directory: %s' % args.lfw_dir) # Read the file containing the pairs used for testing pairs = lfw.read_pairs(os.path.expanduser(args.lfw_pairs)) # Get the paths for the corresponding images lfw_paths, actual_issame = lfw.get_paths( os.path.expanduser(args.lfw_dir), pairs, args.lfw_file_ext) with tf.Graph().as_default(): tf.set_random_seed(args.seed) global_step = tf.Variable(0, trainable=False) # Get a list of image paths and their labels image_list, label_list = facenet.get_image_paths_and_labels(train_set) assert len(image_list) > 0, 'The dataset should not be empty' logging.info('image_list size %d, label_list size %d' % (len(image_list), len(label_list))) # Create a queue that produces indices into the image_list and label_list labels = ops.convert_to_tensor(label_list, dtype=tf.int32) range_size = array_ops.shape(labels)[0] logging.info('labels shape %s, range size: %s' % (labels.shape, str(range_size))) index_queue = tf.train.range_input_producer(range_size, num_epochs=None, shuffle=True, seed=None, capacity=32) logging.info('batch size:%d, epoch size:%d' % (args.batch_size, args.epoch_size)) index_dequeue_op = index_queue.dequeue_many( args.batch_size * args.epoch_size, 'index_dequeue') learning_rate_placeholder = tf.placeholder(tf.float32, name='learning_rate') batch_size_placeholder = tf.placeholder(tf.int32, name='batch_size') phase_train_placeholder = tf.placeholder(tf.bool, name='phase_train') image_paths_placeholder = tf.placeholder(tf.string, shape=(None, 1), name='image_paths') labels_placeholder = tf.placeholder(tf.int64, shape=(None, 1), name='labels') input_queue = data_flow_ops.FIFOQueue(capacity=100000, dtypes=[tf.string, tf.int64], shapes=[(1, ), (1, )], shared_name=None, name=None) enqueue_op = input_queue.enqueue_many( [image_paths_placeholder, labels_placeholder], name='enqueue_op') nrof_preprocess_threads = 4 images_and_labels = [] for _ in range(nrof_preprocess_threads): filenames, label = input_queue.dequeue() logging.info('# filenames len:%s' % filenames.shape) images = [] for filename in tf.unstack(filenames): # logging.info('#file:%s' % filename) file_contents = tf.read_file(filename) image = tf.image.decode_jpeg(file_contents) # logging.info('#image shape:%s' % image.shape) # if args.random_rotate: # image = tf.py_func(facenet.random_rotate_image, [image], tf.uint8) # # if args.random_crop: # # image = tf.random_crop(image, [args.image_size, args.image_size, 3]) # else: # image = tf.image.resize_image_with_crop_or_pad(image, args.image_size, args.image_size) # if args.random_flip: # image = tf.image.random_flip_left_right(image) image = porcessor.preprocess_image(image, args.image_size, args.image_size, is_training=True) #pylint: disable=no-member image.set_shape((args.image_size, args.image_size, 3)) images.append(tf.image.per_image_standardization(image)) images_and_labels.append([images, label]) image_batch, label_batch = tf.train.batch_join( images_and_labels, batch_size=batch_size_placeholder, shapes=[(args.image_size, args.image_size, 3), ()], enqueue_many=True, capacity=4 * nrof_preprocess_threads * args.batch_size, allow_smaller_final_batch=True) image_batch = tf.identity(image_batch, 'image_batch') image_batch = tf.identity(image_batch, 'input') label_batch = tf.identity(label_batch, 'label_batch') logging.info('Total number of classes: %d' % nrof_classes) logging.info('Total number of examples: %d' % len(image_list)) logging.info('Building training graph') batch_norm_params = { # Decay for the moving averages 'decay': 0.995, # epsilon to prevent 0s in variance 'epsilon': 0.001, # force in-place updates of mean and variance estimates 'updates_collections': None, # Moving averages ends up in the trainable variables collection 'variables_collections': [tf.GraphKeys.TRAINABLE_VARIABLES], # Only update statistics during training mode 'is_training': phase_train_placeholder } # Build the inference graph # with tf.device('/GPU:0'): prelogits, _ = network.inference(image_batch, args.keep_probability, phase_train=phase_train_placeholder, weight_decay=args.weight_decay) bottleneck = slim.fully_connected( prelogits, args.embedding_size, activation_fn=None, weights_initializer=tf.truncated_normal_initializer(stddev=0.1), weights_regularizer=slim.l2_regularizer(args.weight_decay), normalizer_fn=slim.batch_norm, normalizer_params=batch_norm_params, scope='Bottleneck', reuse=False) logits = slim.fully_connected( bottleneck, len(train_set), activation_fn=None, weights_initializer=tf.truncated_normal_initializer(stddev=0.1), weights_regularizer=slim.l2_regularizer(args.weight_decay), scope='Logits', reuse=False) embeddings = tf.nn.l2_normalize(bottleneck, 1, 1e-10, name='embeddings') # Add center loss if args.center_loss_factor > 0.0: prelogits_center_loss, _ = facenet.center_loss( prelogits, label_batch, args.center_loss_alfa, nrof_classes) tf.add_to_collection( tf.GraphKeys.REGULARIZATION_LOSSES, prelogits_center_loss * args.center_loss_factor) learning_rate = tf.train.exponential_decay( learning_rate_placeholder, global_step, args.learning_rate_decay_epochs * args.epoch_size, args.learning_rate_decay_factor, staircase=True) tf.summary.scalar('learning_rate', learning_rate) # Calculate the average cross entropy loss across the batch cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits( labels=label_batch, logits=logits, name='cross_entropy_per_example') cross_entropy_mean = tf.reduce_mean(cross_entropy, name='cross_entropy') tf.add_to_collection('losses', cross_entropy_mean) # Calculate the total losses regularization_losses = tf.get_collection( tf.GraphKeys.REGULARIZATION_LOSSES) total_loss = tf.add_n([cross_entropy_mean] + regularization_losses, name='total_loss') # Build a Graph that trains the model with one batch of examples and updates the model parameters train_op = facenet.train(total_loss, global_step, args.optimizer, learning_rate, args.moving_average_decay, tf.global_variables(), args.log_histograms) # Create a saver saver = tf.train.Saver(tf.trainable_variables(), max_to_keep=10) # Build the summary operation based on the TF collection of Summaries. summary_op = tf.summary.merge_all() # Start running operations on the Graph. gpu_options = tf.GPUOptions( per_process_gpu_memory_fraction=args.gpu_memory_fraction) sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options, log_device_placement=False)) sess.run(tf.global_variables_initializer()) sess.run(tf.local_variables_initializer()) summary_writer = tf.summary.FileWriter(log_dir, sess.graph) coord = tf.train.Coordinator() tf.train.start_queue_runners(coord=coord, sess=sess) with sess.as_default(), tf.device('/gpu:1'): if pretrained_model: logging.info('Restoring pretrained model: %s' % pretrained_model) saver.restore(sess, pretrained_model) # Training and validation loop logging.info('Running training') epoch = 0 while epoch < args.max_nrof_epochs: step = sess.run(global_step, feed_dict=None) epoch = step // args.epoch_size # Train for one epoch train(args, sess, epoch, image_list, label_list, index_dequeue_op, enqueue_op, image_paths_placeholder, labels_placeholder, learning_rate_placeholder, phase_train_placeholder, batch_size_placeholder, global_step, total_loss, train_op, summary_op, summary_writer, regularization_losses, args.learning_rate_schedule_file) # Save variables and the metagraph if it doesn't exist already save_variables_and_metagraph(sess, saver, summary_writer, model_dir, subdir, step) # Evaluate on LFW if args.lfw_dir: evaluate(sess, enqueue_op, image_paths_placeholder, labels_placeholder, phase_train_placeholder, batch_size_placeholder, embeddings, label_batch, lfw_paths, actual_issame, args.lfw_batch_size, args.lfw_nrof_folds, log_dir, step, summary_writer) sess.close() return model_dir
def main(args): network = importlib.import_module(args.model_def) subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S')#以时间方式命名一个子路径 log_dir = os.path.join(os.path.expanduser(args.logs_base_dir), subdir)#最终的日志的地址 if not os.path.isdir(log_dir): # Create the log directory if it doesn't exist os.makedirs(log_dir)#如果路径不存在就建立 model_dir = os.path.join(os.path.expanduser(args.models_base_dir), subdir)#模型的路径 if not os.path.isdir(model_dir): # Create the model directory if it doesn't exist os.makedirs(model_dir) # Write arguments to a text file facenet.write_arguments_to_file(args, os.path.join(log_dir, 'arguments.txt'))#将argument的具体信息记录在log目录下的argument.txt文件中 # Store some git revision info in a text file in the log directory src_path,_ = os.path.split(os.path.realpath(__file__)) facenet.store_revision_info(src_path, log_dir, ' '.join(sys.argv)) np.random.seed(seed=args.seed)#使用seed可以保证随机数部分每次出现的结果都一样 random.seed(args.seed) train_set = facenet.get_dataset(args.data_dir) if args.filter_filename: train_set = filter_dataset(train_set, os.path.expanduser(args.filter_filename), args.filter_percentile, args.filter_min_nrof_images_per_class) nrof_classes = len(train_set)#nrof_classes为train_set的类别数 print('Model directory: %s' % model_dir)#打印出来,model和log的地址 print('Log directory: %s' % log_dir) pretrained_model = None if args.pretrained_model: pretrained_model = os.path.expanduser(args.pretrained_model) print('Pre-trained model: %s' % pretrained_model)#如果有提前训练的model就在载入(?)这里没有写载入的代码,但是大概应该是需要载入 if args.lfw_dir: print('LFW directory: %s' % args.lfw_dir)#打印LFW数据集的地址 # Read the file containing the pairs used for testing pairs = lfw.read_pairs(os.path.expanduser(args.lfw_pairs)) # Get the paths for the corresponding images lfw_paths, actual_issame = lfw.get_paths(os.path.expanduser(args.lfw_dir), pairs, args.lfw_file_ext)#获取到lfw数据集的地址,issame是什么还是不知道 with tf.Graph().as_default():#开始tensorflow的会话 tf.set_random_seed(args.seed) global_step = tf.Variable(0, trainable=False) # Get a list of image paths and their labels image_list, label_list = facenet.get_image_paths_and_labels(train_set)#图片和标签的list assert len(image_list)>0, 'The dataset should not be empty' # 创建一个队列实现将label和picture输入网络,因为数据太大需要使用到队列 labels = ops.convert_to_tensor(label_list, dtype=tf.int32) range_size = array_ops.shape(labels)[0]#label的个数 index_queue = tf.train.range_input_producer(range_size, num_epochs=None, shuffle=True, seed=None, capacity=32)#相当于一个一个往外出 index_dequeue_op = index_queue.dequeue_many(args.batch_size*args.epoch_size, 'index_dequeue') learning_rate_placeholder = tf.placeholder(tf.float32, name='learning_rate') batch_size_placeholder = tf.placeholder(tf.int32, name='batch_size') phase_train_placeholder = tf.placeholder(tf.bool, name='phase_train') image_paths_placeholder = tf.placeholder(tf.string, shape=(None,1), name='image_paths') labels_placeholder = tf.placeholder(tf.int64, shape=(None,1), name='labels') input_queue = data_flow_ops.FIFOQueue(capacity=100000, dtypes=[tf.string, tf.int64], shapes=[(1,), (1,)], shared_name=None, name=None) enqueue_op = input_queue.enqueue_many([image_paths_placeholder, labels_placeholder], name='enqueue_op') nrof_preprocess_threads = 4 images_and_labels = [] for _ in range(nrof_preprocess_threads): filenames, label = input_queue.dequeue() images = [] for filename in tf.unstack(filenames): file_contents = tf.read_file(filename) image = tf.image.decode_image(file_contents, channels=3) if args.random_rotate: image = tf.py_func(facenet.random_rotate_image, [image], tf.uint8) if args.random_crop: image = tf.random_crop(image, [args.image_size, args.image_size, 3]) else: image = tf.image.resize_image_with_crop_or_pad(image, args.image_size, args.image_size) if args.random_flip: image = tf.image.random_flip_left_right(image) #pylint: disable=no-member image.set_shape((args.image_size, args.image_size, 3)) images.append(tf.image.per_image_standardization(image)) images_and_labels.append([images, label]) image_batch, label_batch = tf.train.batch_join( images_and_labels, batch_size=batch_size_placeholder, shapes=[(args.image_size, args.image_size, 3), ()], enqueue_many=True, capacity=4 * nrof_preprocess_threads * args.batch_size, allow_smaller_final_batch=True) image_batch = tf.identity(image_batch, 'image_batch') image_batch = tf.identity(image_batch, 'input') label_batch = tf.identity(label_batch, 'label_batch') print('Total number of classes: %d' % nrof_classes) print('Total number of examples: %d' % len(image_list)) print('Building training graph') # Build the inference graph prelogits, _ = network.inference(image_batch, args.keep_probability, phase_train=phase_train_placeholder, bottleneck_layer_size=args.embedding_size, weight_decay=args.weight_decay)#通过googlenet网络中之后输出的结果,详细见models.inception_v1的文件,结果就是构建了网络 logits = slim.fully_connected(prelogits, len(train_set), activation_fn=None, weights_initializer=tf.truncated_normal_initializer(stddev=0.1), weights_regularizer=slim.l2_regularizer(args.weight_decay), scope='Logits', reuse=False)#在全连接之后初始化参数 embeddings = tf.nn.l2_normalize(prelogits, 1, 1e-10, name='embeddings')#进行正则化 # Add center loss if args.center_loss_factor>0.0: prelogits_center_loss, _ = facenet.center_loss(prelogits, label_batch, args.center_loss_alfa, nrof_classes) tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES, prelogits_center_loss * args.center_loss_factor)#将引入center loss factor 之后的loss引入到纳入到graph中的正则化loss类别中 learning_rate = tf.train.exponential_decay(learning_rate_placeholder, global_step, args.learning_rate_decay_epochs*args.epoch_size, args.learning_rate_decay_factor, staircase=True)#设定学习率的初始值和变化方式 tf.summary.scalar('learning_rate', learning_rate)#可视化中离散的学习率的图表 # Calculate the average cross entropy loss across the batch cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits( labels=label_batch, logits=logits, name='cross_entropy_per_example')#每个训练结果的交叉熵损失 cross_entropy_mean = tf.reduce_mean(cross_entropy, name='cross_entropy')#得到所有的交叉熵损失的平均值 tf.add_to_collection('losses', cross_entropy_mean)#将平均交叉熵的值纳入到损失类别中 # Calculate the total losses regularization_losses = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES) total_loss = tf.add_n([cross_entropy_mean] + regularization_losses, name='total_loss')#最后的loss由center_loss和cross_entropy两部分组成 # Build a Graph that trains the model with one batch of examples and updates the model parameters train_op = facenet.train(total_loss, global_step, args.optimizer, learning_rate, args.moving_average_decay, tf.global_variables(), args.log_histograms)#训练的设定 # Create a saver saver = tf.train.Saver(tf.trainable_variables(), max_to_keep=3)#保存图表到log中 # Build the summary operation based on the TF collection of Summaries. summary_op = tf.summary.merge_all()#tensorboard中显示所有信息 # Start running operations on the Graph. gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=args.gpu_memory_fraction) sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options, log_device_placement=False))#设置每个gpu分配多少的内存用于该process sess.run(tf.global_variables_initializer()) sess.run(tf.local_variables_initializer())#初始化所有的variable summary_writer = tf.summary.FileWriter(log_dir, sess.graph)#将graph保存到log的路径下面 coord = tf.train.Coordinator()#创立一个线程管理器 tf.train.start_queue_runners(coord=coord, sess=sess) with sess.as_default(): if pretrained_model: print('Restoring pretrained model: %s' % pretrained_model) saver.restore(sess, pretrained_model) # Training and validation loop print('Running training') epoch = 0 while epoch < args.max_nrof_epochs:#训练的轮次 step = sess.run(global_step, feed_dict=None) epoch = step // args.epoch_size # Train for one epoch train(args, sess, epoch, image_list, label_list, index_dequeue_op, enqueue_op, image_paths_placeholder, labels_placeholder, learning_rate_placeholder, phase_train_placeholder, batch_size_placeholder, global_step, total_loss, train_op, summary_op, summary_writer, regularization_losses, args.learning_rate_schedule_file) # Save variables and the metagraph if it doesn't exist already save_variables_and_metagraph(sess, saver, summary_writer, model_dir, subdir, step) # Evaluate on LFW if args.lfw_dir:#在lfw数据集中进行验证 evaluate(sess, enqueue_op, image_paths_placeholder, labels_placeholder, phase_train_placeholder, batch_size_placeholder, embeddings, label_batch, lfw_paths, actual_issame, args.lfw_batch_size, args.lfw_nrof_folds, log_dir, step, summary_writer) return model_dir
def main(args): # 动态import python模块, 这里指的是外部参数指定的网络结构 network = importlib.import_module(args.model_def) subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S') # os.path.expanduser跨平台支持替换路径中的user路径~ log_dir = os.path.join(os.path.expanduser(args.logs_base_dir), subdir) if not os.path.isdir(log_dir): # Create the log directory if it doesn't exist os.makedirs(log_dir) model_dir = os.path.join(os.path.expanduser(args.models_base_dir), subdir) if not os.path.isdir(model_dir): # Create the model directory if it doesn't exist os.makedirs(model_dir) # Write arguments to a text file facenet.write_arguments_to_file(args, os.path.join(log_dir, 'arguments.txt')) # Store some git revision info in a text file in the log directory src_path, _ = os.path.split(os.path.realpath(__file__)) facenet.store_revision_info(src_path, log_dir, ' '.join(sys.argv)) np.random.seed(seed=args.seed) random.seed(args.seed) # args.data_dir can contain more datasets, separated by comma # TODO: no logic for name conflict? data_dirs = args.data_dir.split(",") train_set = [] for data_dir in data_dirs: if len(data_dir) > 0: train_set.extend(facenet.get_dataset(data_dir)) if args.filter_filename: train_set = filter_dataset(train_set, os.path.expanduser(args.filter_filename), args.filter_percentile, args.filter_min_nrof_images_per_class) nrof_classes = len(train_set) print('Model directory: %s' % model_dir) print('Log directory: %s' % log_dir) pretrained_model = None if args.pretrained_model: pretrained_model = os.path.expanduser(args.pretrained_model) print('Pre-trained model: %s' % pretrained_model) continue_ckpt_dir = None if args.continue_ckpt_dir: continue_ckpt_dir = os.path.expanduser(args.continue_ckpt_dir) print('Continue training from the checkpoint: %s' % continue_ckpt_dir) snapshot_at_step = None if args.snapshot_at_step: snapshot_at_step = int(args.snapshot_at_step) print('Will take a snapshot checkpoint at step', snapshot_at_step) nrof_preprocess_threads = 4 if args.nrof_preprocess_threads: nrof_preprocess_threads = int(args.nrof_preprocess_threads) print('Number of preprocess threads', nrof_preprocess_threads) if args.lfw_dir: print('LFW directory: %s' % args.lfw_dir) # Read the file containing the pairs used for testing pairs = lfw.read_pairs(os.path.expanduser(args.lfw_pairs)) # Get the paths for the corresponding images lfw_paths, actual_issame = lfw.get_paths(os.path.expanduser(args.lfw_dir), pairs, args.lfw_file_ext) with tf.Graph().as_default(): tf.set_random_seed(args.seed) global_step = tf.Variable(0, trainable=False) # Get a list of image paths and their labels image_list, label_list = facenet.get_image_paths_and_labels(train_set) assert len(image_list) > 0, 'The dataset should not be empty' # Create a queue that produces indices into the image_list and label_list # https://www.tensorflow.org/api_guides/python/threading_and_queues # This function converts Python objects of various types to Tensor objects. # It accepts Tensor objects, numpy arrays, Python lists, and Python scalars. labels = ops.convert_to_tensor(label_list, dtype=tf.int32) # This operation returns a 1-D integer tensor representing the shape of input. range_size = array_ops.shape(labels)[0] # Produces the integers from 0 to limit-1 in a queue. index_queue = tf.train.range_input_producer(range_size, num_epochs=None, shuffle=True, seed=None, capacity=32) index_dequeue_op = index_queue.dequeue_many(args.batch_size * args.epoch_size, 'index_dequeue') learning_rate_placeholder = tf.placeholder(tf.float32, name='learning_rate') batch_size_placeholder = tf.placeholder(tf.int32, name='batch_size') phase_train_placeholder = tf.placeholder(tf.bool, name='phase_train') image_paths_placeholder = tf.placeholder(tf.string, shape=(None, 1), name='image_paths') labels_placeholder = tf.placeholder(tf.int64, shape=(None, 1), name='labels') # Creates a queue that dequeues elements in a first-in first-out order. input_queue = data_flow_ops.FIFOQueue(capacity=100000, dtypes=[tf.string, tf.int64], shapes=[(1,), (1,)], shared_name=None, name=None) enqueue_op = input_queue.enqueue_many([image_paths_placeholder, labels_placeholder], name='enqueue_op') # 读取图片文件, 将图片转换成tensor并且做ensembling处理, 结果存入images_and_labels数组 images_and_labels = [] for _ in range(nrof_preprocess_threads): filenames, label = input_queue.dequeue() images = [] # Unpacks the given dimension of a rank-R tensor into rank-(R-1) tensors. for filename in tf.unstack(filenames): file_contents = tf.read_file(filename) # Detects whether an image is a GIF, JPEG, or PNG, and performs the appropriate operation # to convert the input bytes string into a Tensor of type uint8. # Note: decode_gif returns a 4-D array [num_frames, height, width, 3], # as opposed to decode_jpeg and decode_png, which return 3-D arrays [height, width, num_channels]. image = tf.image.decode_image(file_contents, channels=3) # 对训练图片做ensembling # https://www.tensorflow.org/api_docs/python/tf/image # https://www.tensorflow.org/api_docs/python/tf/contrib/image if args.random_rotate: image = tf.py_func(facenet.random_rotate_image, [image], tf.uint8) if args.random_crop: # 训练数据的图片(182)比参数传进来的大小(160)略大, 不做缩放而是直接随机切成160的 image = tf.random_crop(image, [args.image_size, args.image_size, 3]) else: image = tf.image.resize_image_with_crop_or_pad(image, args.image_size, args.image_size) if args.random_flip: image = tf.image.random_flip_left_right(image) if args.random_brightness: image = tf.image.random_brightness(image, max_delta=0.2) # pylint: disable=no-member image.set_shape((args.image_size, args.image_size, 3)) images.append(tf.image.per_image_standardization(image)) images_and_labels.append([images, label]) # Runs a list of tensors to fill a queue to create batches of examples. image_batch, label_batch = tf.train.batch_join( images_and_labels, batch_size=batch_size_placeholder, shapes=[(args.image_size, args.image_size, 3), ()], enqueue_many=True, capacity=4 * nrof_preprocess_threads * args.batch_size, allow_smaller_final_batch=True) # https://stackoverflow.com/questions/34877523/in-tensorflow-what-is-tf-identity-used-for image_batch = tf.identity(image_batch, 'image_batch') image_batch = tf.identity(image_batch, 'input') label_batch = tf.identity(label_batch, 'label_batch') print('Total number of classes: %d' % nrof_classes) print('Total number of examples: %d' % len(image_list)) print('Building training graph') # Build the inference graph prelogits, _ = network.inference(image_batch, args.keep_probability, phase_train=phase_train_placeholder, bottleneck_layer_size=args.embedding_size, weight_decay=args.weight_decay) logits = slim.fully_connected(prelogits, len(train_set), activation_fn=None, weights_initializer=tf.truncated_normal_initializer(stddev=0.1), weights_regularizer=slim.l2_regularizer(args.weight_decay), scope='Logits', reuse=False) # Normalizes along dimension dim using an L2 norm. # For a 1-D tensor with dim = 0, computes output = x / sqrt(max(sum(x**2), epsilon)) # For x with more dimensions, independently normalizes each 1-D slice along dimension dim. # 人脸图片对应的最终编码, 也是算法的核心输出 embeddings = tf.nn.l2_normalize(prelogits, 1, 1e-10, name='embeddings') # Add center loss if args.center_loss_factor > 0.0: prelogits_center_loss, _ = facenet.center_loss(prelogits, label_batch, args.center_loss_alfa, nrof_classes) # Wrapper for Graph.add_to_collection() using the default graph. # Stores value in the collection with the given name. # Note that collections are not sets, so it is possible to add a value to a collection several times. tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES, # args.center_loss_factor center loss论文里的lambda prelogits_center_loss * args.center_loss_factor) learning_rate = tf.train.exponential_decay(learning_rate_placeholder, global_step, args.learning_rate_decay_epochs * args.epoch_size, args.learning_rate_decay_factor, staircase=True) tf.summary.scalar('learning_rate', learning_rate) # Calculate the average cross entropy loss across the batch cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits( labels=label_batch, logits=logits, name='cross_entropy_per_example') cross_entropy_mean = tf.reduce_mean(cross_entropy, name='cross_entropy') tf.add_to_collection('losses', cross_entropy_mean) # Calculate the total losses regularization_losses = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES) # Adds all input tensors element-wise. total_loss = tf.add_n([cross_entropy_mean] + regularization_losses, name='total_loss') # Build a Graph that trains the model with one batch of examples and updates the model parameters train_op = facenet.train(total_loss, global_step, args.optimizer, learning_rate, args.moving_average_decay, tf.global_variables(), args.log_histograms) # Create a saver saver = tf.train.Saver(tf.trainable_variables(), max_to_keep=3) # Build the summary operation based on the TF collection of Summaries. summary_op = tf.summary.merge_all() # Start running operations on the Graph. gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=args.gpu_memory_fraction) sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options, log_device_placement=False)) sess.run(tf.global_variables_initializer()) sess.run(tf.local_variables_initializer()) summary_writer = tf.summary.FileWriter(log_dir, sess.graph) coord = tf.train.Coordinator() tf.train.start_queue_runners(coord=coord, sess=sess) with sess.as_default(): if pretrained_model: print('Restoring pretrained model: %s' % pretrained_model) saver.restore(sess, pretrained_model) elif continue_ckpt_dir: files = os.listdir(continue_ckpt_dir) meta_files = [s for s in files if s.endswith('.meta')] if len(meta_files) == 0: raise ValueError('No meta file found in %s' % continue_ckpt_dir) elif len(meta_files) > 1: raise ValueError( 'There should not be more than one meta file in %s' % continue_ckpt_dir) saver = tf.train.import_meta_graph(continue_ckpt_dir + "/" + meta_files[0]) latest_checkpoint = tf.train.latest_checkpoint(continue_ckpt_dir) print('Restoring checkpoint: %s' % latest_checkpoint) saver.restore(sess, latest_checkpoint) # TODO: don't know why global_step is not saved. get it from the filename last_step = int(os.path.basename(latest_checkpoint).split('-')[-1]) print('Checkpoint restored, last step is ', str(last_step)) sess.run(global_step.assign(last_step)) # Training and validation loop print('Running training') epoch = 0 while epoch < args.max_nrof_epochs: step = sess.run(global_step, feed_dict=None) epoch_size = args.epoch_size epoch = step // epoch_size if args.learning_rate > 0.0: lr = args.learning_rate else: # Read the schedule file each epoch, you can change the file content during running lr = facenet.get_learning_rate_from_file(args.learning_rate_schedule_file, epoch) # Special value means stop if lr == 0.0: break # Train for one epoch train(args, sess, epoch, image_list, label_list, index_dequeue_op, enqueue_op, image_paths_placeholder, labels_placeholder, learning_rate_placeholder, phase_train_placeholder, batch_size_placeholder, global_step, total_loss, train_op, summary_op, summary_writer, regularization_losses, lr, snapshot_at_step, saver, model_dir, subdir ) # Save variables and the metagraph if it doesn't exist already (step in filename is the next step after restore) save_variables_and_metagraph(sess, saver, summary_writer, model_dir, subdir, step + epoch_size) # Evaluate on LFW if args.lfw_dir and args.lfw_epoch_interval > 0: if epoch % args.lfw_epoch_interval == 0: evaluate(sess, enqueue_op, image_paths_placeholder, labels_placeholder, phase_train_placeholder, batch_size_placeholder, embeddings, label_batch, lfw_paths, actual_issame, args.lfw_batch_size, args.lfw_nrof_folds, log_dir, step, summary_writer) # Print current time print("Current date time:", datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S')) return model_dir
def testCenterLoss(self): batch_size = 16 nrof_features = 2 nrof_classes = 16 alfa = 0.5 with tf.Graph().as_default(): features = tf.placeholder(tf.float32, shape=(batch_size, nrof_features), name='features') labels = tf.placeholder(tf.int32, shape=(batch_size, ), name='labels') # Define center loss #loss, update_centers, one_hot, delta1, delta2, centers_delta = facenet.center_loss(features, labels, alfa, nrof_classes) loss = facenet.center_loss(features, labels, alfa, nrof_classes) #loss = facenet.center_inter_loss_tf(features, labels, alfa, nrof_classes) label_to_center = np.array([[-3, -3], [-3, -1], [-3, 1], [-3, 3], [-1, -3], [-1, -1], [-1, 1], [-1, 3], [1, -3], [1, -1], [1, 1], [1, 3], [3, -3], [3, -1], [3, 1], [3, 3]]) sess = tf.Session() with sess.as_default(): sess.run(tf.global_variables_initializer()) np.random.seed(seed=666) for i in range(0, 100): # Create array of random labels lbls = np.random.randint(low=0, high=nrof_classes, size=(batch_size, )) feats = create_features(label_to_center, batch_size, nrof_features, lbls) #center_loss_, centers_, diff_, centers_batch_ = sess.run([center_loss, centers, diff, centers_batch], feed_dict={features:feats, labels:lbls}) #loss_, update_centers_, one_hot_, delta1_, delta2_, centers_delta_ = sess.run([loss, update_centers, one_hot, delta1, delta2, centers_delta], feed_dict={features: feats, labels: lbls}) #loss_, centers_, label_, centers_batch_, diff_, centers_cts_, centers_cts_batch_, diff_mean_, center_cts_clear_ = sess.run(loss, feed_dict={features:feats, labels:lbls}) #loss_, centers_, diff_, centers_cts_batch_ = sess.run(loss, feed_dict={features:feats, labels:lbls}) #loss_, centers_, label_, centers_batch, diff_, centers_cts_, centers_cts_batch_, diff_mean_,center_cts_clear_, centers_cts_batch_reshape = sess.run(loss, feed_dict={features:feats, labels:lbls}) loss_, centers_ = sess.run(loss, feed_dict={ features: feats, labels: lbls }) #loss_, centers_, centers_1D, centers_mtx, centers_3D, features_3D, dist_inter_centers, dist_inter_centers_sum_dim, dist_inter_centers_sum_all, dist_inter_centers_sum, loss_inter_centers, loss_center = sess.run(loss, feed_dict={features:feats, labels:lbls}) ##mzh figure = plt.figure() x = feats[:, 0] y = feats[:, 1] z = lbls plt.scatter(x, y, c=z, s=100, cmap=plt.cm.cool, edgecolors='None', alpha=0.75) x = centers_[:, 0] y = centers_[:, 1] z = lbls plt.scatter(x, y, c=z, s=100, marker='x', cmap=plt.cm.cool, edgecolors='None', alpha=0.75) plt.colorbar() plt.text(0, -3, 'loss: %f, iter: %d' % (loss_, i)) plt.show() #raw_input("Press Enter to continue...") plt.close() # After a large number of updates the estimated centers should be close to the true ones np.testing.assert_almost_equal( centers_, label_to_center, decimal=5, err_msg='Incorrect estimated centers') np.testing.assert_almost_equal(loss, 0.0, decimal=5, err_msg='Incorrect center loss')
def main(args): network = importlib.import_module(args.model_def) subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S') log_dir = os.path.join(os.path.expanduser(args.logs_base_dir), subdir) if not os.path.isdir(log_dir): # Create the log directory if it doesn't exist os.makedirs(log_dir) model_dir = os.path.join(os.path.expanduser(args.models_base_dir), subdir) if not os.path.isdir(model_dir): # Create the model directory if it doesn't exist os.makedirs(model_dir) # Store some git revision info in a text file in the log directory src_path,_ = os.path.split(os.path.realpath(__file__)) facenet.store_revision_info(src_path, log_dir, ' '.join(sys.argv)) np.random.seed(seed=args.seed) random.seed(args.seed) train_set = facenet.get_dataset(args.data_dir) if args.filter_filename: train_set = filter_dataset(train_set, os.path.expanduser(args.filter_filename), args.filter_percentile, args.filter_min_nrof_images_per_class) nrof_classes = len(train_set) print('Model directory: %s' % model_dir) print('Log directory: %s' % log_dir) pretrained_model = None if args.pretrained_model: pretrained_model = os.path.expanduser(args.pretrained_model) print('Pre-trained model: %s' % pretrained_model) if args.lfw_dir: print('LFW directory: %s' % args.lfw_dir) # Read the file containing the pairs used for testing pairs = lfw.read_pairs(os.path.expanduser(args.lfw_pairs)) # Get the paths for the corresponding images lfw_paths, actual_issame = lfw.get_paths(os.path.expanduser(args.lfw_dir), pairs, args.lfw_file_ext) with tf.Graph().as_default(): tf.set_random_seed(args.seed) global_step = tf.Variable(0, trainable=False) # Get a list of image paths and their labels image_list, label_list = facenet.get_image_paths_and_labels(train_set) assert len(image_list)>0, 'The dataset should not be empty' # Create a queue that produces indices into the image_list and label_list labels = ops.convert_to_tensor(label_list, dtype=tf.int32) range_size = array_ops.shape(labels)[0] index_queue = tf.train.range_input_producer(range_size, num_epochs=None, shuffle=True, seed=None, capacity=32) index_dequeue_op = index_queue.dequeue_many(args.batch_size*args.epoch_size, 'index_dequeue') learning_rate_placeholder = tf.placeholder(tf.float32, name='learning_rate') batch_size_placeholder = tf.placeholder(tf.int32, name='batch_size') phase_train_placeholder = tf.placeholder(tf.bool, name='phase_train') image_paths_placeholder = tf.placeholder(tf.string, shape=(None,1), name='image_paths') labels_placeholder = tf.placeholder(tf.int64, shape=(None,1), name='labels') input_queue = data_flow_ops.FIFOQueue(capacity=100000, dtypes=[tf.string, tf.int64], shapes=[(1,), (1,)], shared_name=None, name=None) enqueue_op = input_queue.enqueue_many([image_paths_placeholder, labels_placeholder], name='enqueue_op') nrof_preprocess_threads = 4 images_and_labels = [] for _ in range(nrof_preprocess_threads): filenames, label = input_queue.dequeue() images = [] for filename in tf.unstack(filenames): file_contents = tf.read_file(filename) image = tf.image.decode_png(file_contents) if args.random_rotate: image = tf.py_func(facenet.random_rotate_image, [image], tf.uint8) if args.random_crop: image = tf.random_crop(image, [args.image_size, args.image_size, 3]) else: image = tf.image.resize_image_with_crop_or_pad(image, args.image_size, args.image_size) if args.random_flip: image = tf.image.random_flip_left_right(image) #pylint: disable=no-member image.set_shape((args.image_size, args.image_size, 3)) images.append(tf.image.per_image_standardization(image)) images_and_labels.append([images, label]) image_batch, label_batch = tf.train.batch_join( images_and_labels, batch_size=batch_size_placeholder, shapes=[(args.image_size, args.image_size, 3), ()], enqueue_many=True, capacity=4 * nrof_preprocess_threads * args.batch_size, allow_smaller_final_batch=True) image_batch = tf.identity(image_batch, 'image_batch') image_batch = tf.identity(image_batch, 'input') label_batch = tf.identity(label_batch, 'label_batch') print('Total number of classes: %d' % nrof_classes) print('Total number of examples: %d' % len(image_list)) print('Building training graph') # Build the inference graph prelogits, _ = network.inference(image_batch, args.keep_probability, phase_train=phase_train_placeholder, bottleneck_layer_size=args.embedding_size, weight_decay=args.weight_decay) logits = slim.fully_connected(prelogits, len(train_set), activation_fn=None, weights_initializer=tf.truncated_normal_initializer(stddev=0.1), weights_regularizer=slim.l2_regularizer(args.weight_decay), scope='Logits', reuse=False) embeddings = tf.nn.l2_normalize(prelogits, 1, 1e-10, name='embeddings') # Add center loss if args.center_loss_factor>0.0: prelogits_center_loss, _ = facenet.center_loss(prelogits, label_batch, args.center_loss_alfa, nrof_classes) tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES, prelogits_center_loss * args.center_loss_factor) learning_rate = tf.train.exponential_decay(learning_rate_placeholder, global_step, args.learning_rate_decay_epochs*args.epoch_size, args.learning_rate_decay_factor, staircase=True) tf.summary.scalar('learning_rate', learning_rate) # Calculate the average cross entropy loss across the batch cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits( labels=label_batch, logits=logits, name='cross_entropy_per_example') cross_entropy_mean = tf.reduce_mean(cross_entropy, name='cross_entropy') tf.add_to_collection('losses', cross_entropy_mean) # Calculate the total losses regularization_losses = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES) total_loss = tf.add_n([cross_entropy_mean] + regularization_losses, name='total_loss') # Build a Graph that trains the model with one batch of examples and updates the model parameters train_op = facenet.train(total_loss, global_step, args.optimizer, learning_rate, args.moving_average_decay, tf.global_variables(), args.log_histograms) # Create a saver saver = tf.train.Saver(tf.trainable_variables(), max_to_keep=3) # Build the summary operation based on the TF collection of Summaries. summary_op = tf.summary.merge_all() # Start running operations on the Graph. gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=args.gpu_memory_fraction) sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options, log_device_placement=False)) sess.run(tf.global_variables_initializer()) sess.run(tf.local_variables_initializer()) summary_writer = tf.summary.FileWriter(log_dir, sess.graph) coord = tf.train.Coordinator() tf.train.start_queue_runners(coord=coord, sess=sess) with sess.as_default(): if pretrained_model: print('Restoring pretrained model: %s' % pretrained_model) saver.restore(sess, pretrained_model) # Training and validation loop print('Running training') epoch = 0 while epoch < args.max_nrof_epochs: step = sess.run(global_step, feed_dict=None) epoch = step // args.epoch_size # Train for one epoch train(args, sess, epoch, image_list, label_list, index_dequeue_op, enqueue_op, image_paths_placeholder, labels_placeholder, learning_rate_placeholder, phase_train_placeholder, batch_size_placeholder, global_step, total_loss, train_op, summary_op, summary_writer, regularization_losses, args.learning_rate_schedule_file) # Save variables and the metagraph if it doesn't exist already save_variables_and_metagraph(sess, saver, summary_writer, model_dir, subdir, step) # Evaluate on LFW if args.lfw_dir: evaluate(sess, enqueue_op, image_paths_placeholder, labels_placeholder, phase_train_placeholder, batch_size_placeholder, embeddings, label_batch, lfw_paths, actual_issame, args.lfw_batch_size, args.lfw_nrof_folds, log_dir, step, summary_writer) sess.close() return model_dir
def main(args): # args从文件系统中导入对象 network = importlib.import_module( args.model_def) # 导入模型,default = 'models.inception_resnet_v1' image_size = (args.image_size, args.image_size) # 导入尺寸,default = 160 subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S') log_dir = os.path.join(os.path.expanduser(args.logs_base_dir), subdir) # 导入运行日志目录,default = '~/logs/facenet' if not os.path.isdir( log_dir): # Create the log directory if it doesn't exist os.makedirs(log_dir) model_dir = os.path.join(os.path.expanduser(args.models_base_dir), subdir) # ,导入模型目录,default = '~/models/facenet' if not os.path.isdir( model_dir): # Create the model directory if it doesn't exist os.makedirs(model_dir) stat_file_name = os.path.join(log_dir, 'stat.h5') # 统计数据,用h5格式保存 # Write arguments to a text file facenet.write_arguments_to_file(args, os.path.join(log_dir, 'arguments.txt')) # 记录命令至运行日志 # Store some git revision info in a text file in the log directory src_path, _ = os.path.split( os.path.realpath(__file__)) # os.path.realpath(__file__)是脚本所在的绝对路径 facenet.store_revision_info(src_path, log_dir, ' '.join(sys.argv)) np.random.seed(seed=args.seed) # default = 666 random.seed(args.seed) dataset = facenet.get_dataset( args.data_dir ) # 导入数据集目录,default = '~/datasets/casia/casia_maxpy_mtcnnalign_182_160' if args.filter_filename: # default = '' dataset = filter_dataset( dataset, os.path.expanduser(args.filter_filename), # expanduser把path中包含的"~"和"~user"转换成用户目录. args.filter_percentile, args.filter_min_nrof_images_per_class ) # default = 100.0, default = 0 if args.validation_set_split_ratio > 0.0: # default = 0.0 train_set, val_set = facenet.split_dataset( dataset, args.validation_set_split_ratio, args.min_nrof_val_images_per_class, 'SPLIT_IMAGES') else: train_set, val_set = dataset, [] nrof_classes = len(train_set) print('Model directory: %s' % model_dir) print('Log directory: %s' % log_dir) pretrained_model = None if args.pretrained_model: pretrained_model = os.path.expanduser(args.pretrained_model) print('Pre-trained model: %s' % pretrained_model) if args.lfw_dir: print('LFW directory: %s' % args.lfw_dir) # Read the file containing the pairs used for testing pairs = lfw.read_pairs(os.path.expanduser( args.lfw_pairs)) # default = 'data/pairs.txt' # Get the paths for the corresponding images lfw_paths, actual_issame = lfw.get_paths( os.path.expanduser(args.lfw_dir), pairs) with tf.Graph().as_default(): tf.set_random_seed(args.seed) # 图级随机数种子 global_step = tf.Variable(0, trainable=False) # Get a list of image paths and their labels image_list, label_list = facenet.get_image_paths_and_labels(train_set) assert len(image_list) > 0, 'The training set should not be empty' val_image_list, val_label_list = facenet.get_image_paths_and_labels( val_set) # Create a queue that produces indices into the image_list and label_list labels = ops.convert_to_tensor(label_list, dtype=tf.int32) range_size = array_ops.shape(labels)[0] index_queue = tf.train.range_input_producer( range_size, num_epochs=None, # 产生1到range_size的对列,num_epochs不给值的话 shuffle=True, seed=None, capacity=32) # 则默认无限循环,后面用capacity限制容量 index_dequeue_op = index_queue.dequeue_many( args.batch_size * args.epoch_size, 'index_dequeue') # 使多个元素同时出列并命名 # 创建张量 learning_rate_placeholder = tf.placeholder(tf.float32, name='learning_rate') batch_size_placeholder = tf.placeholder(tf.int32, name='batch_size') phase_train_placeholder = tf.placeholder(tf.bool, name='phase_train') image_paths_placeholder = tf.placeholder(tf.string, shape=(None, 1), name='image_paths') labels_placeholder = tf.placeholder(tf.int32, shape=(None, 1), name='labels') control_placeholder = tf.placeholder(tf.int32, shape=(None, 1), name='control') nrof_preprocess_threads = 4 # 先进先出对列 input_queue = data_flow_ops.FIFOQueue( capacity=2000000, dtypes=[tf.string, tf.int32, tf.int32], shapes=[(1, ), (1, ), (1, )], shared_name=None, name=None) enqueue_op = input_queue.enqueue_many( [image_paths_placeholder, labels_placeholder, control_placeholder], name='enqueue_op') image_batch, label_batch = facenet.create_input_pipeline( input_queue, image_size, nrof_preprocess_threads, batch_size_placeholder) image_batch = tf.identity(image_batch, 'image_batch') image_batch = tf.identity(image_batch, 'input') label_batch = tf.identity(label_batch, 'label_batch') print('Number of classes in training set: %d' % nrof_classes) print('Number of examples in training set: %d' % len(image_list)) print('Number of classes in validation set: %d' % len(val_set)) print('Number of examples in validation set: %d' % len(val_image_list)) print('Building training graph') # Build the inference graph prelogits, _ = network.inference( image_batch, args.keep_probability, phase_train=phase_train_placeholder, bottleneck_layer_size=args.embedding_size, weight_decay=args.weight_decay) logits = slim.fully_connected( prelogits, len(train_set), activation_fn=None, # 相当于Dense weights_initializer=slim.initializers.xavier_initializer(), weights_regularizer=slim.l2_regularizer(args.weight_decay), scope='Logits', reuse=False) embeddings = tf.nn.l2_normalize( prelogits, 1, 1e-10, name='embeddings') # 按行进行L2正则化,同除各行L2范数 # Norm for the prelogits eps = 1e-4 # 按行计算平均值。norm计算范数,abs取绝对值,ord取1,使用第一范数 prelogits_norm = tf.reduce_mean( tf.norm(tf.abs(prelogits) + eps, ord=args.prelogits_norm_p, axis=1)) tf.add_to_collection( tf.GraphKeys.REGULARIZATION_LOSSES, prelogits_norm * args.prelogits_norm_loss_factor) # 将该种正则化方式储存至graphkeys # Add center loss prelogits_center_loss, _ = facenet.center_loss(prelogits, label_batch, args.center_loss_alfa, nrof_classes) tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES, prelogits_center_loss * args.center_loss_factor) # 指数衰减。参数1:原始学习率。参数2:全局步数,每次自增1,如果不写则不增1.参数3:衰减系数。参数4:衰减速度。参数5:是否取整。True时取整 # 具体计算:decayed_learning_rate = learning_rate*decay_rate^(global_step/decay_steps) learning_rate = tf.train.exponential_decay( learning_rate_placeholder, global_step, args.learning_rate_decay_epochs * args.epoch_size, args.learning_rate_decay_factor, staircase=True) tf.summary.scalar('learning_rate', learning_rate) # 保存数据 # Calculate the average cross entropy loss across the batch cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits( labels=label_batch, logits=logits, name='cross_entropy_per_example') cross_entropy_mean = tf.reduce_mean(cross_entropy, name='cross_entropy') tf.add_to_collection('losses', cross_entropy_mean) # cast转换数据类型(布尔->浮点数),equal比较两个向量相同位置的元素是否一样 correct_prediction = tf.cast( tf.equal(tf.argmax(logits, 1), tf.cast(label_batch, tf.int64)), tf.float32) accuracy = tf.reduce_mean(correct_prediction) # 求平均值即准确率 # Calculate the total losses regularization_losses = tf.get_collection( tf.GraphKeys.REGULARIZATION_LOSSES) # 从graphkeys中把之前存储的loss计算方式取出来 total_loss = tf.add_n([cross_entropy_mean] + regularization_losses, name='total_loss') # Build a Graph that trains the model with one batch of examples and updates the model parameters train_op = facenet.train(total_loss, global_step, args.optimizer, learning_rate, args.moving_average_decay, tf.global_variables(), args.log_histograms) # Create a saver saver = tf.train.Saver(tf.trainable_variables(), max_to_keep=3) # Build the summary operation based on the TF collection of Summaries. summary_op = tf.summary.merge_all( ) # 将所有summary全部保存到磁盘,以便tensorboard显示 # Start running operations on the Graph. gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=args. gpu_memory_fraction) # 使用gpu,参数为使用的显存上限 sess = tf.Session(config=tf.ConfigProto( gpu_options=gpu_options, log_device_placement=False)) # 会话 sess.run(tf.global_variables_initializer()) # 返回所有全局变量 sess.run(tf.local_variables_initializer()) # 返回所有局部变量 summary_writer = tf.summary.FileWriter( log_dir, sess.graph) # 将训练过程数据保存在filewriter指定的文件中 coord = tf.train.Coordinator() # 管理在Session中的多个线程 """ 启动入队线程,由多个或单个线程,按照设定规则,把文件读入Filename Queue中。函数返回线程ID的列表,一般情况下,系统有多少个核, 就会启动多少个入队线程(入队具体使用多少个线程在tf.train.batch中定义) """ tf.train.start_queue_runners(coord=coord, sess=sess) with sess.as_default(): if pretrained_model: print('Restoring pretrained model: %s' % pretrained_model) saver.restore(sess, pretrained_model) # Training and validation loop print('Running training') nrof_steps = args.max_nrof_epochs * args.epoch_size nrof_val_samples = int( math.ceil(args.max_nrof_epochs / args.validate_every_n_epochs) ) # Validate every validate_every_n_epochs as well as in the last epoch # ceil返回上入整数 stat = { 'loss': np.zeros((nrof_steps, ), np.float32), 'center_loss': np.zeros((nrof_steps, ), np.float32), 'reg_loss': np.zeros((nrof_steps, ), np.float32), 'xent_loss': np.zeros((nrof_steps, ), np.float32), 'prelogits_norm': np.zeros((nrof_steps, ), np.float32), 'accuracy': np.zeros((nrof_steps, ), np.float32), 'val_loss': np.zeros((nrof_val_samples, ), np.float32), 'val_xent_loss': np.zeros((nrof_val_samples, ), np.float32), 'val_accuracy': np.zeros((nrof_val_samples, ), np.float32), 'lfw_accuracy': np.zeros((args.max_nrof_epochs, ), np.float32), 'lfw_valrate': np.zeros((args.max_nrof_epochs, ), np.float32), 'learning_rate': np.zeros((args.max_nrof_epochs, ), np.float32), 'time_train': np.zeros((args.max_nrof_epochs, ), np.float32), 'time_validate': np.zeros((args.max_nrof_epochs, ), np.float32), 'time_evaluate': np.zeros((args.max_nrof_epochs, ), np.float32), 'prelogits_hist': np.zeros((args.max_nrof_epochs, 1000), np.float32), } for epoch in range(1, args.max_nrof_epochs + 1): step = sess.run(global_step, feed_dict=None) # Train for one epoch t = time.time() cont = train( args, sess, epoch, image_list, label_list, index_dequeue_op, enqueue_op, image_paths_placeholder, labels_placeholder, learning_rate_placeholder, phase_train_placeholder, batch_size_placeholder, control_placeholder, global_step, total_loss, train_op, summary_op, summary_writer, regularization_losses, args.learning_rate_schedule_file, stat, cross_entropy_mean, accuracy, learning_rate, prelogits, prelogits_center_loss, args.random_rotate, args.random_crop, args.random_flip, prelogits_norm, args.prelogits_hist_max, args.use_fixed_image_standardization) stat['time_train'][epoch - 1] = time.time() - t if not cont: break t = time.time() if len(val_image_list) > 0 and ( (epoch - 1) % args.validate_every_n_epochs == args.validate_every_n_epochs - 1 or epoch == args.max_nrof_epochs): validate(args, sess, epoch, val_image_list, val_label_list, enqueue_op, image_paths_placeholder, labels_placeholder, control_placeholder, phase_train_placeholder, batch_size_placeholder, stat, total_loss, regularization_losses, cross_entropy_mean, accuracy, args.validate_every_n_epochs, args.use_fixed_image_standardization) stat['time_validate'][epoch - 1] = time.time() - t # Save variables and the metagraph if it doesn't exist already save_variables_and_metagraph(sess, saver, summary_writer, model_dir, subdir, epoch) # Evaluate on LFW t = time.time() if args.lfw_dir: evaluate(sess, enqueue_op, image_paths_placeholder, labels_placeholder, phase_train_placeholder, batch_size_placeholder, control_placeholder, embeddings, label_batch, lfw_paths, actual_issame, args.lfw_batch_size, args.lfw_nrof_folds, log_dir, step, summary_writer, stat, epoch, args.lfw_distance_metric, args.lfw_subtract_mean, args.lfw_use_flipped_images, args.use_fixed_image_standardization) stat['time_evaluate'][epoch - 1] = time.time() - t print('Saving statistics') with h5py.File(stat_file_name, 'w') as f: for key, value in stat.iteritems(): f.create_dataset(key, data=value) return model_dir
def main(args): project_dir = os.path.dirname(os.getcwd()) network = importlib.import_module(args.model_def) with open(join(project_dir, 'config.yaml'), 'r') as f: cfg = yaml.load(f) if cfg['specs']['set_gpu']: os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2' os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID" os.environ["CUDA_VISIBLE_DEVICES"] = str(cfg['base_conf']['gpu_num']) subdir = '%s_center_loss_factor_%1.2f' % (args.data_dir, args.center_loss_factor) # test = os.path.expanduser(args.logs_base_dir) log_dir = os.path.join(project_dir, 'fine_tuning_process', 'logs', subdir) if not os.path.isdir( log_dir): # Create the log directory if it doesn't exist os.makedirs(log_dir) model_dir = os.path.join(project_dir, 'fine_tuning_process', 'models', subdir) if not os.path.isdir( model_dir): # Create the model directory if it doesn't exist os.makedirs(model_dir) # Write arguments to a text file facenet.write_arguments_to_file(args, os.path.join(log_dir, 'arguments.txt')) # Store some git revision info in a text file in the log directory src_path, _ = os.path.split(os.path.realpath(__file__)) facenet.store_revision_info(src_path, log_dir, ' '.join(sys.argv)) np.random.seed(seed=args.seed) random.seed(args.seed) data_dir = os.path.join(project_dir, 'fine_tuning_process', 'data', args.data_dir, 'train') train_set = facenet.get_dataset(data_dir) if args.filter_filename: train_set = filter_dataset(train_set, os.path.expanduser(args.filter_filename), args.filter_percentile, args.filter_min_nrof_images_per_class) nrof_classes = len(train_set) print('Model directory: %s' % model_dir) print('Log directory: %s' % log_dir) pretrained_model = os.path.join(project_dir, 'fine_tuning_process', 'models', cfg['model_map'][args.embedding_size]) print('Pre-trained model: %s' % pretrained_model) # if args.lfw_dir: lfw_dir = os.path.join(project_dir, 'fine_tuning_process', 'data', args.data_dir, 'test') print('LFW directory: %s' % lfw_dir) # Read the file containing the pairs used for testing lfw_pairs = os.path.join(project_dir, 'fine_tuning_process', 'data', args.data_dir, 'pairs.txt') pairs = lfw.read_pairs(lfw_pairs) # Get the paths for the corresponding images lfw_paths, actual_issame = lfw.get_paths_personal(lfw_dir, pairs) with tf.Graph().as_default(): tf.set_random_seed(args.seed) global_step = tf.Variable(0, trainable=False) # if args.soft_label: # # TODO: read conf # with open(args.soft_label, 'rb') as f: # confidence_sorce = pickle.load(f) # image_list, label_list = facenet.get_image_paths_and_soft_labels(train_set, confidence_sorce) # else: image_list, label_list = facenet.get_image_paths_and_labels(train_set) # Get a list of image paths and their labels # image_list, label_list = facenet.get_image_paths_and_labels(train_set) # image_list, label_list, nrof_classes = get_image_paths_and_labels('data') assert len(image_list) > 0, 'The dataset should not be empty' # Create a queue that produces indices into the image_list and label_list labels = ops.convert_to_tensor(label_list, dtype=tf.int32) range_size = array_ops.shape(labels)[0] index_queue = tf.train.range_input_producer(range_size, num_epochs=None, shuffle=True, seed=None, capacity=32) index_dequeue_op = index_queue.dequeue_many( args.batch_size * args.epoch_size, 'index_dequeue') learning_rate_placeholder = tf.placeholder(tf.float32, name='learning_rate') batch_size_placeholder = tf.placeholder(tf.int32, name='batch_size') phase_train_placeholder = tf.placeholder(tf.bool, name='phase_train') image_paths_placeholder = tf.placeholder(tf.string, shape=(None, 1), name='image_paths') labels_placeholder = tf.placeholder(tf.int64, shape=(None, 1), name='labels') input_queue = data_flow_ops.FIFOQueue(capacity=100000, dtypes=[tf.string, tf.int64], shapes=[(1, ), (1, )], shared_name=None, name=None) enqueue_op = input_queue.enqueue_many( [image_paths_placeholder, labels_placeholder], name='enqueue_op') nrof_preprocess_threads = 4 images_and_labels = [] for _ in range(nrof_preprocess_threads): filenames, label = input_queue.dequeue() images = [] for filename in tf.unstack(filenames): file_contents = tf.read_file(filename) image = tf.image.decode_image(file_contents, channels=3) if args.random_rotate: image = tf.py_func(facenet.random_rotate_image, [image], tf.uint8) if args.random_crop: image = tf.random_crop( image, [args.image_size, args.image_size, 3]) else: image = tf.image.resize_image_with_crop_or_pad( image, args.image_size, args.image_size) if args.random_flip: image = tf.image.random_flip_left_right(image) # pylint: disable=no-member image.set_shape((args.image_size, args.image_size, 3)) images.append(tf.image.per_image_standardization(image)) images_and_labels.append([images, label]) image_batch, label_batch = tf.train.batch_join( images_and_labels, batch_size=batch_size_placeholder, shapes=[(args.image_size, args.image_size, 3), ()], enqueue_many=True, capacity=4 * nrof_preprocess_threads * args.batch_size, allow_smaller_final_batch=True) image_batch = tf.identity(image_batch, 'image_batch') image_batch = tf.identity(image_batch, 'input') label_batch = tf.identity(label_batch, 'label_batch') print('Total number of classes: %d' % nrof_classes) print('Total number of examples: %d' % len(image_list)) print('Building training graph') # Build the inference graph prelogits, _ = network.inference( image_batch, args.keep_probability, phase_train=phase_train_placeholder, bottleneck_layer_size=args.embedding_size, weight_decay=args.weight_decay) # fine_tuning = slim.fully_connected(prelogits, args.embedding_size, activation_fn=None, # scope='FineTuning', reuse=False, trainable=True) logits = slim.fully_connected( prelogits, nrof_classes, activation_fn=None, weights_initializer=tf.truncated_normal_initializer(stddev=0.1), weights_regularizer=slim.l2_regularizer(args.weight_decay), scope='Logits', reuse=False) embeddings = tf.nn.l2_normalize(prelogits, 1, 1e-10, name='embeddings') # Add center loss if args.center_loss_factor > 0.0: prelogits_center_loss, _ = facenet.center_loss( prelogits, label_batch, args.center_loss_alfa, nrof_classes) tf.add_to_collection( tf.GraphKeys.REGULARIZATION_LOSSES, prelogits_center_loss * args.center_loss_factor) tf.summary.scalar('prelogits_center_loss', prelogits_center_loss) learning_rate = tf.train.exponential_decay( learning_rate_placeholder, global_step, args.learning_rate_decay_epochs * args.epoch_size, args.learning_rate_decay_factor, staircase=True) tf.summary.scalar('learning_rate', learning_rate) # Calculate the average cross entropy loss across the batch cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits( labels=label_batch, logits=logits, name='cross_entropy_per_example') cross_entropy_mean = tf.reduce_mean(cross_entropy, name='cross_entropy') tf.add_to_collection('losses', cross_entropy_mean) # Calculate the total losses regularization_losses = tf.get_collection( tf.GraphKeys.REGULARIZATION_LOSSES) total_loss = tf.add_n([cross_entropy_mean] + regularization_losses, name='total_loss') # Build a Graph that trains the model with one batch of examples and updates the model parameters train_op = facenet.train(total_loss, global_step, args.optimizer, learning_rate, args.moving_average_decay, tf.global_variables(), args.log_histograms) # Create a saver all_vars = tf.trainable_variables() var_to_restore = [ v for v in all_vars if not v.name.startswith('Logits') ] saver = tf.train.Saver(var_to_restore, max_to_keep=3) # Build the summary operation based on the TF collection of Summaries. summary_op = tf.summary.merge_all() # Start running operations on the Graph. gpu_options = tf.GPUOptions( per_process_gpu_memory_fraction=args.gpu_memory_fraction) sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options, log_device_placement=False)) sess.run(tf.global_variables_initializer()) sess.run(tf.local_variables_initializer()) summary_writer = tf.summary.FileWriter(log_dir, sess.graph) coord = tf.train.Coordinator() tf.train.start_queue_runners(coord=coord, sess=sess) with sess.as_default(): if args.pretrained_model: print('Restoring pretrained model: %s' % pretrained_model) saver.restore(sess, pretrained_model) result = sess.graph.get_tensor_by_name( "InceptionResnetV1/Bottleneck/weights:0") pre = sess.graph.get_tensor_by_name( "InceptionResnetV1/Block8/Branch_1/Conv2d_0c_3x1/weights:0" ) # tf.stop_gradient(persisted_result) # print(result.eval()) # print("======") # print(pre.eval()) # Training and validation loop print('Running training') epoch = 0 pre_acc = -1 while epoch < args.max_nrof_epochs: step = sess.run(global_step, feed_dict=None) epoch = step // args.epoch_size # Train for one epoch train(args, sess, epoch, image_list, label_list, index_dequeue_op, enqueue_op, image_paths_placeholder, labels_placeholder, learning_rate_placeholder, phase_train_placeholder, batch_size_placeholder, global_step, total_loss, train_op, summary_op, summary_writer, regularization_losses, args.learning_rate_schedule_file, logits) # print(result.eval()) # print("======") # print(pre.eval()) # Save variables and the metagraph if it doesn't exist already # Evaluate on LFW if lfw_dir: acc = evaluate(sess, enqueue_op, image_paths_placeholder, labels_placeholder, phase_train_placeholder, batch_size_placeholder, embeddings, label_batch, lfw_paths, actual_issame, args.lfw_batch_size, args.lfw_nrof_folds, log_dir, step, summary_writer, total_loss, prelogits_center_loss) if acc > pre_acc: save_variables_and_metagraph(sess, saver, summary_writer, model_dir, subdir, step) pre_acc = acc return model_dir
def main(args): #network = importlib.import_module(args.model_def, 'inception_v3') network = importlib.import_module(args.model_def) subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S') log_dir = os.path.join(os.path.expanduser(args.logs_base_dir), subdir) if not os.path.isdir( log_dir): # Create the log directory if it doesn't exist os.makedirs(log_dir) model_dir = os.path.join(os.path.expanduser(args.models_base_dir), subdir) if not os.path.isdir( model_dir): # Create the model directory if it doesn't exist os.makedirs(model_dir) with open(os.path.join(model_dir, 'args.txt'), 'w') as f: for arg in vars(args): f.write(arg + ' ' + str(getattr(args, arg)) + '\n') # Store some git revision info in a text file in the log directory src_path, _ = os.path.split(os.path.realpath(__file__)) facenet.store_revision_info(src_path, log_dir, ' '.join(sys.argv)) np.random.seed(seed=args.seed) #train_set = facenet.get_dataset(args.data_dir) train_set = facenet.get_dataset_with_enhanced(args.data_dir) nrof_classes = len(train_set) print('Model directory: %s' % model_dir) print('Log directory: %s' % log_dir) pretrained_model = None if args.pretrained_model: pretrained_model = os.path.expanduser(args.pretrained_model) print('Pre-trained model: %s' % pretrained_model) if args.lfw_dir: print('LFW directory: %s' % args.lfw_dir) # Read the file containing the pairs used for testing pairs = lfw.read_pairs(os.path.expanduser(args.lfw_pairs)) # Get the paths for the corresponding images lfw_paths, actual_issame = lfw.get_paths( os.path.expanduser(args.lfw_dir), pairs, args.lfw_file_ext) with tf.Graph().as_default(): tf.set_random_seed(args.seed) global_step = tf.Variable(0, trainable=False) # Get a list of image paths and their labels image_list, label_list = facenet.get_image_paths_and_labels(train_set) # Read data and apply label preserving distortions image_batch, label_batch = facenet.read_and_augument_data( image_list, label_list, args.image_size, args.batch_size, args.max_nrof_epochs, args.random_rotate, args.random_crop, args.random_flip, args.nrof_preprocess_threads, args.padding_size, args.patch_type) #print('Total number of classes: %d' % len(train_set)) print('Total number of examples: %d' % len(image_list)) # Node for input images image_batch = tf.identity(image_batch, name='input') # Placeholder for the learning rate learning_rate_placeholder = tf.placeholder(tf.float32, name='learning_rate') # Placeholder for phase_train phase_train_placeholder = tf.placeholder(tf.bool, name='phase_train') # Placeholder for keep probability keep_probability_placeholder = tf.placeholder(tf.float32, name='keep_prob') # Build the inference graph # prelogits = network.inference(image_batch, keep_probability_placeholder, # phase_train=phase_train_placeholder, weight_decay=args.weight_decay) batch_norm_params = { # Decay for the moving averages 'decay': 0.995, # epsilon to prevent 0s in variance 'epsilon': 0.001, # force in-place updates of mean and variance estimates 'updates_collections': None, # Moving averages ends up in the trainable variables collection 'variables_collections': [tf.GraphKeys.TRAINABLE_VARIABLES], # Only update statistics during training mode 'is_training': phase_train_placeholder } #prelogits, _ = network.inception_v3(image_batch, num_classes=len(train_set),is_training=True) prelogits, _ = network.inference(image_batch, args.keep_probability, phase_train=phase_train_placeholder, weight_decay=args.weight_decay) #prelogits = tf.identity(prelogits, name="prelogits") bottleneck = _fully_connected(prelogits, args.embedding_size, name='pre_embedding') #bottleneck = tf.nn.l2_normalize(bottleneck, dim=1,name='embedding') logits = _fully_connected_classifier(bottleneck, len(train_set), name='logits') """ bottleneck = slim.fully_connected(prelogits, args.embedding_size, activation_fn=None, weights_initializer=tf.truncated_normal_initializer(stddev=0.1), weights_regularizer=slim.l2_regularizer(args.weight_decay), normalizer_fn=slim.batch_norm, normalizer_params=batch_norm_params, scope='Bottleneck', reuse=False) logits = slim.fully_connected(bottleneck, len(train_set), activation_fn=None, weights_initializer=tf.truncated_normal_initializer(stddev=0.1), weights_regularizer=slim.l2_regularizer(args.weight_decay), scope='Logits', reuse=False) logits = tf.identity(logits, name="logits") """ # Add DeCov regularization loss if args.decov_loss_factor > 0.0: logits_decov_loss = facenet.decov_loss( logits) * args.decov_loss_factor tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES, logits_decov_loss) # Add center loss update_centers = tf.no_op('update_centers') if args.center_loss_factor > 0.0: prelogits_center_loss, update_centers = facenet.center_loss( bottleneck, label_batch, args.center_loss_alfa, nrof_classes) tf.add_to_collection( tf.GraphKeys.REGULARIZATION_LOSSES, prelogits_center_loss * args.center_loss_factor) #embeddings = tf.nn.l2_normalize(bottleneck, 1, 1e-10, name='embeddings') learning_rate = tf.train.exponential_decay( learning_rate_placeholder, global_step, args.learning_rate_decay_epochs * args.epoch_size, args.learning_rate_decay_factor, staircase=True) tf.summary.scalar('learning_rate', learning_rate) # Calculate the average cross entropy loss across the batch cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits( labels=label_batch, logits=logits, name='cross_entropy_per_example') cross_entropy_mean = tf.reduce_mean(cross_entropy, name='cross_entropy') """ # Multi-label loss: sigmoid loss sigmoid_loss = tf.nn.sigmoid_cross_entropy_with_logits(labels=label_batch, logits=logits, name='sigmoid_loss_per_example') sigmoid_loss_mean = tf.reduce_mean(sigmoid_loss, name='sigmoid_loss') """ tf.add_to_collection('losses', cross_entropy_mean) # Calculate the total losses regularization_losses = tf.get_collection( tf.GraphKeys.REGULARIZATION_LOSSES) total_loss = tf.add_n([cross_entropy_mean] + regularization_losses, name='total_loss') #total_loss = tf.add_n([cross_entropy_mean], name='total_loss') # prediction prediction = tf.argmax(logits, axis=1, name='prediction') acc = slim.metrics.accuracy(predictions=tf.cast(prediction, dtype=tf.int32), labels=tf.cast(label_batch, dtype=tf.int32)) # Build a Graph that trains the model with one batch of examples and updates the model parameters train_op = facenet.train(total_loss, global_step, args.optimizer, learning_rate, args.moving_average_decay, tf.global_variables()) # Create a saver # save_variables = list(set(tf.all_variables())-set([w])-set([b])) save_variables = tf.trainable_variables() saver = tf.train.Saver(save_variables, max_to_keep=3) # Build the summary operation based on the TF collection of Summaries. summary_op = tf.summary.merge_all() # Start running operations on the Graph. # gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=args.gpu_memory_fraction) # sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options, log_device_placement=False)) config = tf.ConfigProto() config.gpu_options.allow_growth = True sess = tf.Session(config=config) sess.run(tf.global_variables_initializer()) sess.run(tf.local_variables_initializer()) summary_writer = tf.summary.FileWriter(log_dir, sess.graph) tf.train.start_queue_runners(sess=sess) with sess.as_default(): if pretrained_model: saver.restore(sess, pretrained_model) # Training and validation loop epoch = 0 while epoch < args.max_nrof_epochs: step = sess.run(global_step, feed_dict=None) epoch = step // args.epoch_size # Train for one epoch train(args, sess, epoch, phase_train_placeholder, learning_rate_placeholder, keep_probability_placeholder, global_step, total_loss, acc, train_op, summary_op, summary_writer, regularization_losses, args.learning_rate_schedule_file, update_centers) # Evaluate on LFW if args.lfw_dir: start_time = time.time() _, _, accuracy, val, val_std, far = lfw.validate( sess, lfw_paths, actual_issame, args.seed, args.batch_size, image_batch, phase_train_placeholder, keep_probability_placeholder, embeddings, nrof_folds=args.lfw_nrof_folds) print('Accuracy: %1.3f+-%1.3f' % (np.mean(accuracy), np.std(accuracy))) print('Validation rate: %2.5f+-%2.5f @ FAR=%2.5f' % (val, val_std, far)) lfw_time = time.time() - start_time # Add validation loss and accuracy to summary summary = tf.Summary() #pylint: disable=maybe-no-member summary.value.add(tag='lfw/accuracy', simple_value=np.mean(accuracy)) summary.value.add(tag='lfw/val_rate', simple_value=val) summary.value.add(tag='time/lfw', simple_value=lfw_time) summary_writer.add_summary(summary, step) with open(os.path.join(log_dir, 'lfw_result.txt'), 'at') as f: f.write('%d\t%.5f\t%.5f\n' % (step, np.mean(accuracy), val)) # Save variables and the metagraph if it doesn't exist already save_variables_and_metagraph(sess, saver, summary_writer, model_dir, subdir, step) return model_dir
def main(args): os.environ["CUDA_VISIBLE_DEVICES"] = '0' network = importlib.import_module(args.model_def) subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S') log_dir = os.path.join(os.path.expanduser(args.logs_base_dir), subdir) if not os.path.isdir( log_dir): # Create the log directory if it doesn't exist os.makedirs(log_dir) model_dir = os.path.join(os.path.expanduser(args.models_base_dir), subdir) if not os.path.isdir( model_dir): # Create the model directory if it doesn't exist os.makedirs(model_dir) # Write arguments to a text file facenet.write_arguments_to_file(args, os.path.join(log_dir, 'arguments.txt')) # Store some git revision info in a text file in the log directory src_path, _ = os.path.split(os.path.realpath(__file__)) facenet.store_revision_info(src_path, log_dir, ' '.join(sys.argv)) np.random.seed(seed=args.seed) random.seed(args.seed) train_set = facenet.get_dataset(args.data_dir) train_set, test_set = facenet.split_dataset(train_set, 0.8, mode='SPLIT_IMAGES') if args.filter_filename: train_set = filter_dataset(train_set, os.path.expanduser(args.filter_filename), args.filter_percentile, args.filter_min_nrof_images_per_class) nrof_classes = len(train_set) test_nrof_classes = len(test_set) print('Model directory: %s' % model_dir) print('Log directory: %s' % log_dir) pretrained_model = None if args.pretrained_model: pretrained_model = os.path.expanduser(args.pretrained_model) # meta_file, ckpt_model=facenet.get_model_filenames(pretrained_model) # pretrained_model=ckpt_model print('Pre-trained model: %s' % pretrained_model) if args.lfw_dir: print('LFW directory: %s' % args.lfw_dir) # Read the file containing the pairs used for testing pairs = lfw.read_pairs(os.path.expanduser(args.lfw_pairs)) # Get the paths for the corresponding images lfw_paths, actual_issame = lfw.get_paths( os.path.expanduser(args.lfw_dir), pairs, args.lfw_file_ext) with tf.Graph().as_default(): tf.set_random_seed(args.seed) global_step = tf.Variable(0, trainable=False) # Get a list of image paths and their labels image_list, label_list = facenet.get_image_paths_and_labels(train_set) assert len(image_list) > 0, 'The dataset should not be empty' test_image_list, test_label_list = facenet.get_image_paths_and_labels( test_set) assert len(test_image_list) > 0, 'The dataset should not be empty' # Create a queue that produces indices into the image_list and label_list labels = ops.convert_to_tensor(label_list, dtype=tf.int32) range_size = array_ops.shape(labels)[0] index_queue = tf.train.range_input_producer(range_size, num_epochs=None, shuffle=True, seed=None, capacity=32) index_dequeue_op = index_queue.dequeue_many( args.batch_size * args.epoch_size, 'index_dequeue') learning_rate_placeholder = tf.placeholder(tf.float32, name='learning_rate') batch_size_placeholder = tf.placeholder(tf.int32, name='batch_size') phase_train_placeholder = tf.placeholder(tf.bool, name='phase_train') image_paths_placeholder = tf.placeholder(tf.string, shape=(None, 1), name='image_paths') labels_placeholder = tf.placeholder(tf.int64, shape=(None, 1), name='labels') input_queue = data_flow_ops.FIFOQueue(capacity=100000, dtypes=[tf.string, tf.int64], shapes=[(1, ), (1, )], shared_name=None, name=None) enqueue_op = input_queue.enqueue_many( [image_paths_placeholder, labels_placeholder], name='enqueue_op') nrof_preprocess_threads = 4 images_and_labels = [] for _ in range(nrof_preprocess_threads): filenames, label = input_queue.dequeue() images = [] for filename in tf.unstack(filenames): file_contents = tf.read_file(filename) image = tf.image.decode_image(file_contents, channels=3) if args.random_rotate: image = tf.py_func(facenet.random_rotate_image, [image], tf.uint8) if args.random_crop: image = tf.random_crop( image, [args.image_size, args.image_size, 3]) else: image = tf.image.resize_image_with_crop_or_pad( image, args.image_size, args.image_size) if args.random_flip: image = tf.image.random_flip_left_right(image) #pylint: disable=no-member image.set_shape((args.image_size, args.image_size, 3)) images.append(tf.image.per_image_standardization(image)) images_and_labels.append([images, label]) image_batch, label_batch = tf.train.batch_join( images_and_labels, batch_size=batch_size_placeholder, shapes=[(args.image_size, args.image_size, 3), ()], enqueue_many=True, capacity=4 * nrof_preprocess_threads * args.batch_size, allow_smaller_final_batch=True) image_batch = tf.identity(image_batch, 'image_batch') image_batch = tf.identity(image_batch, 'input') label_batch = tf.identity(label_batch, 'label_batch') print('Total number of classes: %d' % nrof_classes) print('Total number of examples: %d' % len(image_list)) # Create a queue that produces indices into the test_image_list and test_label_list test_labels = ops.convert_to_tensor(test_label_list, dtype=tf.int32) test_range_size = array_ops.shape(test_labels)[0] test_index_queue = tf.train.range_input_producer(test_range_size, num_epochs=None, shuffle=True, seed=None, capacity=32) # global test_batch_size # test_batch_size=args.batch_size test_index_dequeue_op = test_index_queue.dequeue_many( test_batch_size * test_epoch_size, 'test_index_dequeue') test_input_queue = data_flow_ops.FIFOQueue( capacity=100000, dtypes=[tf.string, tf.int64], shapes=[(1, ), (1, )], shared_name=None, name=None) test_enqueue_op = test_input_queue.enqueue_many( [image_paths_placeholder, labels_placeholder], name='test_enqueue_op') test_nrof_preprocess_threads = 4 test_images_and_labels = [] for _ in range(test_nrof_preprocess_threads): filenames, label = test_input_queue.dequeue() images = [] for filename in tf.unstack(filenames): file_contents = tf.read_file(filename) image = tf.image.decode_image(file_contents, channels=3) if args.random_rotate: image = tf.py_func(facenet.random_rotate_image, [image], tf.uint8) if args.random_crop: image = tf.random_crop( image, [args.image_size, args.image_size, 3]) else: image = tf.image.resize_image_with_crop_or_pad( image, args.image_size, args.image_size) if args.random_flip: image = tf.image.random_flip_left_right(image) # pylint: disable=no-member image.set_shape((args.image_size, args.image_size, 3)) images.append(tf.image.per_image_standardization(image)) test_images_and_labels.append([images, label]) test_image_batch, test_label_batch = tf.train.batch_join( test_images_and_labels, batch_size=test_batch_size, shapes=[(args.image_size, args.image_size, 3), ()], enqueue_many=True, capacity=4 * test_nrof_preprocess_threads * test_batch_size, allow_smaller_final_batch=True) test_image_batch = tf.identity(test_image_batch, 'test_image_batch') test_image_batch = tf.identity(test_image_batch, 'test_input') test_label_batch = tf.identity(test_label_batch, 'test_label_batch') print('Total number of test classes: %d' % test_nrof_classes) print('Total number of test examples: %d' % len(test_image_list)) image_input_placeholder = tf.get_default_graph().get_tensor_by_name( "input:0") label_input_placeholder = tf.get_default_graph().get_tensor_by_name( "label_batch:0") print('Building training graph') # Build the inference graph print("embeddings size is: %s" % (str(args.embedding_size))) prelogits, _ = network.inference( image_batch, args.keep_probability, phase_train=phase_train_placeholder, bottleneck_layer_size=args.embedding_size, weight_decay=args.weight_decay) logits = slim.fully_connected( prelogits, len(train_set), activation_fn=None, weights_initializer=tf.truncated_normal_initializer(stddev=0.1), weights_regularizer=slim.l2_regularizer(args.weight_decay), scope='Logits', reuse=False) embeddings = tf.nn.l2_normalize(prelogits, 1, 1e-10, name='embeddings') # Add center loss if args.center_loss_factor > 0.0: prelogits_center_loss, _ = facenet.center_loss( prelogits, label_batch, args.center_loss_alfa, nrof_classes) tf.add_to_collection( tf.GraphKeys.REGULARIZATION_LOSSES, prelogits_center_loss * args.center_loss_factor) learning_rate = tf.train.exponential_decay( learning_rate_placeholder, global_step, args.learning_rate_decay_epochs * args.epoch_size, args.learning_rate_decay_factor, staircase=True) tf.summary.scalar('learning_rate', learning_rate) # Calculate the average cross entropy loss across the batch cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits( labels=label_batch, logits=logits, name='cross_entropy_per_example') cross_entropy_mean = tf.reduce_mean(cross_entropy, name='cross_entropy') tf.add_to_collection('losses', cross_entropy_mean) # Calculate the total losses regularization_losses = tf.get_collection( tf.GraphKeys.REGULARIZATION_LOSSES) total_loss = tf.add_n([cross_entropy_mean] + regularization_losses, name='total_loss') # Build a Graph that trains the model with one batch of examples and updates the model parameters train_op = facenet.train(total_loss, global_step, args.optimizer, learning_rate, args.moving_average_decay, tf.global_variables(), args.log_histograms) # Create a saver if args.pretrained_model: variables = [] for v in tf.trainable_variables(): if v.name.startswith("Logits") or v.name.startswith( "InceptionResnetV1/Block8") or v.name.startswith( "InceptionResnetV1/Block17"): print("skip variable %s" % v.name) continue else: print("var name %s" % v.name) variables.append(v) # if not v.name.startswith("Logits") and not v.name.startswith("Block8"): # variables.append(v) saver = tf.train.Saver(variables, max_to_keep=3) else: saver = tf.train.Saver(tf.trainable_variables(), max_to_keep=3) # Build the summary operation based on the TF collection of Summaries. summary_op = tf.summary.merge_all() # Start running operations on the Graph. gpu_options = tf.GPUOptions( per_process_gpu_memory_fraction=args.gpu_memory_fraction) sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options, log_device_placement=False)) sess.run(tf.global_variables_initializer()) sess.run(tf.local_variables_initializer()) summary_writer = tf.summary.FileWriter(log_dir, sess.graph) coord = tf.train.Coordinator() tf.train.start_queue_runners(coord=coord, sess=sess) with sess.as_default(): if pretrained_model: print('Restoring pretrained model: %s' % pretrained_model) saver.restore(sess, pretrained_model) # Training and validation loop print('Running training') epoch = 0 while epoch < args.max_nrof_epochs: step = sess.run(global_step, feed_dict=None) #epoch = step // args.epoch_size # Train for one epoch step=train(args, sess, epoch, image_list, label_list, index_dequeue_op, enqueue_op, image_paths_placeholder, labels_placeholder, learning_rate_placeholder, phase_train_placeholder, batch_size_placeholder, global_step, total_loss, train_op, summary_op, summary_writer, regularization_losses, args.learning_rate_schedule_file\ ,test_image_list, test_label_list, test_index_dequeue_op, test_enqueue_op,image_batch, label_batch) # Save variables and the metagraph if it doesn't exist already save_variables_and_metagraph(sess, saver, summary_writer, model_dir, subdir, step) epoch += 1 # Evaluate on LFW if args.lfw_dir: evaluate(sess, enqueue_op, image_paths_placeholder, labels_placeholder, phase_train_placeholder, batch_size_placeholder, embeddings, label_batch, lfw_paths, actual_issame, args.lfw_batch_size, args.lfw_nrof_folds, log_dir, step, summary_writer) # constant_graph = graph_util.convert_variables_to_constants(sess, sess.graph_def, ["embeddings"]) # with tf.gfile.FastGFile(model_dir + '/video-faces_%d_model.pb'%args.max_nrof_epochs, mode='wb') as f: # f.write(constant_graph.SerializeToString()) return model_dir
def get_loss(image_batch, label_batch, scope, train_set): # Build the inference graph prelogits, _ = network.inference( image_batch, args.keep_probability, phase_train=phase_train_placeholder, bottleneck_layer_size=args.embedding_size, weight_decay=args.weight_decay) logits = slim.fully_connected( prelogits, len(train_set), activation_fn=None, weights_initializer=tf.truncated_normal_initializer( stddev=0.1), weights_regularizer=slim.l2_regularizer(args.weight_decay), scope='Logits', reuse=False) embeddings = tf.nn.l2_normalize(prelogits, 1, 1e-10, name='embeddings') # print(logits.get_shape()) (?, 10575) 10575 lei # print(embeddings.get_shape()) (?, 128) embedding_size # Add center loss if args.center_loss_factor > 0.0: prelogits_center_loss, _ = facenet.center_loss( prelogits, label_batch, args.center_loss_alfa, nrof_classes) tf.add_to_collection( tf.GraphKeys.REGULARIZATION_LOSSES, prelogits_center_loss * args.center_loss_factor) # Calculate the average cross entropy loss across the batch cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits( labels=label_batch, logits=logits, name='cross_entropy_per_example') cross_entropy_mean = tf.reduce_mean(cross_entropy, name='cross_entropy') tf.add_to_collection('losses', cross_entropy_mean) # Calculate the total losses regularization_losses = tf.get_collection( tf.GraphKeys.REGULARIZATION_LOSSES, scope) #loss_averages = tf.train.ExponentialMovingAverage(0.9, name='avg') #losses = tf.get_collection('losses',scope) total_loss = tf.add_n([cross_entropy_mean] + regularization_losses, name='total_loss') #loss_averages_op = loss_averages.apply(losses + [total_loss]) # Attach a scalar summmary to all individual losses and the total loss; do the # same for the averaged version of the losses. return total_loss, embeddings, regularization_losses