def main(args): subdir = time.strftime('%Y%m%d-%H%M%S', time.localtime()) 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')) with tf.Graph().as_default(): with tf.Session() as sess: facenet.load_model(model_path) images_placeholder = tf.get_default_graph().get_tensor_by_name( 'input:0') embeddings = tf.get_default_graph().get_tensor_by_name( 'embeddings:0') phase_train_placeholder = tf.get_default_graph( ).get_tensor_by_name('phase_train:0') target = tf.placeholder(dtype=tf.int64, shape=(None, 2), name='target_output') fc1 = tf.layers.dense(inputs=embeddings, units=64, activation='relu', use_bias=True) fc2 = tf.layers.dense(inputs=fc1, units=2, use_bias=True) res = tf.nn.softmax(logits=fc2) loss = tf.reduce_sum( tf.multiply(tf.subtract(res, target), tf.subtract(res, target))) train_step = tf.train.GradientDescentOptimizer(0.5).minimize(loss) tf.global_variables_initializer().run()
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) 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) # get soft labels with open(join(data_dir, 'soft_label.pk'), 'rb') as f: confidence_score = pickle.load(f) image_list, soft_labels_list = facenet.get_image_paths_and_soft_labels( train_set, confidence_score) soft_labels_array = np.array(soft_labels_list) soft_labels = ops.convert_to_tensor(soft_labels_array, dtype=tf.float32) assert len(image_list) > 0, 'The dataset should not be empty' # Create a queue that produces indices into the image_list and label_list range_size = array_ops.shape(soft_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') hard_labels_placeholder = tf.placeholder(tf.int64, shape=(None, 1), name='hard_labels') soft_labels_placeholder = tf.placeholder(tf.float32, shape=(None, nrof_classes), name='soft_labels') input_queue = data_flow_ops.FIFOQueue(capacity=100000, dtypes=[tf.string, tf.float32], shapes=[(1, ), (nrof_classes, )], shared_name=None, name=None) enqueue_op = input_queue.enqueue_many( [image_paths_placeholder, soft_labels_placeholder], name='enqueue_op') nrof_preprocess_threads = 4 images_and_softlabels = [] for _ in range(nrof_preprocess_threads): filenames, soft_labels = 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_softlabels.append([images, soft_labels]) image_batch, soft_label_batch = tf.train.batch_join( images_and_softlabels, batch_size=batch_size_placeholder) image_batch = tf.squeeze(image_batch, 1) image_batch = tf.identity(image_batch, 'image_batch') image_batch = tf.identity(image_batch, 'input') soft_label_batch = tf.identity(soft_label_batch, 'soft_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.fuzzy_center_loss( prelogits, soft_label_batch, args.center_loss_alfa, args.fuzzier, 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.softmax_cross_entropy_with_logits_v2( labels=soft_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, soft_labels_array, index_dequeue_op, enqueue_op, image_paths_placeholder, soft_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 args.lfw_dir: acc = evaluate(sess, enqueue_op, image_paths_placeholder, soft_labels_placeholder, phase_train_placeholder, batch_size_placeholder, embeddings, soft_label_batch, lfw_paths, actual_issame, args.lfw_batch_size, args.lfw_nrof_folds, log_dir, step, summary_writer, nrof_classes, 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): img_mean = np.array([134.10714722, 102.52040863, 87.15436554]) img_stddev = np.sqrt( np.array([3941.30175781, 2856.94287109, 2519.35791016])) vae_def = importlib.import_module(args.vae_def) vae = vae_def.Vae(args.latent_var_size) gen_image_size = vae.get_image_size() subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S') 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) log_file_name = os.path.join(model_dir, 'logs.h5') # Write arguments to a text file facenet.write_arguments_to_file(args, os.path.join(model_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, model_dir, ' '.join(sys.argv)) with tf.Graph().as_default(): tf.set_random_seed(args.seed) global_step = tf.Variable(0, trainable=False) train_set = facenet.get_dataset(args.data_dir) image_list, _ = facenet.get_image_paths_and_labels(train_set) # Create the input queue input_queue = tf.train.string_input_producer(image_list, shuffle=True) nrof_preprocess_threads = 4 image_per_thread = [] for _ in range(nrof_preprocess_threads): file_contents = tf.read_file(input_queue.dequeue()) image = tf.image.decode_image(file_contents, channels=3) image = tf.image.resize_image_with_crop_or_pad( image, args.input_image_size, args.input_image_size) image.set_shape((args.input_image_size, args.input_image_size, 3)) image = tf.cast(image, tf.float32) #pylint: disable=no-member image_per_thread.append([image]) images = tf.train.batch_join(image_per_thread, batch_size=args.batch_size, capacity=4 * nrof_preprocess_threads * args.batch_size, allow_smaller_final_batch=False) # Normalize images_norm = (images - img_mean) / img_stddev # Resize to appropriate size for the encoder images_norm_resize = tf.image.resize_images( images_norm, (gen_image_size, gen_image_size)) # Create encoder network mean, log_variance = vae.encoder(images_norm_resize, True) epsilon = tf.random_normal((tf.shape(mean)[0], args.latent_var_size)) std = tf.exp(log_variance / 2) latent_var = mean + epsilon * std # Create decoder network reconstructed_norm = vae.decoder(latent_var, True) # Un-normalize reconstructed = (reconstructed_norm * img_stddev) + img_mean # Create reconstruction loss if args.reconstruction_loss_type == 'PLAIN': images_resize = tf.image.resize_images( images, (gen_image_size, gen_image_size)) reconstruction_loss = tf.reduce_mean( tf.reduce_sum(tf.pow(images_resize - reconstructed, 2))) elif args.reconstruction_loss_type == 'PERCEPTUAL': network = importlib.import_module(args.model_def) reconstructed_norm_resize = tf.image.resize_images( reconstructed_norm, (args.input_image_size, args.input_image_size)) # Stack images from both the input batch and the reconstructed batch in a new tensor shp = [-1] + images_norm.get_shape().as_list()[1:] input_images = tf.reshape( tf.stack([images_norm, reconstructed_norm_resize], axis=0), shp) _, end_points = network.inference(input_images, 1.0, phase_train=False, bottleneck_layer_size=128, weight_decay=0.0) # Get a list of feature names to use for loss terms feature_names = args.loss_features.replace(' ', '').split(',') # Calculate L2 loss between original and reconstructed images in feature space reconstruction_loss_list = [] for feature_name in feature_names: feature_flat = slim.flatten(end_points[feature_name]) image_feature, reconstructed_feature = tf.unstack(tf.reshape( feature_flat, [2, args.batch_size, -1]), num=2, axis=0) reconstruction_loss = tf.reduce_mean(tf.reduce_sum( tf.pow(image_feature - reconstructed_feature, 2)), name=feature_name + '_loss') reconstruction_loss_list.append(reconstruction_loss) # Sum up the losses in for the different features reconstruction_loss = tf.add_n(reconstruction_loss_list, 'reconstruction_loss') else: pass # Create KL divergence loss kl_loss = kl_divergence_loss(mean, log_variance) kl_loss_mean = tf.reduce_mean(kl_loss) total_loss = args.alfa * kl_loss_mean + args.beta * reconstruction_loss learning_rate = tf.train.exponential_decay( args.initial_learning_rate, global_step, args.learning_rate_decay_steps, args.learning_rate_decay_factor, staircase=True) # Calculate gradients and make sure not to include parameters for the perceptual loss model opt = tf.train.AdamOptimizer(learning_rate) grads = opt.compute_gradients(total_loss, var_list=get_variables_to_train()) # Apply gradients apply_gradient_op = opt.apply_gradients(grads, global_step=global_step) with tf.control_dependencies([apply_gradient_op]): train_op = tf.no_op(name='train') # Create a saver saver = tf.train.Saver(tf.trainable_variables(), max_to_keep=3) facenet_saver = tf.train.Saver(get_facenet_variables_to_restore()) # Start running operations on the Graph gpu_memory_fraction = 1.0 gpu_options = tf.compat.v1.GPUOptions( per_process_gpu_memory_fraction=gpu_memory_fraction) sess = tf.compat.v1.Session(config=tf.compat.v1.ConfigProto( gpu_options=gpu_options, log_device_placement=False)) sess.run(tf.global_variables_initializer()) sess.run(tf.local_variables_initializer()) coord = tf.train.Coordinator() tf.train.start_queue_runners(coord=coord, sess=sess) with sess.as_default(): if args.reconstruction_loss_type == 'PERCEPTUAL': if not args.pretrained_model: raise ValueError( 'A pretrained model must be specified when using perceptual loss' ) pretrained_model_exp = os.path.expanduser( args.pretrained_model) print('Restoring pretrained model: %s' % pretrained_model_exp) facenet_saver.restore(sess, pretrained_model_exp) log = { 'total_loss': np.zeros((0, ), np.float), 'reconstruction_loss': np.zeros((0, ), np.float), 'kl_loss': np.zeros((0, ), np.float), 'learning_rate': np.zeros((0, ), np.float), } step = 0 print('Running training') while step < args.max_nrof_steps: start_time = time.time() step += 1 save_state = step > 0 and (step % args.save_every_n_steps == 0 or step == args.max_nrof_steps) if save_state: _, reconstruction_loss_, kl_loss_mean_, total_loss_, learning_rate_, rec_ = sess.run( [ train_op, reconstruction_loss, kl_loss_mean, total_loss, learning_rate, reconstructed ]) img = facenet.put_images_on_grid(rec_, shape=(16, 8)) misc.imsave( os.path.join(model_dir, 'reconstructed_%06d.png' % step), img) else: _, reconstruction_loss_, kl_loss_mean_, total_loss_, learning_rate_ = sess.run( [ train_op, reconstruction_loss, kl_loss_mean, total_loss, learning_rate ]) log['total_loss'] = np.append(log['total_loss'], total_loss_) log['reconstruction_loss'] = np.append( log['reconstruction_loss'], reconstruction_loss_) log['kl_loss'] = np.append(log['kl_loss'], kl_loss_mean_) log['learning_rate'] = np.append(log['learning_rate'], learning_rate_) duration = time.time() - start_time print( 'Step: %d \tTime: %.3f \trec_loss: %.3f \tkl_loss: %.3f \ttotal_loss: %.3f' % (step, duration, reconstruction_loss_, kl_loss_mean_, total_loss_)) if save_state: print('Saving checkpoint file') checkpoint_path = os.path.join(model_dir, 'model.ckpt') saver.save(sess, checkpoint_path, global_step=step, write_meta_graph=False) print('Saving log') with h5py.File(log_file_name, 'w') as f: for key, value in iteritems(log): f.create_dataset(key, data=value)
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(args): # # 导入 model_def 代表的网络结构 # 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 # 将 参数 写入到 text 文件中 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 # 将一些 git 修订信息存储在日志目录的文本文件中 src_path, _ = os.path.split(os.path.realpath(__file__)) facenet.store_revision_info(src_path, log_dir, ' '.join(sys.argv)) # 获取 facenet 的数据集 np.random.seed(seed=args.seed) # train_set = facenet.get_dataset(args.data_dir) # 训练数据集 train_set = facenet.dataset_from_list(args.data_dir, args.list_file) nrof_classes = len(train_set) print('nrof_classes: ', nrof_classes) # 获取 图像 的 路径 和 labels image_list, label_list = facenet.get_image_paths_and_labels(train_set) print('total images: ', len(image_list)) image_list = np.array(image_list) label_list = np.array(label_list, dtype=np.int32) dataset_size = len(image_list) # 单个 batch_size = 每个 batch 中的人数 * 每个人的图像数 single_batch_size = args.people_per_batch * args.images_per_person indices = range(dataset_size) np.random.shuffle(indices) # 从 dataset 中抽取 样本,将 image_path 和 image_label 返回 def _sample_people_softmax(x): global softmax_ind if softmax_ind >= dataset_size: np.random.shuffle(indices) softmax_ind = 0 true_num_batch = min(single_batch_size, dataset_size - softmax_ind) sample_paths = image_list[indices[softmax_ind:softmax_ind + true_num_batch]] sample_labels = label_list[indices[softmax_ind:softmax_ind + true_num_batch]] softmax_ind += true_num_batch return (np.array(sample_paths), np.array(sample_labels, dtype=np.int32)) def _sample_people(x): '''We sample people based on tf.data, where we can use transform and prefetch. Desc: 我们基于 tf.data 对人进行抽样,这样我们可以使用 transform 和 prefetch 。 ''' image_paths, num_per_class = sample_people( train_set, args.people_per_batch * (args.num_gpus - 1), args.images_per_person) labels = [] for i in range(len(num_per_class)): labels.extend([i] * num_per_class[i]) return (np.array(image_paths), np.array(labels, dtype=np.int32)) # 解析函数,将 image 的路径和 label 解析出来,对应着 image 和 label def _parse_function(filename, label): # 使用 tf.read_file() 进行读取,并使用 tf.image.decode_image() 进行转换为 tensor 的形式 file_contents = tf.read_file(filename) image = tf.image.decode_image(file_contents, channels=3) #image = tf.image.decode_jpeg(file_contents, channels=3) print(image.shape) # 判断是否对图像进行随机裁剪 if args.random_crop: print('use random crop') image = tf.random_crop(image, [args.image_size, args.image_size, 3]) else: print('Not use random crop') #image.set_shape((args.image_size, args.image_size, 3)) image.set_shape((None, None, 3)) # 将图片进行 resize ,转换为我们传入的参数的大小 image = tf.image.resize_images(image, size=(args.image_height, args.image_width)) #print(image.shape) # 判断是否进行随机水平翻转 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)) image.set_shape((args.image_height, args.image_width, 3)) # 强制转换数据类型 image = tf.cast(image, tf.float32) image = tf.subtract(image, 127.5) image = tf.div(image, 128.) #image = tf.image.per_image_standardization(image) return image, label # 将 model 目录和 log 目录先打印一下 print('Model directory: %s' % model_dir) print('Log directory: %s' % log_dir) # # 如果已经提供了 预训练好的模型 # if args.pretrained_model: # # os.path.expanduser() 把路径中包含 ~ 或者 ~user 的地方转换为用户目录 # print('Pre-trained model: %s' % os.path.expanduser(args.pretrained_model)) # # 如果提供了 lfw 数据,读取 lfw 目录中的 pairs 和 lfw 数据集中图像的 path # 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) # 全局的 step global_step = tf.Variable(0, trainable=False, name='global_step') # 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]) # the image is generated by sequence # 在 cpu 中将 训练数据集的 batch 进行拆分,分成 num_gpus 份数据 with tf.device("/cpu:0"): softmax_dataset = tf_data.Dataset.range(args.epoch_size * args.max_nrof_epochs * 100) softmax_dataset = softmax_dataset.map(lambda x: tf.py_func( _sample_people_softmax, [x], [tf.string, tf.int32])) softmax_dataset = softmax_dataset.flat_map(_from_tensor_slices) softmax_dataset = softmax_dataset.map(_parse_function, num_parallel_calls=2000) softmax_dataset = softmax_dataset.batch(args.num_gpus * single_batch_size) softmax_iterator = softmax_dataset.make_initializable_iterator() softmax_next_element = softmax_iterator.get_next() softmax_next_element[0].set_shape( (args.num_gpus * single_batch_size, args.image_height, args.image_width, 3)) softmax_next_element[1].set_shape(args.num_gpus * single_batch_size) batch_image_split = tf.split(softmax_next_element[0], args.num_gpus) batch_label_split = tf.split(softmax_next_element[1], args.num_gpus) # # 在整体数据集上选出 3 元组(triplets) # select_start_time = time.time() # # Select triplets based on the embeddings # print('Selecting suitable triplets for training') # # 修改版本的 triplets # nrof_examples = args.people_per_batch * args.images_per_person # triplets, nrof_random_negs, nrof_triplets = select_triplets(emb_array, num_per_class, # image_paths, args.people_per_batch, args.alpha) # selection_time = time.time() - start_time # print('(nrof_random_negs, nrof_triplets) = (%d, %d): time=%.3f seconds' % # (nrof_random_negs, nrof_triplets, selection_time)) # 学习率设置 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) # 优化器设置 print('Using optimizer: {}'.format(args.optimizer)) if args.optimizer == 'ADAGRAD': opt = tf.train.AdagradOptimizer(learning_rate) elif args.optimizer == 'MOM': opt = tf.train.MomentumOptimizer(learning_rate, 0.9) elif args.optimizer == 'ADAM': opt = tf.train.AdamOptimizer(learning_rate, beta1=0.9, beta2=0.999, epsilon=0.1) else: raise Exception("Not supported optimizer: {}".format( args.optimizer)) tower_losses = [] tower_cross = [] tower_dist = [] tower_reg = [] for i in range(args.num_gpus): with tf.device("/gpu:" + str(i)): with tf.name_scope("tower_" + str(i)) as scope: with slim.arg_scope([slim.model_variable, slim.variable], device="/cpu:0"): with tf.variable_scope( tf.get_variable_scope()) as var_scope: reuse = False if i == 0 else True if args.network == 'inception_resnet_v1': with tf.variable_scope(name_or_scope='', reuse=tf.AUTO_REUSE): prelogits, _ = inception_net.inference( batch_image_split[i], args.keep_probability, phase_train=phase_train_placeholder, bottleneck_layer_size=args. embedding_size, weight_decay=args.weight_decay) print(prelogits) # elif args.network == 'inception_net_v2': # with tf.variable_scope(name_or_scope='', reuse=tf.AUTO_REUSE): # prelogits, _ = inception_net_v2.inference(image_batch, args.keep_probability, # phase_train=phase_train_placeholder, bottleneck_layer_size=args.embedding_size, # weight_decay=args.weight_decay) # print(prelogits) # elif args.network == 'squeezenet': # with tf.variable_scope(name_or_scope='', reuse=tf.AUTO_REUSE): # prelogits, _ = squeezenet.inference(image_batch, args.keep_probability, # phase_train=phase_train_placeholder, bottleneck_layer_size=args.embedding_size, # weight_decay=args.weight_decay) # print(prelogits) else: raise Exception( "Not supported network: {}".format( args.network)) if args.fc_bn: prelogits = slim.batch_norm( prelogits, is_training=True, decay=0.997, epsilon=1e-5, scale=True, updates_collections=tf.GraphKeys. UPDATE_OPS, reuse=reuse, scope='softmax_bn') if args.loss_type == 'triplet': embeddings = tf.nn.l2_normalize( prelogits, 1, 1e-10, name='embeddings') # Split embeddings into anchor, positive and negative and calculate triplet loss anchor, positive, negative = tf.unstack( tf.reshape(embeddings, [-1, 3, args.embedding_size]), 3, 1) triplet_loss = facenet.triplet_loss( anchor, positive, negative, args.alpha) regularization_losses = tf.get_collection( tf.GraphKeys.REGULARIZATION_LOSSES) if args.network == 'sphere_network': print( 'reg loss using weight_decay * tf.add_n' ) reg_loss = args.weight_decay * tf.add_n( regularization_losses) else: print('reg loss using tf.add_n') # reg_loss = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES) reg_loss = tf.add_n(regularization_losses) loss = triplet_loss + reg_loss tower_losses.append(loss) tower_reg.append(reg_loss) # elif args.loss_type =='cosface': #loss = tf.add_n([cross_entropy_mean] + regularization_losses, name='total_loss') tf.get_variable_scope().reuse_variables() # 计算 total loss total_loss = tf.reduce_mean(tower_losses) total_reg = tf.reduce_mean(tower_reg) losses = {} losses['total_loss'] = total_loss losses['total_reg'] = total_reg # # 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()) grads = opt.compute_gradients(total_loss, tf.trainable_variables(), colocate_gradients_with_ops=True) apply_gradient_op = opt.apply_gradients(grads, global_step=global_step) update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS) with tf.control_dependencies(update_ops): train_op = tf.group(apply_gradient_op) # Create a saver # saver = tf.train.Saver(tf.trainable_variables(), max_to_keep=3) save_vars = [ var for var in tf.global_variables() if 'Adagrad' not in var.name and 'global_step' not in var.name ] saver = tf.train.Saver(save_vars, 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, allow_soft_placement=True)) # 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}) sess.run(softmax_iterator.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(): # 如果有预训练好的 model,那就进行 restore 操作,将模型加载进行以后的 测试阶段 if args.pretrained_model: print('Restoring pretrained model: %s' % args.pretrained_model) saver.restore(sess, os.path.expanduser(args.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, learning_rate_placeholder, phase_train_placeholder, global_step, losses, train_op, summary_op, summary_writer, 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, 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): 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) 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 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): 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) 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) train_set = facenet.get_dataset(args.data_dir) 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)) # # 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) with tf.Graph().as_default(): tf.set_random_seed(args.seed) global_step = tf.Variable(0, trainable=False, name='global_step') # Placeholders for the learning rate, batch_size, phase_train, image_path, labels 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]) # 读取数据的线程数,将下面改为 multi_gpu 运行的版本 nrof_preprocess_threads = 4 images_and_labels_all = [] for _ in range(nrof_preprocess_threads): for gpu in range(args.num_gpus): images_and_labels = [] # 每次都从 queue 中将数据 dequeue 出来 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_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]) images_and_labels_all.append(images_and_labels) # 将数据整理,并适用于下面的多 gpu 运行 image_batch_split = [] label_batch_split = [] # label_extend = [] for i in range(args.num_gpus): image_batch, labels_batch = tf.train.batch_join( images_and_labels_all[i], 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') labels_batch = tf.identity(labels_batch, 'label_batch') image_batch_split.append(image_batch) label_batch_split.append(labels_batch) # label_extend.extend(labels_batch) 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) # print('Using optimizer: {}'.format(args.optimizer)) # if args.optimizer == 'ADAGRAD': # opt = tf.train.AdagradOptimizer(learning_rate) # elif args.optimizer == 'MOM': # opt = tf.train.MomentumOptimizer(learning_rate, rho=0.9, epsilon=1e-6) # elif args.optimizer=='ADAM': # opt = tf.train.AdamOptimizer(learning_rate, beta1=0.9, beta2=0.999, epsilon=0.1) # elif args.optimizer=='RMSPROP': # opt = tf.train.RMSPropOptimizer(learning_rate, decay=0.9, momentum=0.9, epsilon=1.0) # elif args.optimizer=='MOM': # opt = tf.train.MomentumOptimizer(learning_rate, 0.9, use_nesterov=True) # else: # raise Exception('Not supported optimizer: {}'.format(args.optimizer)) # 在这部分进行 multi_gpu print('Building training graph....') tower_losses = [] tower_triplet = [] tower_reg= [] # embeddings_extend = [] embeddings_split = [] for i in range(args.num_gpus): with tf.device("/gpu:" + str(i)): with tf.name_scope("tower_" + str(i)) as scope: with tf.variable_scope(tf.get_variable_scope()) as var_scope: # Build the inference graph with tf.variable_scope(name_or_scope='', reuse=tf.AUTO_REUSE): # # Dequeues one batch for one tower # image_batch_de, label_batch_de = batch_queue.dequeue() prelogits, _ = network.inference(image_batch_split[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') # embeddings_extend.extend(embeddings) embeddings_split.append(embeddings) # Split embeddings into anchor, postive and negative and calculate triplet loss anchor, positive, negative = tf.unstack(tf.reshape(embeddings, [-1,3,args.embedding_size]), 3, 1) triplet_loss_split = facenet.triplet_loss(anchor, positive, negative, args.alpha) regularization_losses = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES) tower_triplet.append(triplet_loss_split) loss = triplet_loss_split + tf.add_n(regularization_losses) tower_losses.append(loss) tower_reg.append(regularization_losses) # 同名变量可以重用 tf.get_variable_scope().reuse_variables() total_loss = tf.reduce_mean(tower_losses) total_reg = tf.reduce_mean(tower_reg) losses = {} losses['total_loss'] = total_loss losses['total_reg'] = total_reg # # 计算 embeddings 的均值 # tmp_embeddings = None # for j in range(arg.num_gpus): # if j > 0: # tmp_embeddings += embeddings_split[j] # else: # tmp_embeddings = embeddings_split[j] # embeddings = tmp_embeddings / args.num_gpus # 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()) # grads = opt.compute_gradients(total_loss,tf.trainable_variables(),colocate_gradients_with_ops=True) # apply_gradient_op = opt.apply_gradients(grads,global_step=global_step) # update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS) # with tf.control_dependencies(update_ops): # train_op = tf.group(apply_gradient_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)) # 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) 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' % args.pretrained_model) saver.restore(sess, os.path.expanduser(args.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 multi gpus for one epoch epoch_start_time = time.time() # for i in range(args.num_gpus): train_multi_gpu(args, sess, train_set, epoch, image_paths_placeholder, labels_placeholder, label_batch_split[0], label_batch_split[1], batch_size_placeholder, learning_rate_placeholder, phase_train_placeholder, enqueue_op, input_queue, global_step, embeddings_split[0], embeddings_split[1], losses['total_loss'], losses['total_reg'], train_op, summary_op, summary_writer, args.learning_rate_schedule_file, args.embedding_size) print('The %dth epoch running time is %.3f seconds!!!' %(epoch, time.time()-epoch_start_time)) # # Train for one epoch # train(args, sess, epoch, # learning_rate_placeholder, phase_train_placeholder, global_step, # losses, train_op, summary_op, summary_writer, 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) return model_dir
def main(args): img_mean = np.array([134.10714722, 102.52040863, 87.15436554]) img_stddev = np.sqrt(np.array([3941.30175781, 2856.94287109, 2519.35791016])) vae_def = importlib.import_module(args.vae_def) vae = vae_def.Vae(args.latent_var_size) gen_image_size = vae.get_image_size() subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S') 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) log_file_name = os.path.join(model_dir, 'logs.h5') # Write arguments to a text file facenet.write_arguments_to_file(args, os.path.join(model_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, model_dir, ' '.join(sys.argv)) with tf.Graph().as_default(): tf.set_random_seed(args.seed) global_step = tf.Variable(0, trainable=False) train_set = facenet.get_dataset(args.data_dir) image_list, _ = facenet.get_image_paths_and_labels(train_set) # Create the input queue input_queue = tf.train.string_input_producer(image_list, shuffle=True) nrof_preprocess_threads = 4 image_per_thread = [] for _ in range(nrof_preprocess_threads): file_contents = tf.read_file(input_queue.dequeue()) image = tf.image.decode_image(file_contents, channels=3) image = tf.image.resize_image_with_crop_or_pad(image, args.input_image_size, args.input_image_size) image.set_shape((args.input_image_size, args.input_image_size, 3)) image = tf.cast(image, tf.float32) #pylint: disable=no-member image_per_thread.append([image]) images = tf.train.batch_join( image_per_thread, batch_size=args.batch_size, capacity=4 * nrof_preprocess_threads * args.batch_size, allow_smaller_final_batch=False) # Normalize images_norm = (images-img_mean) / img_stddev # Resize to appropriate size for the encoder images_norm_resize = tf.image.resize_images(images_norm, (gen_image_size,gen_image_size)) # Create encoder network mean, log_variance = vae.encoder(images_norm_resize, True) epsilon = tf.random_normal((tf.shape(mean)[0], args.latent_var_size)) std = tf.exp(log_variance/2) latent_var = mean + epsilon * std # Create decoder network reconstructed_norm = vae.decoder(latent_var, True) # Un-normalize reconstructed = (reconstructed_norm*img_stddev) + img_mean # Create reconstruction loss if args.reconstruction_loss_type=='PLAIN': images_resize = tf.image.resize_images(images, (gen_image_size,gen_image_size)) reconstruction_loss = tf.reduce_mean(tf.reduce_sum(tf.pow(images_resize - reconstructed,2))) elif args.reconstruction_loss_type=='PERCEPTUAL': network = importlib.import_module(args.model_def) reconstructed_norm_resize = tf.image.resize_images(reconstructed_norm, (args.input_image_size,args.input_image_size)) # Stack images from both the input batch and the reconstructed batch in a new tensor shp = [-1] + images_norm.get_shape().as_list()[1:] input_images = tf.reshape(tf.stack([images_norm, reconstructed_norm_resize], axis=0), shp) _, end_points = network.inference(input_images, 1.0, phase_train=False, bottleneck_layer_size=128, weight_decay=0.0) # Get a list of feature names to use for loss terms feature_names = args.loss_features.replace(' ', '').split(',') # Calculate L2 loss between original and reconstructed images in feature space reconstruction_loss_list = [] for feature_name in feature_names: feature_flat = slim.flatten(end_points[feature_name]) image_feature, reconstructed_feature = tf.unstack(tf.reshape(feature_flat, [2,args.batch_size,-1]), num=2, axis=0) reconstruction_loss = tf.reduce_mean(tf.reduce_sum(tf.pow(image_feature-reconstructed_feature, 2)), name=feature_name+'_loss') reconstruction_loss_list.append(reconstruction_loss) # Sum up the losses in for the different features reconstruction_loss = tf.add_n(reconstruction_loss_list, 'reconstruction_loss') else: pass # Create KL divergence loss kl_loss = kl_divergence_loss(mean, log_variance) kl_loss_mean = tf.reduce_mean(kl_loss) total_loss = args.alfa*kl_loss_mean + args.beta*reconstruction_loss learning_rate = tf.train.exponential_decay(args.initial_learning_rate, global_step, args.learning_rate_decay_steps, args.learning_rate_decay_factor, staircase=True) # Calculate gradients and make sure not to include parameters for the perceptual loss model opt = tf.train.AdamOptimizer(learning_rate) grads = opt.compute_gradients(total_loss, var_list=get_variables_to_train()) # Apply gradients apply_gradient_op = opt.apply_gradients(grads, global_step=global_step) with tf.control_dependencies([apply_gradient_op]): train_op = tf.no_op(name='train') # Create a saver saver = tf.train.Saver(tf.trainable_variables(), max_to_keep=3) facenet_saver = tf.train.Saver(get_facenet_variables_to_restore()) # Start running operations on the Graph gpu_memory_fraction = 1.0 gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=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()) coord = tf.train.Coordinator() tf.train.start_queue_runners(coord=coord, sess=sess) with sess.as_default(): if args.reconstruction_loss_type=='PERCEPTUAL': if not args.pretrained_model: raise ValueError('A pretrained model must be specified when using perceptual loss') pretrained_model_exp = os.path.expanduser(args.pretrained_model) print('Restoring pretrained model: %s' % pretrained_model_exp) facenet_saver.restore(sess, pretrained_model_exp) log = { 'total_loss': np.zeros((0,), np.float), 'reconstruction_loss': np.zeros((0,), np.float), 'kl_loss': np.zeros((0,), np.float), 'learning_rate': np.zeros((0,), np.float), } step = 0 print('Running training') while step < args.max_nrof_steps: start_time = time.time() step += 1 save_state = step>0 and (step % args.save_every_n_steps==0 or step==args.max_nrof_steps) if save_state: _, reconstruction_loss_, kl_loss_mean_, total_loss_, learning_rate_, rec_ = sess.run( [train_op, reconstruction_loss, kl_loss_mean, total_loss, learning_rate, reconstructed]) img = facenet.put_images_on_grid(rec_, shape=(16,8)) misc.imsave(os.path.join(model_dir, 'reconstructed_%06d.png' % step), img) else: _, reconstruction_loss_, kl_loss_mean_, total_loss_, learning_rate_ = sess.run( [train_op, reconstruction_loss, kl_loss_mean, total_loss, learning_rate]) log['total_loss'] = np.append(log['total_loss'], total_loss_) log['reconstruction_loss'] = np.append(log['reconstruction_loss'], reconstruction_loss_) log['kl_loss'] = np.append(log['kl_loss'], kl_loss_mean_) log['learning_rate'] = np.append(log['learning_rate'], learning_rate_) duration = time.time() - start_time print('Step: %d \tTime: %.3f \trec_loss: %.3f \tkl_loss: %.3f \ttotal_loss: %.3f' % (step, duration, reconstruction_loss_, kl_loss_mean_, total_loss_)) if save_state: print('Saving checkpoint file') checkpoint_path = os.path.join(model_dir, 'model.ckpt') saver.save(sess, checkpoint_path, global_step=step, write_meta_graph=False) print('Saving log') with h5py.File(log_file_name, 'w') as f: for key, value in log.iteritems(): f.create_dataset(key, data=value)
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 = time.strftime('%Y%m%d-%H%M%S', time.localtime()) 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')) np.random.seed(seed=args.seed) train_set = utils.___get_dataset(args.file_exp) print('Model directory: %s' % model_dir) print('Log directory: %s' % log_dir) # 如果选择了预训练的模型的话,这里我们会选取facenet的网络作预训练 if args.pretrained_model: print('Pre-trained model: %s' % os.path.expanduser(args.pretrained_model)) 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 其实就是 路径/label,三元组,也就是make好pair的 # label的必要性? 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 = [] # 这里其实就是对数据进行预处理,通过从queue中获取到数据,读取路径下的图片并且预处理后做成一个list 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_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]) # print('image input successfully!') # 其实就是对于list里面进行获取batch 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) # 返回一个节点,那么就可以做到更新节点,每次产生新的batch image_batch = tf.identity(image_batch, 'image_batch') image_batch = tf.identity(image_batch, 'input') labels_batch = tf.identity(labels_batch, 'label_batch') # Build the inference graph # 网络的参数设置,返回的是输出的dropout和fc(bottleneck)之后的输出,那么label到底作用在哪里 prelogits, _ = network.inference( image_batch, args.keep_probability, phase_train=phase_train_placeholder, bottleneck_layer_size=args.embedding_size, weight_decay=args.weight_decay) # embedding 其实就是对于softmax进行距离的l2正则化 embeddings = tf.nn.l2_normalize(prelogits, 1, 1e-10, name='embeddings') # 把我们输入进去的图片集得到的结果拆分为三元组 # Split embeddings into anchor, positive and negative and calculate triplet loss anchor, positive, negative = tf.unstack( tf.reshape(embeddings, [-1, 3, args.embedding_size]), 3, 1) triplet_loss = facenet.triplet_loss(anchor, positive, negative, args.alpha) # get到了,把learning rate 坐成一个placeholder就可以动态调整learning rate啦 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([triplet_loss] + 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()) # 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() config.gpu_options.allow_growth = True sess = tf.Session(config=config) # 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}) # print('variable inti successfully!') summary_writer = tf.summary.FileWriter(log_dir, sess.graph) # 线程管理器 coord = tf.train.Coordinator() tf.train.start_queue_runners(coord=coord, sess=sess) # print('begin to train!') with sess.as_default(): # 读取预训练模型 if args.pretrained_model: print('Restoring pretrained model: %s' % args.pretrained_model) saver.restore(sess, os.path.expanduser(args.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 # print('train another 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, input_queue, global_step, embeddings, total_loss, train_op, summary_op, summary_writer, args.learning_rate_schedule_file, args.embedding_size, anchor, positive, negative, triplet_loss) # 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 generate_input_fn(set, mode=tf.estimator.ModeKeys.EVAL, batch_size=1): def parse_function(filename, label): image_string = tf.read_file(filename) # Don't use tf.image.decode_image, or the output shape will be undefined image = tf.image.decode_jpeg(image_string, channels=3) # This will convert to float values in [0, 1] image = tf.image.convert_image_dtype(image, tf.float32) image = tf.image.resize_images(image, [args.image_size, args.image_size]) return image, label def _input_fn(): is_training = (mode == tf.estimator.ModeKeys.TRAIN) image_list, label_list = facenet.get_image_paths_and_labels(set) assert len(image_list)>0, 'The training set should not be empty' dataset = tf.data.Dataset.from_tensor_slices((filenames, labels)) dataset = dataset.shuffle(len(filenames)) dataset = dataset.map(parse_function, num_parallel_calls=args.nrof_preprocess_threads) if is_training: dataset = dataset.map(train_preprocess, num_parallel_calls=args.nrof_preprocess_threads) dataset = dataset.batch(args.batch_size) dataset = dataset.prefetch(args.prefetch_value) features = {'images': images} return features, label_list return _input_fn def get_feature_columns(): feature_columns = { 'images': tf.feature_column.numeric_column('images', (IMAGE_HEIGHT, IMAGE_WIDTH, IMAGE_DEPTH)), } return feature_columns 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) 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) 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) 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) 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)) params={'log_dir':log_dir,'stat_file_name':stat_file_name,'stat':stat} with tf.Graph().as_default(): # trainset, valset # Create a queue that produces indices into the image_list and label_list 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') # Start running operations on the Graph. gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=args.gpu_memory_fraction,allow_growth=True) config=tf.ConfigProto(gpu_options=gpu_options, log_device_placement=False) config=tf.estimator.RunConfig(session_config=config,save_checkpoints_steps=args.save_checkpoints_steps, tf_random_seed=args.seed, model_dir=args.model_dir) estimator = tf.estimator.Estimator( model_fn=model_fn, model_dir=FLAGS.model_dir, config=tf.contrib.learn.RunConfig(session_config=config),params=params) with sess.as_default(): if pretrained_model: print('Restoring pretrained model: %s' % pretrained_model) saver.restore(sess, pretrained_model) 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): 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): network = importlib.import_module(args.model_def) subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S') + args.experiment_name 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) class_name = ['smile','oval_face','5_ocloc_shadow','bald','archied_eyebrows','Big_lips', 'Big_Nose'] class_num = len(class_name) class_index = [31,25,0,4,1,6,7] all_image_list = [] all_label_list = [] for i in range(class_num): image_list = [] label_list = [] train_set = facenet.get_sub_category_dataset(args.data_dir, class_index[i]) image_list_p, label_list_p = facenet.get_image_paths_and_labels_triplet(train_set[0], args) image_list_n, label_list_n = facenet.get_image_paths_and_labels_triplet(train_set[1], args) image_list.append(image_list_p) image_list.append(image_list_n) label_list.append(label_list_p) label_list.append(label_list_n) all_image_list.append(image_list) all_label_list.append(label_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)) 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) image_size = args.image_size batch_size = args.batch_size 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') image_placeholder = tf.placeholder(tf.float32, shape=(batch_size, image_size, image_size,3), name='images') labels_placeholder = tf.placeholder(tf.int64, shape=(batch_size,3), name='labels') code_placeholder = tf.placeholder(tf.float32, shape=(batch_size,class_num,1,1), name='code') image_batch = normalized_image(image_placeholder) code_batch = code_placeholder control_code = tf.tile(code_placeholder,[1,1,args.embedding_size,1]) mask_array = np.ones((1 ,class_num,args.embedding_size,1),np.float32) # for i in range(class_num): # mask_array[:,i,(args.embedding_size/class_num)*i:(args.embedding_size/class_num)*(i+1)] = 1 mask_tensor = tf.get_variable('mask', dtype=tf.float32, trainable=args.learned_mask, initializer=tf.constant(mask_array)) mask_tensor = tf.tile(mask_tensor,[batch_size,1,1,1]) control_code = tf.tile(code_placeholder,[1,1,args.embedding_size,1]) mask_out = tf.multiply(mask_tensor, control_code) mask_out = tf.reduce_sum(mask_out,axis=1) mask_out = tf.squeeze(mask_out) mask_out = tf.nn.relu(mask_out) mask0_array = np.ones((1, class_num, 128, 1), np.float32) mask0_tensor = tf.get_variable('mask0', dtype=tf.float32, trainable=args.learned_mask, initializer=tf.constant(mask0_array)) mask0_tensor = tf.tile(mask0_tensor, [batch_size, 1, 1, 1]) control0_code = tf.tile(code_placeholder,[1,1,128,1]) mask0_out = tf.multiply(mask0_tensor, control0_code) mask0_out = tf.reduce_sum(mask0_out, axis=1) mask0_out = tf.squeeze(mask0_out) mask0_out = tf.nn.relu(mask0_out) mask0_out = tf.expand_dims(mask0_out,1) mask0_out = tf.expand_dims(mask0_out,1) mask1_array = np.ones((1, class_num, 128, 1), np.float32) mask1_tensor = tf.get_variable('mask1', dtype=tf.float32, trainable=args.learned_mask, initializer=tf.constant(mask1_array)) mask1_tensor = tf.tile(mask1_tensor, [batch_size, 1, 1, 1]) control1_code = tf.tile(code_placeholder,[1,1,128,1]) mask1_out = tf.multiply(mask1_tensor, control1_code) mask1_out = tf.reduce_sum(mask1_out, axis=1) mask1_out = tf.squeeze(mask1_out) mask1_out = tf.nn.relu(mask1_out) mask1_out = tf.expand_dims(mask1_out,1) mask1_out = tf.expand_dims(mask1_out,1) # Build the inference graph prelogits, _ = network.inference(image_batch, mask0_out, mask1_out, args.keep_probability, phase_train=phase_train_placeholder, bottleneck_layer_size=args.embedding_size, weight_decay=args.weight_decay) embeddings_pre = tf.multiply(mask_out, prelogits) embeddings = tf.nn.l2_normalize(embeddings_pre, 1, 1e-10, name='embeddings') anchor_index = list(range(0,batch_size,3)) positive_index = list(range(1,batch_size,3)) negative_index = list(range(2,batch_size,3)) a_indice = tf.constant(np.array(anchor_index)) p_indice = tf.constant(np.array(positive_index)) n_indice = tf.constant(np.array(negative_index)) anchor = tf.gather(embeddings,a_indice) positive = tf.gather(embeddings,p_indice) negative = tf.gather(embeddings,n_indice) triplet_loss = facenet.triplet_loss(anchor, positive, negative, args.alpha) 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([triplet_loss] + 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()) # Create a saver trainable_variables = tf.global_variables() saver = tf.train.Saver(trainable_variables, max_to_keep=35) # 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) 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' % args.pretrained_model) saver.restore(sess, os.path.expanduser(args.pretrained_model)) # Training and validation loop epoch = 0 Accuracy = [0] while epoch < args.max_nrof_epochs: step = sess.run(global_step, feed_dict=None) # epoch = step // args.epoch_size # Train for one epoch code_list = [] triplets_list = [] max_num = 32768 if (epoch+1)%args.lr_epoch == 0: args.learning_rate = 0.1*args.learning_rate if args.random_trip: for i in range(class_num): code = np.zeros((batch_size, class_num, 1, 1), np.float32) _class = i code[:, _class, :, :] = 1 Triplets = triplet_random(args, sess, all_image_list[i], all_image_list, epoch, image_placeholder, batch_size_placeholder, learning_rate_placeholder, phase_train_placeholder, global_step, embeddings, total_loss, train_op, summary_op, summary_writer, args.learning_rate_schedule_file, args.embedding_size, anchor, positive, negative, triplet_loss, max_num) triplets_list.append(Triplets) code_list.append(code) else: for i in range(class_num): code = np.zeros((batch_size, 1, 1, 1), np.float32) _class = i if _class > 3: _class = 3 code[:, :, :, :] = _class print(class_name[i]) Triplets = triplet(args, sess, all_image_list[i], epoch, image_placeholder, code_placeholder, batch_size_placeholder, learning_rate_placeholder, phase_train_placeholder, global_step, embeddings, total_loss, train_op, summary_op, summary_writer, args.learning_rate_schedule_file, args.embedding_size, anchor, positive, negative, triplet_loss,code) triplets_num = len(Triplets) triplets_list.append(Triplets) code_list.append(code) train(args, sess, image_list, epoch, image_placeholder, code_placeholder, batch_size_placeholder, learning_rate_placeholder, phase_train_placeholder, global_step, embeddings, total_loss, train_op, summary_op, summary_writer, args.learning_rate_schedule_file, args.embedding_size, anchor, positive, negative, triplet_loss, triplets_list, code_list, model_dir, Accuracy) if (epoch+1)%2 == 0: Accuracy = test(args, sess, image_list, epoch, image_placeholder,code_placeholder, batch_size_placeholder, learning_rate_placeholder, phase_train_placeholder, global_step, embeddings, total_loss, train_op, summary_op, summary_writer, args.learning_rate_schedule_file, args.embedding_size, anchor, positive, negative, triplet_loss, triplets_list, Accuracy) # Save variables and the metagraph if it doesn't exist already model_name = 'epoch' + str(epoch+1) print(model_dir) if (epoch+1) > 0 : if (epoch +1)%2 == 0: save_variables_and_metagraph(sess, saver, summary_writer, model_dir, model_name, step) print('models are saved in ', os.path.join(model_dir, model_name)) epoch = epoch + 1 sess.close() 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) np.random.seed(seed=args.seed) random.seed(args.seed) # load training dataset train_set = facenet.get_dataset(args.data_dir) if args.filter_min_nrof_images_per_class > 0: train_set = clean_dataset(train_set, args.filter_min_nrof_images_per_class) nrof_classes = len(train_set) pretrained_model = None if args.pretrained_model: pretrained_model = os.path.expanduser(args.pretrained_model) print('Pre-trained model: %s' % pretrained_model) # load lfw dataset for validation 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] with tf.device('/cpu: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') 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=1000000, 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 = args.nrof_preprocess_threads images_and_labels = [] for _ in range(nrof_preprocess_threads): images_and_labels = distorted_inputs(images_and_labels, input_queue, args) image_batch, label_batch = tf.train.batch_join( images_and_labels, batch_size=args.batch_size, enqueue_many=True, capacity=4 * nrof_preprocess_threads * args.batch_size, allow_smaller_final_batch=True) print(image_batch) # perfetching queue not working properly yet batch_queue = slim.prefetch_queue.prefetch_queue( [image_batch, label_batch], dynamic_pad=True, capacity=4) image_batch, label_batch = batch_queue.dequeue() 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, reuse=None) embeddings = tf.nn.l2_normalize(prelogits, 1, 1e-10, name='embeddings') print(embeddings) nrof_classes = len(train_set) weights = tf.get_variable( 'softmax_weights', shape=(args.embedding_size, nrof_classes), dtype=tf.float32, initializer=tf.variance_scaling_initializer(), regularizer=slim.l2_regularizer(args.weight_decay), trainable=True) weights = tf.nn.l2_normalize(weights, 0, name='norm_weights') if args.keep_probability < 1.0: scaled_prelogits = slim.dropout( scaled_prelogits, args.keep_probability, is_training=phase_train_placeholder, scope='Dropout') logits = facenet.combined_loss( embeddings, label_batch, nrof_classes, weights, scale_factor=args.l2_constrained_scale_factor, m1=args.m1, m2=args.m2) # Add norm loss if args.norm_loss_factor > 0.0: norm_loss = args.norm_loss_factor * tf.reduce_mean( tf.pow( tf.norm(prelogits, axis=1) - args.l2_constrained_scale_factor, 2)) tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES, norm_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.trainable_variables(), args.num_gpus, args.log_histograms) #/////////////////////////////////////////////////////////////////////////////////// # Create a saver if args.finetune: print("finetune model") all_vars = tf.trainable_variables() vars_to_restore = [ v for v in all_vars if not v.name.startswith('Logits') ] else: vars_to_restore = tf.trainable_variables() saver = tf.train.Saver(vars_to_restore, max_to_keep=40) # Build the summary operation based on the TF collection of Summaries. summary_op = tf.summary.merge_all() # create corresponding model and log directories 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) print('Model directory: %s' % model_dir) print('Log directory: %s' % log_dir) # Write arguments to a text file facenet.write_arguments_to_file( args, os.path.join(model_dir, 'arguments.txt')) #============================================================================================================= # 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, allow_soft_placement=True, log_device_placement=False)) sess.run(tf.global_variables_initializer()) sess.run(tf.local_variables_initializer()) save_graph_def(sess, model_dir) 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, global_step, total_loss, train_op, summary_op, summary_writer, regularization_losses, args.learning_rate_schedule_file, learning_rate, log_dir) # 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, actual_issame, args.lfw_batch_size, args.lfw_nrof_folds, log_dir, step, summary_writer) return model_dir
def main(args): #此处导入的是:models.inception_resnet_v1模型,以后再看怎么更改模型 network = importlib.import_module(args.model_def) #用当前日期来命名模型 subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S') #日志保存在c:\\users\\Administrator\logs\facenet\ 文件夹里 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) # 把参数写在日志文件中 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__)) #arg_string:'E:/facenet/train_tripletloss.py' output_dir:'C:\\Users\\Administrator/logs/facenet\\20180314-181556' facenet.store_revision_info(src_path, log_dir, ' '.join(sys.argv)) np.random.seed(seed=args.seed) #获取数据集,train_set是包含文件路径与标签的集合 #先输入一个父路径 path:'E:/facenet/data/lfw_160',接着输入每个子路径 # 输出:一个list,每个元素是一个ImageClass,里边包含图片地址的list(image_paths)以及对应的人名(name)[以后可能会直接调用这几个属性] train_set = facenet.get_dataset(args.data_dir) 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)) 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语句适用于对资源进行访问的场合,确保使用过程中是否发生异常都会执行必要嘚瑟“清理”操作 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') #新建一个队列,数据流操作,fifo先入先出 input_queue = data_flow_ops.FIFOQueue(capacity=100000, dtypes=[tf.string, tf.int64], shapes=[(3, ), (3, )], shared_name=None, name=None) #enqueue_many返回的是一个操作 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.unstack(filenames): file_contents = tf.read_file(filename) image = tf.image.decode_image(file_contents, channels=3) 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) image_batch = tf.identity(image_batch, 'image_batch') image_batch = tf.identity(image_batch, 'input') labels_batch = tf.identity(labels_batch, 'label_batch') # Build the inference (构造计算图) #其中prelogits是最后一层的输出 prelogits, _ = network.inference( image_batch, args.keep_probability, phase_train=phase_train_placeholder, bottleneck_layer_size=args.embedding_size, weight_decay=args.weight_decay) #L2正则化(范化)函数 # embeddings = tf.nn.l2_normalize(输入向量, L2范化的维数(取0(列L2范化)或1(行L2范化)), 泛化的最小值边界, name='embeddings') embeddings = tf.nn.l2_normalize(prelogits, 1, 1e-10, name='embeddings') # Split embeddings into anchor, positive and negative and calculate triplet loss anchor, positive, negative = tf.unstack( tf.reshape(embeddings, [-1, 3, args.embedding_size]), 3, 1) triplet_loss = facenet.triplet_loss(anchor, positive, negative, args.alpha) #将指数衰减应用在学习率上 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) # 计算损失 regularization_losses = tf.get_collection( tf.GraphKeys.REGULARIZATION_LOSSES) #构建L2正则化 total_loss = tf.add_n([triplet_loss] + 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()) # Create a saver创建一个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)) # 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}) #写log文件 summary_writer = tf.summary.FileWriter(log_dir, sess.graph) #获取线程坐标 coord = tf.train.Coordinator() #将队列中的多用sunner开始执行 tf.train.start_queue_runners(coord=coord, sess=sess) with sess.as_default(): if args.pretrained_model: print('Restoring pretrained model: %s' % args.pretrained_model) #saver.restore(sess, os.path.expanduser(args.pretrained_model)) facenet.load_model(args.pretrained_model) # Training and validation loop epoch = 0 #将所有数据过一遍的次数 默认500 while epoch < args.max_nrof_epochs: step = sess.run(global_step, feed_dict=None) #epoch_size是一个epoch中批的个数,这个epoch是全局的批处理个数以一个epoch中。。。这个epoch将用于求学习率 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, input_queue, global_step, embeddings, total_loss, train_op, summary_op, summary_writer, args.learning_rate_schedule_file, args.embedding_size, anchor, positive, negative, triplet_loss) # 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): # 导入 model_def 指代的网络结构 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): os.makedirs(model_dir) # 将 参数 写入 text 文件中 facenet.write_arguments_to_file(args, os.path.join(log_dir, 'arguments.txt')) # 存储一些 git 修订信息到 log 文件夹的 text 文件中 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) # 打印 Model 存储目录 和 Log 存储目录 print('Model directory: %s' % model_dir) print('Log directory: %s' % log_dir) # 检测是否 已经有训练完成的 model 了 # if args.pretrained_model: # print('Pre-trained model: %s' % os.path.expanduser(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) # print('lfw_paths_len^^^^^^^^^^^^^^', len(lfw_paths)) # print('lfw_paths^^^^^^^^^^^^^^', lfw_paths) # print('actual_issame_len^^^^^^^^^^', len(actual_issame)) # print('actual_issame^^^^^^^^^^', actual_issame) 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.unstack(filenames): file_contents = tf.read_file(filename) image = tf.image.decode_image(file_contents, channels=3) 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]) # tf.train.batch_join() --- 运行 tensor list 来填充队列,以创建样本的批次。返回与 tensors_list[i] 有着相同数量和类型的张量的列的列表或者字典。 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) # tf.identity(input, name=None) --- 返回一个与 input 具有相同 shape 和 内容的 tensor image_batch = tf.identity(image_batch, 'image_batch') image_batch = tf.identity(image_batch, 'input') labels_batch = tf.identity(labels_batch, 'label_batch') # 首先在 一个 gpu 上运行 network 的 inference graph with tf.device('/cpu:0'): embeddings = [] anchors = [] positives = [] negatives = [] # 在 gpu 0 上进行运行 inference graph with tf.device('/gpu:2'): # 创建 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) # l2 normalize embeddings = tf.nn.l2_normalize(prelogits, 1, 1e-10, name='embeddings') # ------ print start ----------- print('embeddings-------', embeddings) # ------ print end ------------- # Split embedding into anchor, positive and negative and calculate teiplet loss anchor, positive, negative = tf.unstack( tf.reshape(embeddings, [-1, 3, args.embedding_size]), 3, 1) # ------------------- print start --------------------------------- # print('@@@@@@@@@@@@wwww', anchor.get_shape()) # print('############wwww', positive.get_shape()) # print('$$$$$$$$$$$$wwww', negative.get_shape()) # ------------------- print end ----------------------------------- # 接着进行拆分,将 anchor, positive, negative 三组数据进行拆分,拆分成对应着 num_gpus 的份数 # 但是这里有一个限制,所切分的 tensor 的维度,必须可以被 切分成的份数 整除, 所以直接使用 tf.split() 会报错 for i in range(args.num_gpus): anchors_tmp = anchor[i::args.num_gpus] anchors.append(anchors_tmp) positives_tmp = positive[i::args.num_gpus] positives.append(positives_tmp) negatives_tmp = negative[i::args.num_gpus] negatives.append(negatives_tmp) # -------print start 查看 emdedding 和 相对应的 3 个 anchors,positive,negative # print('wowowowoowowow', embeddings.get_shape()) # print('wowninininini_anchors0', anchors[0].get_shape()) # print('wowninininini_anchors1', anchors[1].get_shape()) # print('wowninininini_positives0', positives[0].get_shape()) # print('wowninininini_positives1', positives[1].get_shape()) # print('wowninininini_negatives0', negatives[0].get_shape()) # print('wowninininini_negatives1', negatives[1].get_shape()) # ------ print end ------------------------- # 在这部分修改为 multi-gpu 训练 # 即 将每一个 batch 均分,然后在多个 gpu 上来计算对应的 triplet_loss ,之后汇总得到和,求取平均,得到一个 batch_size 的 loss # tower_losses = [] # tower_triplets = [] # tower_reg = [] # for i in range(args.num_gpus): # with tf.device("/gpu:" + str(i)): # with tf.name_scope("tower_" + str(i)) as scope: # with tf.variable_scope(tf.get_variable_scope()) as var_scope: # triplet_loss_split = facenet.triplet_loss(anchors[i], positive[i], negative[i], args.alpha) # regularization_loss = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES) # tower_triplets.append(triplet_loss_split) # loss = triplet_loss_split + tf.add_n(regularization_loss) # tower_losses.append(loss) # tower_reg.append(regularization_loss) # # 计算 multi gpu 运行完成得到的 loss # total_loss = tf.reduce_mean(tower_losses) # total_reg = tf.reduce_mean(tower_reg) # losses = {} # losses['total_loss'] = total_loss # losses['total_reg'] = total_reg # # 创建 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) # embeddings = tf.nn.l2_normalize(prelogits, 1, 1e-10, name='embeddings') # # Split embedding into anchor, positive and negative and calculate teiplet loss # anchor, positive, negative = tf.unstack(tf.reshape(embeddings, [-1, 3, args.embedding_size]), 3, 1) 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) # # 计算 total losses # regularization_losses = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES) # total_loss = tf.add_n([triplet_loss] + regularization_losses, name='total_loss') # 创建 使用 1 个 batch 来训练模型并更新其中参数的 Graph # train_op = facenet.train(total_loss, global_step, args.optimizer, # learning_rate, args.moving_average_decay, tf.global_variables()) # 在多 gpu 上训练的改版 train_op, total_loss = facenet.train_multi_gpu( args.num_gpus, anchors, positives, negatives, args.alpha, global_step, args.optimizer, learning_rate, args.moving_average_decay, tf.global_variables()) # Create a saver saver = tf.train.Saver(tf.trainable_variables(), max_to_keep=3) # 基于 TF Summaries 的 collection 创建一个 summary opration summary_op = tf.summary.merge_all() # 在 Graph 启动 running operations gpu_options = tf.GPUOptions( per_process_gpu_memory_fraction=args.gpu_memory_fraction) sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options, allow_soft_placement=True)) # 初始化 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) 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' % args.pretrained_model) # saver.restore(sess, os.path.expanduser(args.pretrained_model)) # facenet.load_model(args.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 # --- print start --- print('@@@@@@@@@@@@@@args.embedding_size', args.embedding_size) print('@@@@@@@@@@@@@@anchor', anchor, anchor.get_shape()) print('@@@@@@@@@@@@@@positive', positive, positive.get_shape()) print('@@@@@@@@@@@@@@negative', negative, negative.get_shape()) print('@@@@@@@@@@@@@@total_loss', total_loss, total_loss.get_shape()) # --- print end ----- epoch_start_time = time.time() # origin # train(args, sess, train_set, epoch, image_paths_placeholder, labels_placeholder, labels_batch, # batch_size_placeholder, learning_rate_placeholder, phase_train_placeholder, enqueue_op, input_queue, global_step, # embeddings, total_loss, train_op, summary_op, summary_writer, args.learning_rate_schedule_file, # args.embedding_size, anchor, positive, negative, total_loss) # print('第 %d 个 epoch跑完,花费时间 %.3f' %(epoch, (time.time() - epoch_start_time))) # modified training train_multi_gpus( args, sess, train_set, epoch, image_paths_placeholder, labels_placeholder, labels_batch, batch_size_placeholder, learning_rate_placeholder, phase_train_placeholder, enqueue_op, input_queue, global_step, embeddings, anchors, positives, negatives, train_op, summary_op, summary_writer, args.learning_rate_schedule_file, args.embedding_size) print('第 %d 个 epoch跑完,花费时间 %.3f' % (epoch, (time.time() - epoch_start_time))) # 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) 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): 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) nrof_classes = len(dataset) 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) learning_rate_placeholder = tf.placeholder(tf.float32, name='learning_rate') batch_size_placeholder = tf.placeholder(tf.int32, name='batch_size') 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=200000, dtypes=[tf.string, tf.int64], shapes=[(3, ), (3, )], shared_name=None, name=None) enqueue_op = input_queue.enqueue_many( [image_paths_placeholder, labels_placeholder], name='enqueue_op') # image_batch, label_batch = facenet.create_input_pipeline(input_queue, image_size, nrof_preprocess_threads, batch_size_placeholder) 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_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) image_batch = tf.identity(image_batch, 'image_batch') image_batch = tf.identity(image_batch, 'input') label_batch = tf.identity(labels_batch, 'label_batch') print('Number of classes in training set: %d' % nrof_classes) print('Building training graph') with tf.contrib.slim.arg_scope( mobilenet_v2.training_scope( is_training=True, dropout_keep_prob=args.keep_probability, weight_decay=args.weight_decay)): logits, end_points = mobilenet_v2.mobilenet( image_batch, num_classes=nrof_classes) prelogits = tf.squeeze(end_points['global_pool'], [1, 2]) print('After mobilenet ') logits = slim.fully_connected( prelogits, args.embedding_size, activation_fn=None, weights_initializer=slim.initializers.xavier_initializer(), reuse=False) embeddings = tf.identity(logits, 'embeddings') """ Tensor("Squeeze:0", shape=(?, 1280), dtype=float32) Tensor("fully_connected/BiasAdd:0", shape=(?, 512), dtype=float32) Tensor("label_batch:0", shape=(?,), dtype=int64) """ print('logits node') print(prelogits) print(logits) print(label_batch) # g = tf.get_default_graph() # tf.contrib.quantize.create_training_graph(input_graph=g) # Norm for the prelogits eps = 1e-4 # Split embeddings into anchor, positive and negative and calculate triplet loss anchor, positive, negative = tf.unstack( tf.reshape(embeddings, [-1, 3, args.embedding_size]), 3, 1) triplet_loss = facenet.triplet_loss(anchor, positive, negative, args.alpha) 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([triplet_loss] + 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()) # Create a saver saver = tf.train.Saver(tf.trainable_variables(), max_to_keep=3) # saver_new = tf.train.Saver(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() 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) 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 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, dataset, epoch, image_paths_placeholder, labels_placeholder, label_batch, batch_size_placeholder, learning_rate_placeholder, enqueue_op, input_queue, global_step, embeddings, total_loss, train_op, summary_op, summary_writer, args.learning_rate_schedule_file, args.embedding_size, anchor, positive, negative, triplet_loss) # 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, label_batch, image_paths_placeholder, labels_placeholder, batch_size_placeholder, learning_rate_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) # --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): # 导入网络架构模型 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): 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) # 保存参数日志 facenet.write_arguments_to_file(args, os.path.join(log_dir, 'arguments.txt')) # 设置随机数种子 np.random.seed(seed=args['seed']) # 获取数据集,train_set是包含文件路径与标签的集合 # 包含图片地址的(image_paths)以及对应的人名(name) train_set = facenet.get_dataset(args['data_dir']) print('模型目录: %s' % model_dir) print('log目录: %s' % log_dir) # 判断是否有预训练模型 if args['pretrained_model']: print('Pre-trained model: %s' % os.path.expanduser(args['pretrained_model'])) if args['lfw_dir']: print('LFW目录: %s' % args['lfw_dir']) # 读取用于测试的pairs文件 pairs = lfw.read_pairs(os.path.expanduser(args['lfw_pairs'])) shuffle(pairs) # 获取对应的路径 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) # 学习率 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]) preprocess_threads = 4 images_and_labels = [] for _ in range(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_flip']: image = tf.image.random_flip_left_right(image) 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 * 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') labels_batch = tf.identity(labels_batch, 'label_batch') # 构造计算图 # 其中prelogits是最后一层的输出 prelogits, _ = network.inference( image_batch, args['keep_probability'], phase_train=phase_train_placeholder, bottleneck_layer_size=args['embedding_size'], weight_decay=args['weight_decay']) # L2正则化 # embeddings = tf.nn.l2_normalize # 输入向量, L2范化的维数(取0(列L2范化)或1(行L2范化)) # 泛化的最小值边界, name='embeddings') embeddings = tf.nn.l2_normalize(prelogits, 1, 1e-10, name='embeddings') # 计算 triplet_loss anchor, positive, negative = tf.unstack( tf.reshape(embeddings, [-1, 3, args['embedding_size']]), 3, 1) triplet_loss = facenet.triplet_loss(anchor, positive, negative, args['alpha']) # 将指数衰减应用在学习率上 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) # 计算损失 regularization_losses = tf.get_collection( tf.GraphKeys.REGULARIZATION_LOSSES) # 构建L2正则化 total_loss = tf.add_n([triplet_loss] + regularization_losses, name='total_loss') # 确定优化方法并根据损失函求梯度,每更新一次参数,global_step 会加 1 train_op = facenet.train(total_loss, global_step, args['optimizer'], learning_rate, args['moving_average_decay'], tf.global_variables()) # 创建一个saver用来保存或者从内存中读取一个模型参数 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)) # 初始化变量 sess.run(tf.global_variables_initializer(), feed_dict={phase_train_placeholder: True}) sess.run(tf.local_variables_initializer(), feed_dict={phase_train_placeholder: True}) # 写log文件 summary_writer = tf.summary.FileWriter(log_dir, sess.graph) # 获取线程 coord = tf.train.Coordinator() # 将队列中的多用sunner开始执行 tf.train.start_queue_runners(coord=coord, sess=sess) with sess.as_default(): # 读入预训练模型(如果有) if args['pretrained_model']: print('载入预训练模型: %s' % args['pretrained_model']) # saver.restore(sess, os.path.expanduser(args['pretrained_model'])) facenet.load_model(args['pretrained_model']) epoch = 0 # 将所有数据过一遍的次数 while epoch < args['max_nrof_epochs']: step = sess.run(global_step, feed_dict=None) # epoch_size是一个epoch中批的个数 # epoch是全局的批处理个数以一个epoch中。。。这个epoch将用于求学习率 epoch = step // args['epoch_size'] # 训练一个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, input_queue, global_step, embeddings, total_loss, train_op, summary_op, summary_writer, args['learning_rate_schedule_file'], args['embedding_size'], anchor, positive, negative, triplet_loss) # 保存变量和metagraph(如果不存在) save_variables_and_metagraph(sess, saver, summary_writer, model_dir, subdir, step) # 使用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): os.environ["CUDA_VISIBLE_DEVICES"] = args.gpu if args.cluster: hvd.init() rank = hvd.rank() subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S') log_dir = os.path.join(os.path.expanduser(args.logs_base_dir), subdir + '_' + str(rank)) if not os.path.isdir( log_dir): # Create the log directory if it doesn't exist os.makedirs(log_dir) set_logger(logger, log_dir) if rank == 0: 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=rank) logger.info('Model directory: %s' % model_dir) logger.info('Log directory: %s' % log_dir) else: 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) set_logger(logger, 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) logger.info('Model directory: %s' % model_dir) logger.info('Log directory: %s' % log_dir) logger.info("train_tripletloss......") # supervised_dataset, unsupervised_dataset = dataset.get_dataset(args.data_dir, args.data_source) supervised_dataset = dataset.get_supervised_dataset( args.data_dir, args.data_source, args.images_per_person) unsupervised_dataset = {} if args.data_source == 'MULTIPLE' and args.unsupervised != 'NONE': unsupervised_dataset = dataset.get_dataset(args.data_dir, args.data_source) # logger.debug("supervised_dataset: %s, unsupervised_dataset: %s" % (supervised_dataset, unsupervised_dataset)) # logger.debug("supervised_dataset['id']: %d" % (len(supervised_dataset['id']))) # logger.debug("supervised_dataset['camera']: %d" % (len(supervised_dataset['camera']))) # logger.debug("supervised_dataset['id+camera']: %d" % (len(supervised_dataset['id+camera']))) if args.pretrained_model: logger.info('Pre-trained model: %s' % os.path.expanduser(args.pretrained_model)) if args.lfw_dir: logger.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, lfw_actual_issame = lfw.get_paths( os.path.expanduser(args.lfw_dir), pairs, args.lfw_file_ext) # dataset = facenet.get_dataset(args.lfw_dir) # lfw_image_list, lfw_label_list = facenet.get_image_paths_and_labels(dataset) if args.val_dir: logger.info('val directory: %s' % args.val_dir) val_lfw_pairs = lfw.read_pairs(os.path.expanduser(args.val_pairs)) # Get the paths for the corresponding images val_paths, val_actual_issame = lfw.get_paths( os.path.expanduser(args.val_dir), val_lfw_pairs, args.lfw_file_ext) # dataset = facenet.get_dataset(args.val_dir) # val_image_list, val_label_list = facenet.get_image_paths_and_labels(dataset) # META_FILE = "face_meta.tsv" # path_for_metadata = os.path.join(log_dir, META_FILE) # with open(path_for_metadata, 'w') as f: # f.write("Index\tLabel\n") # for index, label in enumerate(val_label_list): # f.write("%d\t%d\n" % (index, label)) with tf.Graph().as_default(): tf.set_random_seed(args.seed) global_step = tf.Variable(0, trainable=False, name='global_step') # 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') data_augmentations_placeholder = tf.placeholder( tf.int64, shape=(None, 3), name='data_augmentations') source_image_paths_placeholder = tf.placeholder( tf.string, shape=(None, 1), name='source_image_paths') target_image_paths_placeholder = tf.placeholder( tf.string, shape=(None, 1), name='target_image_paths') input_queue = data_flow_ops.FIFOQueue( capacity=100000, dtypes=[tf.string, tf.int64, tf.int64], shapes=[(3, ), (3, ), (3, )], shared_name=None, name=None) enqueue_op = input_queue.enqueue_many([ image_paths_placeholder, labels_placeholder, data_augmentations_placeholder ]) image_batch, labels_batch = dataset.create_input_pipeline( input_queue, args, batch_size_placeholder) image_batch = tf.identity(image_batch, 'image_batch') image_batch = tf.identity(image_batch, 'input') labels_batch = tf.identity(labels_batch, 'label_batch') network = importlib.import_module(args.model_def) prelogits, _ = network.inference( image_batch, 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') triplet = Triplet(args.max_triplet_per_select) triplet_loss = triplet.triplet_loss(embeddings, args.embedding_size, args.alpha) domain_adaptation_loss = tf.constant(0.0) domain_enqueue_op = None if args.data_source == 'MULTIPLE' and args.unsupervised != 'NONE': # begin: domain adaptation loss domain_input_queue = data_flow_ops.FIFOQueue( capacity=100000, dtypes=[tf.string, tf.string], shapes=[(1, ), (1, )], shared_name=None, name=None) domain_enqueue_op = domain_input_queue.enqueue_many( [ source_image_paths_placeholder, target_image_paths_placeholder ], name='domain_enqueue_op') source_image_batch, target_image_batch = dataset.create_domain_input_pipeline( domain_input_queue, args, batch_size_placeholder) source_image_batch = tf.identity(source_image_batch, 'source_image_batch') target_image_batch = tf.identity(target_image_batch, 'target_image_batch') source_prelogits, source_end_points = network.inference( source_image_batch, args.keep_probability, phase_train=phase_train_placeholder, bottleneck_layer_size=args.embedding_size, weight_decay=args.weight_decay, reuse=True) target_prelogits, target_end_points = network.inference( target_image_batch, args.keep_probability, phase_train=phase_train_placeholder, bottleneck_layer_size=args.embedding_size, weight_decay=args.weight_decay, reuse=True) # multiplier 1.0 may not be the best if args.unsupervised == 'MMD': domain_adaptation_loss = 1.0 * losses.mmd_loss( source_end_points['PreLogitsFlatten'], target_end_points['PreLogitsFlatten'], 1.0) elif args.unsupervised == 'DANN': domain_adaptation_loss = 0.1 * losses.dann_loss( source_end_points['PreLogitsFlatten'], target_end_points['PreLogitsFlatten'], 1.0) tf.add_to_collection('losses', domain_adaptation_loss) # end: domain adaptation loss regularization_losses = tf.get_collection( tf.GraphKeys.REGULARIZATION_LOSSES) total_loss = tf.add_n([triplet_loss] + [domain_adaptation_loss] + regularization_losses, name='total_loss') learning_rate = get_learning_rate(args, learning_rate_placeholder, global_step) tf.summary.scalar('learning_rate', learning_rate) # # 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, args.cluster, args.nrof_warmup_epochs) # split train into 2 parts: compute gradient and apply gradient trained_vars = tf.trainable_variables() # for var in trained_vars: # logger.debug(var) opt = facenet.get_optimizer(args.optimizer, learning_rate, args.cluster) grads_and_vars = facenet.compute_gradients(opt, total_loss) # grads = facenet.compute_gradients_excluding_vars(total_loss) grads, vars = zip(*grads_and_vars) grads = [ g if g is not None else tf.zeros_like(v) for g, v in zip(grads, vars) ] gradient_placeholder = [ tf.placeholder(tf.float32) for _ in xrange(len(trained_vars)) ] apply_gradient_op = facenet.apply_gradients( opt, zip(gradient_placeholder, trained_vars), global_step, args.moving_average_decay) # Create a saver saver = tf.train.Saver(tf.trainable_variables(), max_to_keep=100) # 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)) config = tf.ConfigProto() config.gpu_options.allow_growth = True if args.cluster: # Pin GPU to be used to process local rank (one GPU per process) config.gpu_options.visible_device_list = str(hvd.local_rank()) sess = tf.Session(config=config) # 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}) if args.cluster: sess.run(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(): epoch = 0 if args.pretrained_model: logger.info('Restoring pretrained model: %s' % args.pretrained_model) saver.restore(sess, os.path.expanduser(args.pretrained_model)) if args.lfw_dir: evaluate(sess, lfw_paths, embeddings, labels_batch, image_paths_placeholder, labels_placeholder, data_augmentations_placeholder, batch_size_placeholder, learning_rate_placeholder, phase_train_placeholder, enqueue_op, lfw_actual_issame, args.batch_size, args.lfw_nrof_folds, log_dir, 'lfw_raw', epoch, summary_writer, args.embedding_size) if args.val_dir: evaluate(sess, val_paths, embeddings, labels_batch, image_paths_placeholder, labels_placeholder, data_augmentations_placeholder, batch_size_placeholder, learning_rate_placeholder, phase_train_placeholder, enqueue_op, val_actual_issame, args.batch_size, args.lfw_nrof_folds, log_dir, 'val_raw', epoch, summary_writer, args.embedding_size) # Training and validation loop while epoch < args.max_nrof_epochs: step = sess.run(global_step, feed_dict=None) # epoch = step // args.epoch_size # Train for one epoch triplet.train( image_batch, args, sess, args.data_source, args.unsupervised, supervised_dataset, unsupervised_dataset, epoch, image_paths_placeholder, labels_placeholder, data_augmentations_placeholder, source_image_paths_placeholder, target_image_paths_placeholder, labels_batch, batch_size_placeholder, learning_rate_placeholder, phase_train_placeholder, enqueue_op, domain_enqueue_op, global_step, embeddings, total_loss, opt, grads, gradient_placeholder, apply_gradient_op, summary_op, summary_writer, args.learning_rate_schedule_file, args.embedding_size, triplet_loss, domain_adaptation_loss, log_dir) if (args.cluster and rank == 0) or not args.cluster: # Save variables and the metagraph if it doesn't exist already # save_variables_and_metagraph(sess, saver, summary_writer, model_dir, subdir, step) save_variables_and_metagraph(sess, saver, summary_writer, model_dir, subdir, epoch) if args.lfw_dir: evaluate(sess, lfw_paths, embeddings, labels_batch, image_paths_placeholder, labels_placeholder, data_augmentations_placeholder, batch_size_placeholder, learning_rate_placeholder, phase_train_placeholder, enqueue_op, lfw_actual_issame, args.batch_size, args.lfw_nrof_folds, log_dir, 'lfw', epoch, summary_writer, args.embedding_size) if args.val_dir: evaluate(sess, val_paths, embeddings, labels_batch, image_paths_placeholder, labels_placeholder, data_augmentations_placeholder, batch_size_placeholder, learning_rate_placeholder, phase_train_placeholder, enqueue_op, val_actual_issame, args.batch_size, args.lfw_nrof_folds, log_dir, 'val', epoch, summary_writer, args.embedding_size) epoch += 1 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) train_set = facenet.get_dataset(args.data_dir) 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)) 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.unstack(filenames): file_contents = tf.read_file(filename) image = tf.image.decode_image(file_contents, channels=3) 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) image_batch = tf.identity(image_batch, 'image_batch') image_batch = tf.identity(image_batch, 'input') labels_batch = tf.identity(labels_batch, 'label_batch') # 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) embeddings = tf.nn.l2_normalize(prelogits, 1, 1e-10, name='embeddings') # Split embeddings into anchor, positive and negative and calculate triplet loss anchor, positive, negative = tf.unstack(tf.reshape(embeddings, [-1,3,args.embedding_size]), 3, 1) triplet_loss = facenet.triplet_loss(anchor, positive, negative, args.alpha) 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([triplet_loss] + 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()) # 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)) # 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) 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' % args.pretrained_model) saver.restore(sess, os.path.expanduser(args.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, train_set, epoch, image_paths_placeholder, labels_placeholder, labels_batch, batch_size_placeholder, learning_rate_placeholder, phase_train_placeholder, enqueue_op, input_queue, global_step, embeddings, total_loss, train_op, summary_op, summary_writer, args.learning_rate_schedule_file, args.embedding_size, anchor, positive, negative, triplet_loss) # 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): # 动态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 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.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_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) 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) 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) train_set = facenet.get_dataset(args.data_dir) 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)) 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) # 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.unstack(filenames): file_contents = tf.read_file(filename) image = tf.image.decode_image(file_contents, channels=3) 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) image_batch = tf.identity(image_batch, 'image_batch') image_batch = tf.identity(image_batch, 'input') labels_batch = tf.identity(labels_batch, 'label_batch') # 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) embeddings = tf.nn.l2_normalize(prelogits, 1, 1e-10, name='embeddings') # Split embeddings into anchor, positive and negative and calculate triplet loss anchor, positive, negative = tf.unstack( tf.reshape(embeddings, [-1, 3, args.embedding_size]), 3, 1) triplet_loss = facenet.triplet_loss(anchor, positive, negative, args.alpha) 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([triplet_loss] + 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()) # 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)) # 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) 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' % args.pretrained_model) saver.restore(sess, os.path.expanduser(args.pretrained_model)) # facenet.load_model(args.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, train_set, epoch, image_paths_placeholder, labels_placeholder, labels_batch, batch_size_placeholder, learning_rate_placeholder, phase_train_placeholder, enqueue_op, input_queue, global_step, embeddings, total_loss, train_op, summary_op, summary_writer, args.learning_rate_schedule_file, args.embedding_size, anchor, positive, negative, triplet_loss) # 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) 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): 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(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) # 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 # os.path.realpath(__file__)代表返回当前模块真实路径 # os.path.split(os.path.realpath(__file__))代表返回路径的目录和文件名(元组形式) 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对象,定义见facenet.py文件 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) # 划分训练集和测试集,train_set和val_set的形式和dataset一样 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也是列表,子元素也是列表,每个子列表包含pairs.txt的每一行 pairs = lfw.read_pairs(os.path.expanduser(args.lfw_pairs)) # Get the paths for the corresponding images #lfw_paths为两两比较的列表,列表的元素为有2个元素的元祖,actual_issame为列表,表示每个元素是否为同一个人 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对应的是全局批的个数,根据这个参数可以更新学习率 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的大小和样本个数一样 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) #capacity代表队列容量 # 返回的是一个出列操作,每次出列一个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') # 上面的队列是一个样本索引的出队队列,只用来出列 # 用来每次出列一个epoch中用到的样本 # 这里是第二个队列,这个队列用来入列,每个元素的大小为shape=[(1,),(1,),(1,)] nrof_preprocess_threads = 4 # 这里的shape代表每一个元素的维度 input_queue = data_flow_ops.FIFOQueue( capacity=600000, dtypes=[tf.string, tf.int32, tf.int32], shapes=[(1, ), (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, 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('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) embeddings = tf.nn.l2_normalize(prelogits, 1, 1e-10, name='embeddings') # arcface_logits = arcface_logits_compute(embeddings, label_batch, args, nrof_classes) 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) with tf.variable_scope('Logits'): cosface_logits = AM_logits_compute(embeddings, label_batch, args, nrof_classes) cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits( labels=label_batch, logits=cosface_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(cosface_logits, 1), tf.cast(label_batch, tf.int64)), tf.float32) accuracy = tf.reduce_mean(correct_prediction) # for weights in slim.get_variables_by_name('embedding_weights'): # weight_regularization = tf.contrib.layers.l2_regularizer(args.weight_decay)(weights) # tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES, weight_regularization) regularization_losses = tf.get_collection( tf.GraphKeys.REGULARIZATION_LOSSES) if args.weight_decay == 0: total_loss = tf.add_n([cross_entropy_mean], name='total_loss') else: total_loss = tf.add_n([cross_entropy_mean] + regularization_losses, name='total_loss') #define two saver in case under 'finetuning on different dataset' situation saver_save = tf.train.Saver(tf.trainable_variables(), max_to_keep=1) train_op = facenet.train(total_loss, global_step, args.optimizer, learning_rate, args.moving_average_decay, tf.global_variables(), args.log_histograms) 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) facenet.load_model(pretrained_model) print('Running cosface training') best_accuracy = 0.0 for epoch in range(1, args.max_nrof_epochs + 1): step = sess.run(global_step, feed_dict=None) 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, global_step, total_loss, accuracy, train_op, summary_op, summary_writer, regularization_losses, args.learning_rate_schedule_file, args.random_rotate, args.random_crop, args.random_flip, args.use_fixed_image_standardization, control_placeholder) if not cont: break print('validation running...') if args.lfw_dir: best_accuracy = 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, best_accuracy, saver_save, model_dir, subdir, args.lfw_subtract_mean, args.lfw_use_flipped_images, args.use_fixed_image_standardization, args.lfw_distance_metric) 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 main(args): network = importlib.import_module(args.model_def) subdir = 'Finger' 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) train_set = facenet.get_dataset(args.data_dir) print('Model directory: %s' % model_dir) print('Log directory: %s' % log_dir) 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') phase_train_placeholder = tf.placeholder(tf.bool, name='phase_train') image_placeholder = tf.placeholder(tf.float32, shape=(None, 150, 4), name='image') dynamic_alpha_placeholder = tf.placeholder( tf.float32, shape=(), name='dynamic_alpha_placeholder') prelogits, _ = network.inference( image_placeholder, 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') # Split embeddings into anchor, positive and negative and calculate triplet loss anchor, positive, negative = tf.unstack( tf.reshape(embeddings, [-1, 3, args.embedding_size]), 3, 1) triplet_loss = facenet.triplet_loss(anchor, positive, negative, dynamic_alpha_placeholder) # 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) learning_rate = learning_rate_placeholder 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([triplet_loss] + regularization_losses, name='total_loss') # Build a Graph that trains the model with one batch of examples and updates the model parameters extra_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS) with tf.control_dependencies(extra_ops): if args.optimizer == 'ADAGRAD': opt = tf.train.AdagradOptimizer(learning_rate) elif args.optimizer == 'ADADELTA': opt = tf.train.AdadeltaOptimizer(learning_rate, rho=0.9, epsilon=1e-6) elif args.optimizer == 'ADAM': opt = tf.train.AdamOptimizer(learning_rate, beta1=0.9, beta2=0.999, epsilon=0.1) elif args.optimizer == 'RMSPROP': opt = tf.train.RMSPropOptimizer(learning_rate, decay=0.9, momentum=0.9, epsilon=1.0) elif args.optimizer == 'MOM': opt = tf.train.MomentumOptimizer(learning_rate, 0.9, use_nesterov=True) else: raise ValueError('Invalid optimization algorithm') train_op = opt.minimize(total_loss) # train_op = facenet.train(total_loss, global_step, args.optimizer, # learning_rate, args.moving_average_decay, tf.global_variables()) # Create a saver 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.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) coord = tf.train.Coordinator() tf.train.start_queue_runners(coord=coord, sess=sess) with sess.as_default(): # saver.restore(sess,'./models/siamese/Finger/model-Finger.ckpt-548') # saver.save(sess, 'c3d_lstm/') epoch = 1 final_loss = 0.0 count = 0.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_placeholder, learning_rate_placeholder, phase_train_placeholder, global_step, embeddings, total_loss, train_op, summary_op, summary_writer, args.embedding_size, anchor, positive, negative, triplet_loss, dynamic_alpha_placeholder, final_loss, count) epoch += 1 # Save variables and the metagraph if it doesn't exist already save_variables_and_metagraph(sess, saver, summary_writer, model_dir, subdir, epoch) global epoch_list global alpha_list # plt.plot(epoch_list,alpha_list) # plt.show() # plt.savefig('alpha-vs-epoch.png') file_for_alpha.write(epoch_list) file_for_alpha.write(alpha_list) return model_dir