def main(args): network = importlib.import_module(args.model_def, 'inference') subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S') log_dir = os.path.join(os.path.expanduser(args.logs_base_dir), subdir) if not os.path.isdir( log_dir): # Create the log directory if it doesn't exist os.makedirs(log_dir) model_dir = os.path.join(os.path.expanduser(args.models_base_dir), subdir) if not os.path.isdir( model_dir): # Create the model directory if it doesn't exist os.makedirs(model_dir) # Store some git revision info in a text file in the log directory src_path, _ = os.path.split(os.path.realpath(__file__)) facenet.store_revision_info(src_path, log_dir, ' '.join(sys.argv)) np.random.seed(seed=args.seed) train_set = facenet.get_dataset(args.data_dir) print('Model directory: %s' % model_dir) print('Log directory: %s' % log_dir) pretrained_model = None if args.pretrained_model: pretrained_model = os.path.expanduser(args.pretrained_model) print('Pre-trained model: %s' % pretrained_model) if args.lfw_dir: print('LFW directory: %s' % args.lfw_dir) # Read the file containing the pairs used for testing pairs = lfw.read_pairs(os.path.expanduser(args.lfw_pairs)) # Get the paths for the corresponding images lfw_paths, actual_issame = lfw.get_paths( os.path.expanduser(args.lfw_dir), pairs, args.lfw_file_ext) with tf.Graph().as_default(): tf.set_random_seed(args.seed) global_step = tf.Variable(0, trainable=False) # Get a list of image paths and their labels image_list, label_list = facenet.get_image_paths_and_labels(train_set) # Read data and apply label preserving distortions image_batch, label_batch = facenet.read_and_augument_data( image_list, label_list, args.image_size, args.batch_size, args.max_nrof_epochs, args.random_crop, args.random_flip, args.nrof_preprocess_threads) print('Total number of classes: %d' % len(train_set)) print('Total number of examples: %d' % len(image_list)) # Node for input images image_batch.set_shape((None, args.image_size, args.image_size, 3)) image_batch = tf.identity(image_batch, name='input') # Placeholder for the learning rate learning_rate_placeholder = tf.placeholder(tf.float32, name='learning_rate') # Placeholder for phase_train phase_train_placeholder = tf.placeholder(tf.bool, name='phase_train') # Build the inference graph prelogits, _ = network.inference(image_batch, args.keep_probability, phase_train=phase_train_placeholder, weight_decay=args.weight_decay) with tf.variable_scope('Logits'): n = int(prelogits.get_shape()[1]) m = len(train_set) w = tf.get_variable( 'w', shape=[n, m], dtype=tf.float32, initializer=tf.truncated_normal_initializer(stddev=0.1), regularizer=slim.l2_regularizer(args.weight_decay), trainable=True) b = tf.get_variable('b', [m], initializer=None, trainable=True) logits = tf.matmul(prelogits, w) + b # Add DeCov regularization loss if args.decov_loss_factor > 0.0: logits_decov_loss = facenet.decov_loss( logits) * args.decov_loss_factor tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES, logits_decov_loss) # Add center loss update_centers = tf.no_op('update_centers') if args.center_loss_factor > 0.0: prelogits_center_loss, update_centers = facenet.center_loss( prelogits, label_batch, args.center_loss_alfa) tf.add_to_collection( tf.GraphKeys.REGULARIZATION_LOSSES, prelogits_center_loss * args.center_loss_factor) embeddings = tf.nn.l2_normalize(prelogits, 1, 1e-10, name='embeddings') learning_rate = tf.train.exponential_decay( learning_rate_placeholder, global_step, args.learning_rate_decay_epochs * args.epoch_size, args.learning_rate_decay_factor, staircase=True) tf.scalar_summary('learning_rate', learning_rate) # Calculate the average cross entropy loss across the batch cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits( logits, label_batch, name='cross_entropy_per_example') cross_entropy_mean = tf.reduce_mean(cross_entropy, name='cross_entropy') tf.add_to_collection('losses', cross_entropy_mean) # Calculate the total losses regularization_losses = tf.get_collection( tf.GraphKeys.REGULARIZATION_LOSSES) total_loss = tf.add_n([cross_entropy_mean] + regularization_losses, name='total_loss') # Build a Graph that trains the model with one batch of examples and updates the model parameters train_op = facenet.train(total_loss, global_step, args.optimizer, learning_rate, args.moving_average_decay, tf.all_variables(), args.log_histograms) # Create a saver save_variables = list(set(tf.all_variables()) - set([w]) - set([b])) saver = tf.train.Saver(save_variables, max_to_keep=3) # Build the summary operation based on the TF collection of Summaries. summary_op = tf.merge_all_summaries() # Start running operations on the Graph. gpu_options = tf.GPUOptions( per_process_gpu_memory_fraction=args.gpu_memory_fraction) sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options, log_device_placement=False)) sess.run(tf.initialize_all_variables()) sess.run(tf.initialize_local_variables()) summary_writer = tf.train.SummaryWriter(log_dir, sess.graph) tf.train.start_queue_runners(sess=sess) with sess.as_default(): if pretrained_model: saver.restore(sess, pretrained_model) # Training and validation loop epoch = 0 while epoch < args.max_nrof_epochs: step = sess.run(global_step, feed_dict=None) epoch = step // args.epoch_size # Train for one epoch train(args, sess, epoch, phase_train_placeholder, learning_rate_placeholder, global_step, total_loss, train_op, summary_op, summary_writer, regularization_losses, args.learning_rate_schedule_file, update_centers) # Save variables and the metagraph if it doesn't exist already save_variables_and_metagraph(sess, saver, summary_writer, model_dir, subdir, step) # Evaluate on LFW if args.lfw_dir: start_time = time.time() _, _, accuracy, val, val_std, far = lfw.validate( sess, lfw_paths, actual_issame, args.seed, args.batch_size, image_batch, phase_train_placeholder, embeddings, nrof_folds=args.lfw_nrof_folds) print('Accuracy: %1.3f+-%1.3f' % (np.mean(accuracy), np.std(accuracy))) print('Validation rate: %2.5f+-%2.5f @ FAR=%2.5f' % (val, val_std, far)) lfw_time = time.time() - start_time # Add validation loss and accuracy to summary summary = tf.Summary() #pylint: disable=maybe-no-member summary.value.add(tag='lfw/accuracy', simple_value=np.mean(accuracy)) summary.value.add(tag='lfw/val_rate', simple_value=val) summary.value.add(tag='time/lfw', simple_value=lfw_time) summary_writer.add_summary(summary, step) with open(os.path.join(log_dir, 'lfw_result.txt'), 'at') as f: f.write('%d\t%.5f\t%.5f\n' % (step, np.mean(accuracy), val)) return model_dir
def main(args): network = importlib.import_module( args.model_def) # --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(argv=None): # pylint: disable=unused-argument if FLAGS.model_name: subdir = FLAGS.model_name preload_model = True else: subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S') preload_model = False log_dir = os.path.join(os.path.expanduser(FLAGS.logs_base_dir), subdir) model_dir = os.path.join(os.path.expanduser(FLAGS.models_base_dir), subdir) if not os.path.isdir(model_dir): # Create the model directory if it doesn't exist os.mkdir(model_dir) np.random.seed(seed=FLAGS.seed) dataset = facenet.get_dataset(FLAGS.data_dir) train_set, validation_set = facenet.split_dataset(dataset, FLAGS.train_set_fraction, FLAGS.split_mode) print('Model directory: %s' % model_dir) with tf.Graph().as_default(): tf.set_random_seed(FLAGS.seed) global_step = tf.Variable(0, trainable=False) # Placeholder for input images images_placeholder = tf.placeholder(tf.float32, shape=(FLAGS.batch_size, FLAGS.image_size, FLAGS.image_size, 3), name='input') # Placeholder for phase_train phase_train_placeholder = tf.placeholder(tf.bool, name='phase_train') # Build the inference graph embeddings = facenet.inference_nn4_max_pool_96(images_placeholder, phase_train=phase_train_placeholder) # Split example embeddings into anchor, positive and negative anchor, positive, negative = tf.split(0, 3, embeddings) # Calculate triplet loss loss = facenet.triplet_loss(anchor, positive, negative) # Build a Graph that trains the model with one batch of examples and updates the model parameters train_op, _ = facenet.train(loss, global_step) # Create a saver saver = tf.train.Saver(tf.all_variables(), max_to_keep=0) # Build the summary operation based on the TF collection of Summaries. summary_op = tf.merge_all_summaries() # Build an initialization operation to run below. init = tf.initialize_all_variables() # Start running operations on the Graph. sess = tf.Session(config=tf.ConfigProto(log_device_placement=FLAGS.log_device_placement)) sess.run(init) summary_writer = tf.train.SummaryWriter(log_dir, sess.graph) with sess.as_default(): if preload_model: ckpt = tf.train.get_checkpoint_state(model_dir) if ckpt and ckpt.model_checkpoint_path: saver.restore(sess, ckpt.model_checkpoint_path) else: raise ValueError('Checkpoint not found') # Training and validation loop for epoch in range(FLAGS.max_nrof_epochs): # Train for one epoch step = train(sess, train_set, epoch, images_placeholder, phase_train_placeholder, global_step, embeddings, loss, train_op, summary_op, summary_writer) # Validate epoch validate(sess, validation_set, epoch, images_placeholder, phase_train_placeholder, global_step, embeddings, loss, train_op, summary_op, summary_writer) # Save the model checkpoint after each epoch print('Saving checkpoint') checkpoint_path = os.path.join(model_dir, 'model.ckpt') saver.save(sess, checkpoint_path, global_step=step) graphdef_dir = os.path.join(model_dir, 'graphdef') graphdef_filename = 'graph_def.pb' if (not os.path.exists(os.path.join(graphdef_dir, graphdef_filename))): print('Saving graph definition') tf.train.write_graph(sess.graph_def, graphdef_dir, graphdef_filename, False)
def main(args): network = importlib.import_module(args.model_def, 'inference') subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S') log_dir = os.path.join(os.path.expanduser(args.logs_base_dir), subdir) if not os.path.isdir( log_dir): # Create the log directory if it doesn't exist os.makedirs(log_dir) model_dir = os.path.join(os.path.expanduser(args.models_base_dir), subdir) if not os.path.isdir( model_dir): # Create the model directory if it doesn't exist os.makedirs(model_dir) # Store some git revision info in a text file in the log directory src_path, _ = os.path.split(os.path.realpath(__file__)) facenet.store_revision_info(src_path, log_dir, ' '.join(sys.argv)) np.random.seed(seed=args.seed) random.seed(args.seed) #train_set = facenet.get_dataset(args.data_dir) train_set = facenet.get_huge_dataset(args.data_dir, args.trainset_start, args.trainset_end) nrof_classes = len(train_set) # Get a list of image paths and their labels image_list, label_list = facenet.get_image_paths_and_labels(train_set) print('Total number of classes: %d' % nrof_classes) print('Total number of examples: %d' % len(image_list)) if args.filter_filename: print('Filtering...') train_set = filter_dataset(train_set, args.filter_filename, args.filter_percentile, args.filter_min_nrof_images_per_class, args.trainset_start) nrof_classes = len(train_set) # Get a list of image paths and their labels image_list, label_list = facenet.get_image_paths_and_labels(train_set) print('Total number of classes: %d' % nrof_classes) print('Total number of examples: %d' % len(image_list)) print('Model directory: %s' % model_dir) print('Log directory: %s' % log_dir) pretrained_model = None if args.pretrained_model: pretrained_model = os.path.expanduser(args.pretrained_model) meta_file, ckpt_file = facenet.get_model_filenames( os.path.expanduser(args.pretrained_model)) print('Pre-trained model: %s' % pretrained_model) if args.lfw_dir: print('LFW directory: %s' % args.lfw_dir) # Read the file containing the pairs used for testing pairs = lfw.read_pairs(os.path.expanduser(args.lfw_pairs)) # Get the paths for the corresponding images lfw_paths, actual_issame = lfw.get_paths( os.path.expanduser(args.lfw_dir), pairs, args.lfw_file_ext) with tf.Graph().as_default(): tf.set_random_seed(args.seed) global_step = tf.Variable(0, trainable=False) # Create a queue that produces indices into the image_list and label_list labels = ops.convert_to_tensor(label_list, dtype=tf.int32) range_size = array_ops.shape(labels)[0] index_queue = tf.train.range_input_producer(range_size, num_epochs=None, shuffle=True, seed=None, capacity=32) index_dequeue_op = index_queue.dequeue_many( args.batch_size * args.epoch_size, 'index_dequeue') learning_rate_placeholder = tf.placeholder(tf.float32, name='learning_rate') batch_size_placeholder = tf.placeholder(tf.int32, name='batch_size') phase_train_placeholder = tf.placeholder(tf.bool, name='phase_train') image_paths_placeholder = tf.placeholder(tf.string, shape=(None, 1), name='image_paths') labels_placeholder = tf.placeholder(tf.int64, shape=(None, 1), name='labels') input_queue = data_flow_ops.FIFOQueue(capacity=100000, dtypes=[tf.string, tf.int64], shapes=[(1, ), (1, )], shared_name=None, name=None) enqueue_op = input_queue.enqueue_many( [image_paths_placeholder, labels_placeholder], name='enqueue_op') nrof_preprocess_threads = 4 images_and_labels = [] for _ in range(nrof_preprocess_threads): filenames, label = input_queue.dequeue() images = [] for filename in tf.unpack(filenames): file_contents = tf.read_file(filename) image = tf.image.decode_png(file_contents) if args.random_rotate: image = tf.py_func(facenet.random_rotate_image, [image], tf.uint8) if args.random_crop: image = tf.random_crop( image, [args.image_size, args.image_size, 3]) else: image = tf.image.resize_image_with_crop_or_pad( image, args.image_size, args.image_size) if args.random_flip: image = tf.image.random_flip_left_right(image) #pylint: disable=no-member image.set_shape((args.image_size, args.image_size, 3)) images.append(tf.image.per_image_standardization(image)) images_and_labels.append([images, label]) image_batch, label_batch = tf.train.batch_join( images_and_labels, batch_size=batch_size_placeholder, shapes=[(args.image_size, args.image_size, 3), ()], enqueue_many=True, capacity=4 * nrof_preprocess_threads * args.batch_size, allow_smaller_final_batch=True) #image_batch = tf.identity(image_batch, 'image_batch') image_batch = tf.identity(image_batch, 'input') label_batch = tf.identity(label_batch, 'label_batch') print('Building training graph') # Build the inference graph prelogits, _ = network.inference(image_batch, args.keep_probability, phase_train=phase_train_placeholder, weight_decay=args.weight_decay) logits = slim.fully_connected( prelogits, len(train_set), activation_fn=None, weights_initializer=tf.truncated_normal_initializer(stddev=0.1), weights_regularizer=slim.l2_regularizer(args.weight_decay), scope='Logits', reuse=False) embeddings = tf.nn.l2_normalize(prelogits, 1, 1e-10, name='embeddings') # Add center loss if args.center_loss_factor > 0.0: prelogits_center_loss, centers, _, centers_cts_batch_reshape = facenet.center_loss( prelogits, label_batch, args.center_loss_alfa, nrof_classes) #prelogits_center_loss, _ = facenet.center_loss_similarity(prelogits, label_batch, args.center_loss_alfa, nrof_classes) ####Similarity cosine distance, center loss tf.add_to_collection( tf.GraphKeys.REGULARIZATION_LOSSES, prelogits_center_loss * args.center_loss_factor) learning_rate = tf.train.exponential_decay( learning_rate_placeholder, global_step, args.learning_rate_decay_epochs * args.epoch_size, args.learning_rate_decay_factor, staircase=True) tf.summary.scalar('learning_rate', learning_rate) # Calculate the average cross entropy loss across the batch cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits( logits, label_batch, name='cross_entropy_per_example') cross_entropy_mean = tf.reduce_mean(cross_entropy, name='cross_entropy') tf.add_to_collection('losses', cross_entropy_mean) # Calculate the total losses regularization_losses = tf.get_collection( tf.GraphKeys.REGULARIZATION_LOSSES) total_loss = tf.add_n([cross_entropy_mean] + regularization_losses, name='total_loss') #### Training accuracy of softmax: check the underfitting or overfiting ############################# correct_prediction = tf.equal(tf.argmax(logits, 1), label_batch) train_acc = tf.reduce_mean(tf.cast(correct_prediction, tf.float32)) ######################################################################################################## ########## edit mzh ##################### # Create list with variables to restore restore_vars = [] update_gradient_vars = [] if args.pretrained_model: update_gradient_vars = tf.global_variables() for var in tf.global_variables(): if not ('Embeddings/' in var.op.name or 'Centralisation/' in var.op.name or 'centers' in var.op.name or 'centers_cts' in var.op.name): restore_vars.append(var) #else: #update_gradient_vars.append(var) else: restore_vars = tf.global_variables() update_gradient_vars = tf.global_variables() ########## edit mzh ##################### # Build a Graph that trains the model with one batch of examples and updates the model parameters train_op = facenet.train(total_loss, global_step, args.optimizer, learning_rate, args.moving_average_decay, tf.global_variables(), args.log_histograms) # Create a saver restore_saver = tf.train.Saver(restore_vars) ## mzh #saver = tf.train.Saver(tf.trainable_variables(), max_to_keep=3) saver = tf.train.Saver(tf.global_variables(), max_to_keep=3) # Build the summary operation based on the TF collection of Summaries. summary_op = tf.summary.merge_all() # Start running operations on the Graph. gpu_options = tf.GPUOptions( per_process_gpu_memory_fraction=args.gpu_memory_fraction) sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options, log_device_placement=False)) sess.run(tf.global_variables_initializer()) sess.run(tf.local_variables_initializer()) summary_writer = tf.summary.FileWriter(log_dir, sess.graph) tf.train.start_queue_runners(sess=sess) with sess.as_default(): if pretrained_model: print('Restoring pretrained model: %s' % pretrained_model) #saver.restore(sess, pretrained_model) restore_saver.restore( sess, os.path.join(os.path.expanduser(args.pretrained_model), ckpt_file)) # Training and validation loop print('Running training') epoch = 0 acc = 0 val = 0 far = 0 best_acc = 0 while epoch < args.max_nrof_epochs: step = sess.run(global_step, feed_dict=None) epoch = step // args.epoch_size # Train for one epoch train(args, sess, epoch, image_list, label_list, index_dequeue_op, enqueue_op, image_paths_placeholder, labels_placeholder, learning_rate_placeholder, phase_train_placeholder, batch_size_placeholder, global_step, total_loss, train_op, summary_op, summary_writer, regularization_losses, args.learning_rate_schedule_file, prelogits_center_loss, cross_entropy_mean, acc, val, far, centers_cts_batch_reshape, train_acc) # Save variables and the metagraph if it doesn't exist already save_variables_and_metagraph(sess, saver, summary_writer, model_dir, subdir, step) # Evaluate on LFW if args.lfw_dir: acc, val, far = evaluate( sess, enqueue_op, image_paths_placeholder, labels_placeholder, phase_train_placeholder, batch_size_placeholder, embeddings, label_batch, lfw_paths, actual_issame, args.lfw_batch_size, args.lfw_nrof_folds, log_dir, step, summary_writer, args.evaluate_mode) ## saving the best_model if acc > best_acc: best_acc = acc best_model_dir = os.path.join(model_dir, 'best_model') if not os.path.isdir( best_model_dir ): # Create the log directory if it doesn't exist os.makedirs(best_model_dir) if os.listdir(best_model_dir): for file in glob.glob( os.path.join(best_model_dir, '*.*')): os.remove(file) for file in glob.glob(os.path.join(model_dir, '*.*')): shutil.copy(file, best_model_dir) return model_dir
def 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): 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 train(): dataset = facenet.get_dataset(FLAGS.data_dir) train_set, test_set = facenet.split_dataset(dataset, 0.9) """Train CIFAR-10 for a number of steps.""" with tf.Graph().as_default(): global_step = tf.Variable(0, trainable=False) # Placeholder for input images images_placeholder = tf.placeholder(tf.float32, shape=(FLAGS.batch_size, 96, 96, 3), name='Input') # Build a Graph that computes the logits predictions from the inference model embeddings = facenet.inference_no_batch_norm_deeper(images_placeholder, tf.constant(True)) #embeddings = facenet.inference(images_placeholder, tf.constant(False)) # Split example embeddings into anchor, positive and negative #a, p, n = tf.split(0, 3, embeddings) # Calculate triplet loss loss = facenet.triplet_loss_modified(embeddings) # Build a Graph that trains the model with one batch of examples and updates the model parameters train_op, grads = facenet.train(loss, global_step) # Create a saver saver = tf.train.Saver(tf.all_variables()) # Build the summary operation based on the TF collection of Summaries. summary_op = tf.merge_all_summaries() # Build an initialization operation to run below. init = tf.initialize_all_variables() check_num = tf.add_check_numerics_ops() # Start running operations on the Graph. sess = tf.Session(config=tf.ConfigProto(log_device_placement=FLAGS.log_device_placement)) sess.run(init) summary_writer = tf.train.SummaryWriter(FLAGS.train_dir, graph_def=sess.graph_def) epoch = 1 with sess.as_default(): while epoch<FLAGS.max_nrof_epochs: batch_number = 0 while batch_number<FLAGS.epoch_size: print('Loading new data') image_data, num_per_class = facenet.load_data(train_set) print('Selecting suitable triplets for training') start_time = time.time() emb_list = [] # Run a forward pass for the sampled images nrof_examples_per_epoch = FLAGS.people_per_batch*FLAGS.images_per_person nrof_batches_per_epoch = int(np.floor(nrof_examples_per_epoch/FLAGS.batch_size)) #for i in xrange(nrof_batches_per_epoch): #feed_dict = facenet.get_batch(images_placeholder, image_data, i) #emb_list += sess.run([embeddings], feed_dict=feed_dict) #emb_array = np.vstack(emb_list) # Stack the embeddings to a nrof_examples_per_epoch x 128 matrix ## Select triplets based on the embeddings #apn, nrof_random_negs, nrof_triplets = facenet.select_triplets(emb_array, num_per_class, image_data) #duration = time.time() - start_time #print('(nrof_random_negs, nrof_triplets) = (%d, %d): time=%.3f seconds' % (nrof_random_negs, nrof_triplets, duration)) count = 0 # while count<nrof_triplets*3 and batch_number<FLAGS.epoch_size: while batch_number<FLAGS.epoch_size: start_time = time.time() # feed_dict = facenet.get_batch(images_placeholder, apn, batch_number) feed_dict = facenet.get_batch(images_placeholder, image_data, batch_number) grad_tensors, grad_vars = zip(*grads) grads_eval = sess.run(grad_tensors, feed_dict=feed_dict) for gt, gv in zip(grads_eval, grad_vars): print('%40s: %6d %6f %6f' % (gv.op.name, np.sum(np.isnan(gt)), np.max(gt), np.min(gt))) duration = time.time() - start_time print('Epoch: [%d][%d/%d]\tTime %.3f\ttripErr %2.3f' % (epoch, batch_number, FLAGS.epoch_size, duration, err)) batch_number+=1 count+=FLAGS.batch_size epoch+=1 # Save the model checkpoint periodically. checkpoint_path = os.path.join(FLAGS.train_dir, 'model.ckpt') saver.save(sess, checkpoint_path, global_step=epoch*FLAGS.epoch_size+batch_number)
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) 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 train_facenet(config_): # display the model parameters config_.display() # Get the image_size image_size = (config_.im_height, config_.im_width) preprocess(config_) # Create dirs to save the logs and checkpoints subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S') log_dir = os.path.join(os.path.expanduser(config_.logs_base_dir), subdir) if not os.path.isdir( log_dir): # Create the log directory if it doesn't exist os.makedirs(log_dir) model_dir = os.path.join(os.path.expanduser(config_.models_base_dir), subdir) if not os.path.isdir( model_dir): # Create the model directory if it doesn't exist os.makedirs(model_dir) # random seed for reproducability np.random.seed(seed=config_.seed) random.seed(config_.seed) # get the training dataset, the dir should have structure # person1 # person1_image_1 # person1_image_2 # . # . # person 2 # person2_image_1 # . # . dataset = facenet.get_dataset(config_.data_dir) # get train and test dataset if config_.validation_set_split_ratio > 0.0: train_set, val_set = facenet.split_dataset( dataset, config_.validation_set_split_ratio, config_.min_nrof_val_images_per_class, 'SPLIT_IMAGES') else: train_set, val_set = dataset, [] nrof_classes = len(train_set) print('Model directory: %s' % model_dir) print('Log directory: %s' % log_dir) pretrained_model = None if config_.pretrained_model: pretrained_model = os.path.expanduser(config_.pretrained_model) print('Pre-trained model: %s' % pretrained_model) # get the image pairs to test the quality of embedding if config_.lfw_dir: print('LFW directory: %s' % config_.lfw_dir) # Read the file containing the pairs used for testing pairs = lfw.read_pairs(os.path.expanduser(config_.lfw_pairs)) # Get the paths for the corresponding images lfw_paths, actual_issame = lfw.get_paths( os.path.expanduser(config_.lfw_dir), pairs) with tf.Graph().as_default(): tf.set_random_seed(config_.seed) global_step = tf.Variable(0, trainable=False) # Get a list of image paths and their labels image_list, label_list = facenet.get_image_paths_and_labels(train_set) assert len(image_list) > 0, 'The training set should not be empty' val_image_list, val_label_list = facenet.get_image_paths_and_labels( val_set) # Create a queue that produces indices into the image_list and label_list labels = ops.convert_to_tensor(label_list, dtype=tf.int32) range_size = array_ops.shape(labels)[0] index_queue = tf.train.range_input_producer(range_size, num_epochs=None, shuffle=True, seed=None, capacity=32) index_dequeue_op = index_queue.dequeue_many( config_.batch_size * config_.epoch_size, 'index_dequeue') learning_rate_placeholder = tf.placeholder(tf.float32, name='learning_rate') batch_size_placeholder = tf.placeholder(tf.int32, name='batch_size') phase_train_placeholder = tf.placeholder(tf.bool, name='phase_train') image_paths_placeholder = tf.placeholder(tf.string, shape=(None, 1), name='image_paths') labels_placeholder = tf.placeholder(tf.int32, shape=(None, 1), name='labels') control_placeholder = tf.placeholder(tf.int32, shape=(None, 1), name='control') nrof_preprocess_threads = 4 input_queue = data_flow_ops.FIFOQueue( capacity=2000000, dtypes=[tf.string, tf.int32, tf.int32], shapes=[(1, ), (1, ), (1, )], shared_name=None, name=None) enqueue_op = input_queue.enqueue_many( [image_paths_placeholder, labels_placeholder, control_placeholder], name='enqueue_op') image_batch, label_batch = facenet.create_input_pipeline( input_queue, image_size, nrof_preprocess_threads, batch_size_placeholder) image_batch = tf.identity(image_batch, 'image_batch') image_batch = tf.identity(image_batch, 'input') label_batch = tf.identity(label_batch, 'label_batch') print('Number of classes in training set: %d' % nrof_classes) print('Number of examples in training set: %d' % len(image_list)) print('Number of classes in validation set: %d' % len(val_set)) print('Number of examples in validation set: %d' % len(val_image_list)) print('Building training graph') # Build the inference graph prelogits, _ = network.inference( image_batch, config_.keep_probability, phase_train=phase_train_placeholder, bottleneck_layer_size=config_.embedding_size, weight_decay=config_.weight_decay) # logits needed for training, we can ignore this in testing phase logits = slim.fully_connected( prelogits, len(train_set), activation_fn=None, weights_initializer=slim.initializers.xavier_initializer(), weights_regularizer=slim.l2_regularizer(config_.weight_decay), scope='Logits', reuse=False) # learned embeddings, will be used to assess the similarity between two images embeddings = tf.nn.l2_normalize(prelogits, 1, 1e-10, name='embeddings') # Norm for the prelogits eps = 1e-4 prelogits_norm = tf.reduce_mean( tf.norm(tf.abs(prelogits) + eps, ord=config_.prelogits_norm_p, axis=1)) tf.add_to_collection( tf.GraphKeys.REGULARIZATION_LOSSES, prelogits_norm * config_.prelogits_norm_loss_factor) # Add center loss prelogits_center_loss, _ = facenet.center_loss( prelogits, label_batch, config_.center_loss_alfa, nrof_classes) tf.add_to_collection( tf.GraphKeys.REGULARIZATION_LOSSES, prelogits_center_loss * config_.center_loss_factor) learning_rate = tf.train.exponential_decay( learning_rate_placeholder, global_step, config_.learning_rate_decay_epochs * config_.epoch_size, config_.learning_rate_decay_factor, staircase=True) tf.summary.scalar('learning_rate', learning_rate) # Calculate the average cross entropy loss across the batch cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits( labels=label_batch, logits=logits, name='cross_entropy_per_example') cross_entropy_mean = tf.reduce_mean(cross_entropy, name='cross_entropy') tf.add_to_collection('losses', cross_entropy_mean) correct_prediction = tf.cast( tf.equal(tf.argmax(logits, 1), tf.cast(label_batch, tf.int64)), tf.float32) accuracy = tf.reduce_mean(correct_prediction) # Calculate the total losses regularization_losses = tf.get_collection( tf.GraphKeys.REGULARIZATION_LOSSES) total_loss = tf.add_n([cross_entropy_mean] + regularization_losses, name='total_loss') # Build a Graph that trains the model with one batch of examples and updates the model parameters train_op = facenet.train(total_loss, global_step, config_.optimizer, learning_rate, config_.moving_average_decay, tf.global_variables(), config_.log_histograms) # Create a saver all_vars = tf.trainable_variables() var_to_restore = [ v for v in all_vars if not v.name.startswith('Logits') ] saver = tf.train.Saver(var_to_restore, max_to_keep=5, keep_checkpoint_every_n_hours=1.0) #saver = tf.train.Saver(tf.trainable_variables(), max_to_keep=3) # Build the summary operation based on the TF collection of Summaries. summary_op = tf.summary.merge_all() # Start running operations on the Graph. gpu_options = tf.GPUOptions( per_process_gpu_memory_fraction=config_.gpu_memory_fraction) sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options, log_device_placement=False)) sess.run(tf.global_variables_initializer()) sess.run(tf.local_variables_initializer()) summary_writer = tf.summary.FileWriter(log_dir, sess.graph) coord = tf.train.Coordinator() tf.train.start_queue_runners(coord=coord, sess=sess) with sess.as_default(): if pretrained_model: try: print('Restoring pretrained model: %s' % pretrained_model) #saver.restore(sess, pretrained_model) facenet.load_model(pretrained_model) except: print( 'Error loading model(maybe checkpoint path is wrong).. training from scratch' ) # Training and validation loop print('Running training') nrof_steps = config_.max_nrof_epochs * config_.epoch_size nrof_val_samples = int( math.ceil(config_.max_nrof_epochs / config_.validate_every_n_epochs) ) # Validate every validate_every_n_epochs as well as in the last epoch stat = { 'loss': np.zeros((nrof_steps, ), np.float32), 'center_loss': np.zeros((nrof_steps, ), np.float32), 'reg_loss': np.zeros((nrof_steps, ), np.float32), 'xent_loss': np.zeros((nrof_steps, ), np.float32), 'prelogits_norm': np.zeros((nrof_steps, ), np.float32), 'accuracy': np.zeros((nrof_steps, ), np.float32), 'val_loss': np.zeros((nrof_val_samples, ), np.float32), 'val_xent_loss': np.zeros((nrof_val_samples, ), np.float32), 'val_accuracy': np.zeros((nrof_val_samples, ), np.float32), 'lfw_accuracy': np.zeros((config_.max_nrof_epochs, ), np.float32), 'lfw_valrate': np.zeros((config_.max_nrof_epochs, ), np.float32), 'learning_rate': np.zeros((config_.max_nrof_epochs, ), np.float32), 'time_train': np.zeros((config_.max_nrof_epochs, ), np.float32), 'time_validate': np.zeros((config_.max_nrof_epochs, ), np.float32), 'time_evaluate': np.zeros((config_.max_nrof_epochs, ), np.float32), 'prelogits_hist': np.zeros((config_.max_nrof_epochs, 1000), np.float32), } for epoch in range(1, config_.max_nrof_epochs + 1): step = sess.run(global_step, feed_dict=None) # Train for one epoch t = time.time() cont = train( config_, sess, epoch, image_list, label_list, index_dequeue_op, enqueue_op, image_paths_placeholder, labels_placeholder, learning_rate_placeholder, phase_train_placeholder, batch_size_placeholder, control_placeholder, global_step, total_loss, train_op, summary_op, summary_writer, regularization_losses, config_.learning_rate_schedule_file, stat, cross_entropy_mean, accuracy, learning_rate, prelogits, prelogits_center_loss, config_.random_rotate, config_.random_crop, config_.random_flip, prelogits_norm, config_.prelogits_hist_max, config_.use_fixed_image_standardization) stat['time_train'][epoch - 1] = time.time() - t if not cont: break t = time.time() if len(val_image_list) > 0 and ( (epoch - 1) % config_.validate_every_n_epochs == config_.validate_every_n_epochs - 1 or epoch == config_.max_nrof_epochs): validate(config_, sess, epoch, val_image_list, val_label_list, enqueue_op, image_paths_placeholder, labels_placeholder, control_placeholder, phase_train_placeholder, batch_size_placeholder, stat, total_loss, regularization_losses, cross_entropy_mean, accuracy, config_.validate_every_n_epochs, config_.use_fixed_image_standardization) stat['time_validate'][epoch - 1] = time.time() - t # Save variables and the metagraph if it doesn't exist already save_variables_and_metagraph(sess, saver, summary_writer, model_dir, subdir, epoch) # Evaluate on LFW t = time.time() if config_.lfw_dir: evaluate(sess, enqueue_op, image_paths_placeholder, labels_placeholder, phase_train_placeholder, batch_size_placeholder, control_placeholder, embeddings, label_batch, lfw_paths, actual_issame, config_.lfw_batch_size, config_.lfw_nrof_folds, log_dir, step, summary_writer, stat, epoch, config_.lfw_distance_metric, config_.lfw_subtract_mean, config_.lfw_use_flipped_images, config_.use_fixed_image_standardization) stat['time_evaluate'][epoch - 1] = time.time() - t print('Saving statistics') return model_dir
def main(args): network = importlib.import_module(args.model_def) 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(argv=None): # pylint: disable=unused-argument if FLAGS.model_name: subdir = FLAGS.model_name preload_model = True else: subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S') preload_model = False log_dir = os.path.join(os.path.expanduser(FLAGS.logs_base_dir), subdir) if not os.path.isdir( log_dir): # Create the log directory if it doesn't exist os.mkdir(log_dir) model_dir = os.path.join(os.path.expanduser(FLAGS.models_base_dir), subdir) if not os.path.isdir( model_dir): # Create the model directory if it doesn't exist os.mkdir(model_dir) # Store some git revision info in a text file in the log directory src_path, _ = os.path.split(os.path.realpath(__file__)) store_training_info(src_path, log_dir, ' '.join(argv)) np.random.seed(seed=FLAGS.seed) dataset = facenet.get_dataset(FLAGS.data_dir) train_set, validation_set = facenet.split_dataset(dataset, FLAGS.train_set_fraction, FLAGS.split_mode) print('Model directory: %s' % model_dir) with tf.Graph().as_default(): tf.set_random_seed(FLAGS.seed) global_step = tf.Variable(0, trainable=False) # Placeholder for input images images_placeholder = tf.placeholder(tf.float32, shape=(FLAGS.batch_size, FLAGS.image_size, FLAGS.image_size, 3), name='input') # Placeholder for phase_train phase_train_placeholder = tf.placeholder(tf.bool, name='phase_train') # Build the inference graph embeddings = facenet.inference_nn4_max_pool_96( images_placeholder, FLAGS.pool_type, FLAGS.use_lrn, FLAGS.keep_probability, phase_train=phase_train_placeholder) # Split example embeddings into anchor, positive and negative anchor, positive, negative = tf.split(0, 3, embeddings) # Calculate triplet loss loss = facenet.triplet_loss(anchor, positive, negative, FLAGS.alpha) # Build a Graph that trains the model with one batch of examples and updates the model parameters train_op, _ = facenet.train(loss, global_step, FLAGS.optimizer, FLAGS.learning_rate, FLAGS.moving_average_decay) # Create a saver saver = tf.train.Saver(tf.all_variables(), max_to_keep=0) # Build the summary operation based on the TF collection of Summaries. summary_op = tf.merge_all_summaries() # Build an initialization operation to run below. init = tf.initialize_all_variables() # Start running operations on the Graph. sess = tf.Session(config=tf.ConfigProto( log_device_placement=FLAGS.log_device_placement)) sess.run(init) summary_writer = tf.train.SummaryWriter(log_dir, sess.graph) with sess.as_default(): if preload_model: ckpt = tf.train.get_checkpoint_state(model_dir) if ckpt and ckpt.model_checkpoint_path: saver.restore(sess, ckpt.model_checkpoint_path) else: raise ValueError('Checkpoint not found') # Training and validation loop for epoch in range(FLAGS.max_nrof_epochs): # Train for one epoch step = train(sess, train_set, epoch, images_placeholder, phase_train_placeholder, global_step, embeddings, loss, train_op, summary_op, summary_writer) # Test on validation set validate(sess, validation_set, epoch, images_placeholder, phase_train_placeholder, global_step, embeddings, loss, 'validation', summary_writer) # Test on training set validate(sess, train_set, epoch, images_placeholder, phase_train_placeholder, global_step, embeddings, loss, 'training', summary_writer) if (epoch % FLAGS.checkpoint_period == 0) or (epoch == FLAGS.max_nrof_epochs - 1): # Save the model checkpoint print('Saving checkpoint') checkpoint_path = os.path.join(model_dir, 'model.ckpt') saver.save(sess, checkpoint_path, global_step=step) # Save the model if it hasn't been saved before graphdef_dir = os.path.join(model_dir, 'graphdef') graphdef_filename = 'graph_def.pb' if (not os.path.exists( os.path.join(graphdef_dir, graphdef_filename))): print('Saving graph definition') tf.train.write_graph(sess.graph_def, graphdef_dir, graphdef_filename, False)
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) np.random.seed(seed=args.seed) random.seed(args.seed) nrof_classes = 8631 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, args.lfw_file_ext) # images_lfw = np.load(args.lfw_dir+'.npy') 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') phase_train_placeholder = tf.placeholder(tf.bool, name='phase_train') tfrecords_list = glob.glob(args.tfrecord_dir) filename_queue = tf.train.string_input_producer(tfrecords_list, shuffle=True) reader = tf.TFRecordReader() key, records = reader.read(filename_queue) features = tf.parse_single_example(records, features={ 'label': tf.FixedLenFeature([], tf.int64), "image_raw": tf.FixedLenFeature([], tf.string) }) label = tf.cast(features['label'], tf.int32) image = tf.cast( tf.image.decode_jpeg(features["image_raw"], channels=3), tf.float32) if args.random_flip: image = tf.image.random_flip_left_right(image) image.set_shape((112, 96, 3)) image = tf.subtract(image, 127.5) * 0.0078125 images_and_labels = [image, label] image_batch, label_batch = tf.train.shuffle_batch( images_and_labels, batch_size=args.batch_size, shapes=[(112, 96, 3), ()], capacity=40000, min_after_dequeue=10000, allow_smaller_final_batch=True) # image_batch.set_shape([args.batch_size, 112, 112, 3]) # label_batch.set_shape([args.batch_size]) image_batch = tf.identity(image_batch, 'input') label_batch = tf.identity(label_batch, 'label') image_batch.set_shape([None, 112, 96, 3]) print('Total number of classes: %d' % nrof_classes) print('Total number of examples: 3000000') 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) prelogits = tf.identity(prelogits, 'prelogits') embeddings = tf.nn.l2_normalize(prelogits, 1, 1e-10, name='embeddings') cross_entropy_mean, logits = cosSoftmax_loss(embeddings, label_batch, args.batch_size, nrof_classes, m=0.35, s=30, name='softmax') # cross_entropy_mean, accuracy = adaptive_loss(embeddings, label_batch, args.batch_size, nrof_classes, m=0.35, s=30, name='softmax') # AM_logits, logits = AM_logits_compute(embeddings, label_batch, args, nrof_classes) #AM_logits = Arc_logits(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) # cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits( # labels=label_batch, logits=AM_logits, name='cross_entropy_per_example') # cross_entropy_mean = tf.reduce_mean(cross_entropy, name='cross_entropy') correct_prediction = tf.cast( tf.equal(tf.argmax(logits, 1), tf.cast(label_batch, tf.int64)), tf.float32) accuracy = tf.reduce_mean(correct_prediction) for weights in slim.get_variables_by_name('kernel'): kernel_regularization = tf.contrib.layers.l2_regularizer( args.weight_decay)(weights) tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES, kernel_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') tf.add_to_collection('losses', 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.trainable_variables(), args.log_histograms) # train_op = tf.train.AdamOptimizer(learning_rate).minimize(total_loss,global_step = global_step,var_list=tf.trainable_variables()) # train_op = tf.train.MomentumOptimizer(learning_rate,momentum=0.9).minimize(total_loss,global_step=global_step,var_list=tf.trainable_variables()) 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) gpu_options = tf.GPUOptions(allow_growth=True) 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: exclusions = [] except_exclusions = slim.get_variables_to_restore( exclude=exclusions) restore_variables = [ v for v in tf.trainable_variables() if v in except_exclusions ] saver_load = tf.train.Saver(restore_variables) print('Restoring pretrained model: %s' % pretrained_model) saver_load.restore(sess, pretrained_model) best_accuracy = evaluate_double(sess, phase_train_placeholder, image_batch, embeddings, lfw_paths, actual_issame, log_dir, 0, summary_writer, 0.0, saver_save, model_dir, subdir, args) print('Running training') epoch = 0 best_accuracy = 0.0 while epoch < args.max_nrof_epochs: step = sess.run(global_step, feed_dict=None) epoch = step // args.epoch_size train(args, sess, epoch, learning_rate_placeholder, phase_train_placeholder, global_step, total_loss, train_op, summary_op, summary_writer, regularization_losses, accuracy, learning_rate) print('validation running...') if args.lfw_dir: best_accuracy = evaluate_double( sess, phase_train_placeholder, image_batch, embeddings, lfw_paths, actual_issame, log_dir, step + args.epoch_size, summary_writer, best_accuracy, saver_save, model_dir, subdir, args) return model_dir
def main(argv=None): # pylint: disable=unused-argument if FLAGS.model_name: subdir = FLAGS.model_name preload_model = True else: subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S') preload_model = False log_dir = os.path.join(os.path.expanduser(FLAGS.logs_base_dir), subdir) if not os.path.isdir(log_dir): # Create the log directory if it doesn't exist os.mkdir(log_dir) model_dir = os.path.join(os.path.expanduser(FLAGS.models_base_dir), subdir) if not os.path.isdir(model_dir): # Create the model directory if it doesn't exist os.mkdir(model_dir) # Store some git revision info in a text file in the log directory src_path,_ = os.path.split(os.path.realpath(__file__)) facenet.store_revision_info(src_path, log_dir, ' '.join(argv)) np.random.seed(seed=FLAGS.seed) dataset = facenet.get_dataset(FLAGS.data_dir) train_set, validation_set = facenet.split_dataset(dataset, FLAGS.train_set_fraction, FLAGS.split_mode) print('Model directory: %s' % model_dir) with tf.Graph().as_default(): tf.set_random_seed(FLAGS.seed) global_step = tf.Variable(0, trainable=False) # Placeholder for input images images_placeholder = tf.placeholder(tf.float32, shape=(None, FLAGS.image_size, FLAGS.image_size, 3), name='input') # Placeholder for phase_train phase_train_placeholder = tf.placeholder(tf.bool, name='phase_train') # Build the inference graph embeddings = network.inference(images_placeholder, FLAGS.pool_type, FLAGS.use_lrn, FLAGS.keep_probability, phase_train=phase_train_placeholder) # Split example embeddings into anchor, positive and negative anchor, positive, negative = tf.split(0, 3, embeddings) # Calculate triplet loss loss = facenet.triplet_loss(anchor, positive, negative, FLAGS.alpha) # Build a Graph that trains the model with one batch of examples and updates the model parameters train_op, _ = facenet.train(loss, global_step, FLAGS.optimizer, FLAGS.learning_rate, FLAGS.moving_average_decay) # Create a saver saver = tf.train.Saver(tf.all_variables(), max_to_keep=0) # Build the summary operation based on the TF collection of Summaries. summary_op = tf.merge_all_summaries() # Build an initialization operation to run below. init = tf.initialize_all_variables() # Start running operations on the Graph. sess = tf.Session(config=tf.ConfigProto(log_device_placement=FLAGS.log_device_placement)) sess.run(init) summary_writer = tf.train.SummaryWriter(log_dir, sess.graph) with sess.as_default(): if preload_model: ckpt = tf.train.get_checkpoint_state(model_dir) if ckpt and ckpt.model_checkpoint_path: saver.restore(sess, ckpt.model_checkpoint_path) else: raise ValueError('Checkpoint not found') # Training and validation loop for epoch in range(FLAGS.max_nrof_epochs): # Train for one epoch step = train(sess, train_set, epoch, images_placeholder, phase_train_placeholder, global_step, embeddings, loss, train_op, summary_op, summary_writer) # Store the state of the random number generator rng_state = np.random.get_state() # Test on validation set np.random.seed(seed=FLAGS.seed) validate(sess, validation_set, epoch, images_placeholder, phase_train_placeholder, global_step, embeddings, loss, 'validation', summary_writer) # Test on training set np.random.seed(seed=FLAGS.seed) validate(sess, train_set, epoch, images_placeholder, phase_train_placeholder, global_step, embeddings, loss, 'training', summary_writer) # Restore state of the random number generator np.random.set_state(rng_state) if (epoch % FLAGS.checkpoint_period == 0) or (epoch==FLAGS.max_nrof_epochs-1): # Save the model checkpoint print('Saving checkpoint') checkpoint_path = os.path.join(model_dir, 'model.ckpt') saver.save(sess, checkpoint_path, global_step=step)
def main(args): network = importlib.import_module(args.model_def, 'inference') subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S') log_dir = os.path.join(os.path.expanduser(args.logs_base_dir), subdir) if not os.path.isdir( log_dir): # Create the log directory if it doesn't exist os.makedirs(log_dir) model_dir = os.path.join(os.path.expanduser(args.models_base_dir), subdir) if not os.path.isdir( model_dir): # Create the model directory if it doesn't exist os.makedirs(model_dir) # Store some git revision info in a text file in the log directory src_path, _ = os.path.split(os.path.realpath(__file__)) facenet.store_revision_info(src_path, log_dir, ' '.join(sys.argv)) np.random.seed(seed=args.seed) train_set = facenet.get_dataset(args.data_dir) nrof_classes = len(train_set) print('Model directory: %s' % model_dir) print('Log directory: %s' % log_dir) pretrained_model = None if args.pretrained_model: pretrained_model = os.path.expanduser(args.pretrained_model) print('Pre-trained model: %s' % pretrained_model) if args.lfw_dir: print('LFW directory: %s' % args.lfw_dir) # Read the file containing the pairs used for testing pairs = lfw.read_pairs(os.path.expanduser(args.lfw_pairs)) # Get the paths for the corresponding images lfw_paths, actual_issame = lfw.get_paths( os.path.expanduser(args.lfw_dir), pairs, args.lfw_file_ext) with tf.Graph().as_default(): tf.set_random_seed(args.seed) global_step = tf.Variable(0, trainable=False) # Get a list of image paths and their labels image_list, label_list = facenet.get_image_paths_and_labels(train_set) # Read data and apply label preserving distortions image_batch, label_batch = facenet.read_and_augument_data( image_list, label_list, args.image_size, args.batch_size, args.max_nrof_epochs, args.random_crop, args.random_flip, args.nrof_preprocess_threads) print('Total number of classes: %d' % nrof_classes) print('Total number of examples: %d' % len(image_list)) print('Building training graph') # Placeholder for the learning rate learning_rate_placeholder = tf.placeholder(tf.float32, name='learning_rate') # Build the inference graph prelogits, _ = network.inference(image_batch, args.keep_probability, phase_train=True, weight_decay=args.weight_decay) logits = slim.fully_connected( prelogits, len(train_set), activation_fn=None, weights_initializer=tf.truncated_normal_initializer(stddev=0.1), weights_regularizer=slim.l2_regularizer(args.weight_decay), scope='Logits', reuse=False) # Add DeCov regularization loss if args.decov_loss_factor > 0.0: logits_decov_loss = facenet.decov_loss( logits) * args.decov_loss_factor tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES, logits_decov_loss) # Add center loss if args.center_loss_factor > 0.0: prelogits_center_loss, _ = facenet.center_loss( prelogits, label_batch, args.center_loss_alfa, nrof_classes) tf.add_to_collection( tf.GraphKeys.REGULARIZATION_LOSSES, prelogits_center_loss * args.center_loss_factor) learning_rate = tf.train.exponential_decay( learning_rate_placeholder, global_step, args.learning_rate_decay_epochs * args.epoch_size, args.learning_rate_decay_factor, staircase=True) tf.scalar_summary('learning_rate', learning_rate) # Calculate the average cross entropy loss across the batch cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits( logits, label_batch, name='cross_entropy_per_example') cross_entropy_mean = tf.reduce_mean(cross_entropy, name='cross_entropy') tf.add_to_collection('losses', cross_entropy_mean) # Calculate the total losses regularization_losses = tf.get_collection( tf.GraphKeys.REGULARIZATION_LOSSES) total_loss = tf.add_n([cross_entropy_mean] + regularization_losses, name='total_loss') # Build a Graph that trains the model with one batch of examples and updates the model parameters train_op = facenet.train(total_loss, global_step, args.optimizer, learning_rate, args.moving_average_decay, tf.all_variables(), args.log_histograms) # Evaluation print('Building evaluation graph') lfw_label_list = range(0, len(lfw_paths)) assert ( len(lfw_paths) % args.lfw_batch_size == 0 ), "The number of images in the LFW test set need to be divisible by the lfw_batch_size" eval_image_batch, eval_label_batch = facenet.read_and_augument_data( lfw_paths, lfw_label_list, args.image_size, args.lfw_batch_size, None, False, False, args.nrof_preprocess_threads, shuffle=False) # Node for input images eval_image_batch.set_shape((None, args.image_size, args.image_size, 3)) eval_image_batch = tf.identity(eval_image_batch, name='input') eval_prelogits, _ = network.inference(eval_image_batch, 1.0, phase_train=False, weight_decay=0.0, reuse=True) eval_embeddings = tf.nn.l2_normalize(eval_prelogits, 1, 1e-10, name='embeddings') # Create a saver saver = tf.train.Saver(tf.all_variables(), max_to_keep=3) # Build the summary operation based on the TF collection of Summaries. summary_op = tf.merge_all_summaries() # Start running operations on the Graph. gpu_options = tf.GPUOptions( per_process_gpu_memory_fraction=args.gpu_memory_fraction) sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options, log_device_placement=False)) sess.run(tf.initialize_all_variables()) sess.run(tf.initialize_local_variables()) summary_writer = tf.train.SummaryWriter(log_dir, sess.graph) tf.train.start_queue_runners(sess=sess) with sess.as_default(): if pretrained_model: print('Restoring pretrained model: %s' % pretrained_model) saver.restore(sess, pretrained_model) # Training and validation loop print('Running training') epoch = 0 while epoch < args.max_nrof_epochs: step = sess.run(global_step, feed_dict=None) epoch = step // args.epoch_size # Train for one epoch train(args, sess, epoch, learning_rate_placeholder, global_step, total_loss, train_op, summary_op, summary_writer, regularization_losses, args.learning_rate_schedule_file) # Save variables and the metagraph if it doesn't exist already save_variables_and_metagraph(sess, saver, summary_writer, model_dir, subdir, step) # Evaluate on LFW if args.lfw_dir: evaluate(sess, eval_embeddings, eval_label_batch, actual_issame, args.lfw_batch_size, args.seed, args.lfw_nrof_folds, log_dir, step, summary_writer) return model_dir
def main(args): 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): 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): # 主函数入口 # 从model模块中选择要使用的训练结构 network = importlib.import_module(args.model_def) # 日志路径和模型保存路径的子目录命名结构 subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S') log_dir = os.path.join(os.path.expanduser(args.logs_base_dir), subdir) if not os.path.isdir(log_dir): # Create the log directory if it doesn't exist os.makedirs(log_dir) model_dir = os.path.join(os.path.expanduser(args.models_base_dir), subdir) if not os.path.isdir(model_dir): # Create the model directory if it doesn't exist os.makedirs(model_dir) # Store some git revision info in a text file in the log directory # 当前脚本的的绝对路径,存储相关信息到log文件中 src_path,_ = os.path.split(os.path.realpath(__file__)) facenet.store_revision_info(src_path, log_dir, ' '.join(sys.argv)) # 用参数初始化numpy随机器 np.random.seed(seed=args.seed) random.seed(args.seed) # 获取训练数据 train_set = facenet.get_dataset(args.data_dir) if args.filter_filename: train_set = filter_dataset(train_set, os.path.expanduser(args.filter_filename), args.filter_percentile, args.filter_min_nrof_images_per_class) # 训练数据子类别数目 nrof_classes = len(train_set) # 打印模型和log保存路径,如果有预训练模型需要加载即加载 print('Model directory: %s' % model_dir) print('Log directory: %s' % log_dir) pretrained_model = None if args.pretrained_model: pretrained_model = os.path.expanduser(args.pretrained_model) print('Pre-trained model: %s' % pretrained_model) # 如果指定了lfw验证数据路径即打印,并且加载lfw数据配对文件及相关信息 if args.lfw_dir: print('LFW directory: %s' % args.lfw_dir) # Read the file containing the pairs used for testing pairs = lfw.read_pairs(os.path.expanduser(args.lfw_pairs)) # Get the paths for the corresponding images lfw_paths, actual_issame = lfw.get_paths(os.path.expanduser(args.lfw_dir), pairs, args.lfw_file_ext) # 新建一个图,将该图作为默认图,进入上下文管理器 with tf.Graph().as_default(): # 设置随机种子和全局 tf.set_random_seed(args.seed) global_step = tf.Variable(0, trainable=False) # Get a list of image paths and their labels # 得到训练数据的列表和相对应的标签列表 image_list, label_list = facenet.get_image_paths_and_labels(train_set) assert len(image_list)>0, 'The dataset should not be empty' # Create a queue that produces indices into the image_list and label_list # 将标签列表转化为tensor形式的列表,并获取tensor的范围 labels = ops.convert_to_tensor(label_list, dtype=tf.int32) range_size = array_ops.shape(labels)[0] # index_queue = tf.train.range_input_producer(range_size, num_epochs=None, shuffle=True, seed=None, capacity=32) # 构建训练标签队列,并设置训练中的参数 index_dequeue_op = index_queue.dequeue_many(args.batch_size*args.epoch_size, 'index_dequeue') learning_rate_placeholder = tf.placeholder(tf.float32, name='learning_rate') batch_size_placeholder = tf.placeholder(tf.int32, name='batch_size') phase_train_placeholder = tf.placeholder(tf.bool, name='phase_train') image_paths_placeholder = tf.placeholder(tf.string, shape=(None,1), name='image_paths') labels_placeholder = tf.placeholder(tf.int64, shape=(None,1), name='labels') # 构建训练数据的队列,训练数据,训练标签配对 input_queue = data_flow_ops.FIFOQueue(capacity=100000, dtypes=[tf.string, tf.int64], shapes=[(1,), (1,)], shared_name=None, name=None) enqueue_op = input_queue.enqueue_many([image_paths_placeholder, labels_placeholder], name='enqueue_op') # 数据预处理线程数 nrof_preprocess_threads = 4 images_and_labels = [] # 使用线程去并行处理数据 for _ in range(nrof_preprocess_threads): filenames, label = input_queue.dequeue() images = [] # 读取队列中的配对数据,读取训练图像和训练标签,并对数据进行预处理 for filename in tf.unstack(filenames): file_contents = tf.read_file(filename) image = tf.image.decode_png(file_contents) if args.random_rotate: image = tf.py_func(facenet.random_rotate_image, [image], tf.uint8) # 如果没开启随机截取的开关,即选择图像正中的位置进行训练 if args.random_crop: image = tf.random_crop(image, [args.image_size, args.image_size, 3]) else: image = tf.image.resize_image_with_crop_or_pad(image, args.image_size, args.image_size) if args.random_flip: image = tf.image.random_flip_left_right(image) #pylint: disable=no-member # 再一次确认图像分辨率 image.set_shape((args.image_size, args.image_size, 3)) images.append(tf.image.per_image_standardization(image)) images_and_labels.append([images, label]) # 配置训练batch的参数 image_batch, label_batch = tf.train.batch_join( images_and_labels, batch_size=batch_size_placeholder, shapes=[(args.image_size, args.image_size, 3), ()], enqueue_many=True, capacity=4 * nrof_preprocess_threads * args.batch_size, allow_smaller_final_batch=True) image_batch = tf.identity(image_batch, 'image_batch') image_batch = tf.identity(image_batch, 'input') label_batch = tf.identity(label_batch, 'label_batch') # 打印最终处理完的数据信息 print('Total number of classes: %d' % nrof_classes) print('Total number of examples: %d' % len(image_list)) print('Building training graph') # Build the inference graph # 构建TensorFlow数据流图 prelogits, _ = network.inference(image_batch, args.keep_probability, phase_train=phase_train_placeholder, bottleneck_layer_size=args.embedding_size, weight_decay=args.weight_decay) # 连接全连接层 logits = slim.fully_connected(prelogits, len(train_set), activation_fn=None, weights_initializer=tf.truncated_normal_initializer(stddev=0.1), weights_regularizer=slim.l2_regularizer(args.weight_decay), scope='Logits', reuse=False) # 对特征维度(128维)做一个L2正则化处理 embeddings = tf.nn.l2_normalize(prelogits, 1, 1e-10, name='embeddings') # Add center loss # 添加center loss if args.center_loss_factor>0.0: prelogits_center_loss, _ = facenet.center_loss(prelogits, label_batch, args.center_loss_alfa, nrof_classes) # tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES, prelogits_center_loss * args.center_loss_factor) learning_rate = tf.train.exponential_decay(learning_rate_placeholder, global_step, args.learning_rate_decay_epochs*args.epoch_size, args.learning_rate_decay_factor, staircase=True) tf.summary.scalar('learning_rate', learning_rate) # Calculate the average cross entropy loss across the batch # 计算交叉熵 cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits( labels=label_batch, logits=logits, name='cross_entropy_per_example') cross_entropy_mean = tf.reduce_mean(cross_entropy, name='cross_entropy') tf.add_to_collection('losses', cross_entropy_mean) # Calculate the total losses # 计算总的loss regularization_losses = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES) total_loss = tf.add_n([cross_entropy_mean] + regularization_losses, name='total_loss') # Build a Graph that trains the model with one batch of examples and updates the model parameters # 构建总的训练方式 train_op = facenet.train(total_loss, global_step, args.optimizer, learning_rate, args.moving_average_decay, tf.global_variables(), args.log_histograms) # Create a saver # 构建一个保存对象 saver = tf.train.Saver(tf.trainable_variables(), max_to_keep=3) # Build the summary operation based on the TF collection of Summaries. # 构建一个总的训练摘要对象 summary_op = tf.summary.merge_all() # Start running operations on the Graph. # 开始训练,配置GPU使用参数 gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=args.gpu_memory_fraction) sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options, log_device_placement=False)) sess.run(tf.global_variables_initializer()) sess.run(tf.local_variables_initializer()) summary_writer = tf.summary.FileWriter(log_dir, sess.graph) coord = tf.train.Coordinator() tf.train.start_queue_runners(coord=coord, sess=sess) with sess.as_default(): if pretrained_model: print('Restoring pretrained model: %s' % pretrained_model) saver.restore(sess, pretrained_model) # Training and validation loop # 开始训练循环 print('Running training') epoch = 0 while epoch < args.max_nrof_epochs: step = sess.run(global_step, feed_dict=None) epoch = step // args.epoch_size # Train for one epoch train(args, sess, epoch, image_list, label_list, index_dequeue_op, enqueue_op, image_paths_placeholder, labels_placeholder, learning_rate_placeholder, phase_train_placeholder, batch_size_placeholder, global_step, total_loss, train_op, summary_op, summary_writer, regularization_losses, args.learning_rate_schedule_file) # Save variables and the metagraph if it doesn't exist already save_variables_and_metagraph(sess, saver, summary_writer, model_dir, subdir, step) # Evaluate on LFW if args.lfw_dir: evaluate(sess, enqueue_op, image_paths_placeholder, labels_placeholder, phase_train_placeholder, batch_size_placeholder, embeddings, label_batch, lfw_paths, actual_issame, args.lfw_batch_size, args.lfw_nrof_folds, log_dir, step, summary_writer) sess.close() return model_dir
def main(args): 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): # 导入网络架构模型 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 train(): dataset = facenet.get_dataset(FLAGS.data_dir) train_set, test_set = facenet.split_dataset(dataset, 0.9) fileName = "/home/david/debug4.h5" f = h5py.File(fileName, "r") for item in f.values(): print(item) w1 = f['1w'][:] b1 = f['1b'][:] f.close() print(w1.shape) print(b1.shape) """Train CIFAR-10 for a number of steps.""" with tf.Graph().as_default(): global_step = tf.Variable(0, trainable=False) # Placeholder for input images images_placeholder = tf.placeholder(tf.float32, shape=(FLAGS.batch_size, 96, 96, 3), name='Input') # Build a Graph that computes the logits predictions from the inference model #embeddings = facenet.inference_nn4_max_pool_96(images_placeholder, phase_train=True) conv1 = _conv(images_placeholder, 3, 64, 7, 7, 2, 2, 'SAME', 'conv1_7x7', phase_train=False, use_batch_norm=False, init_weight=w1, init_bias=b1) resh1 = tf.reshape(conv1, [-1, 294912]) embeddings = _affine(resh1, 294912, 128) # Split example embeddings into anchor, positive and negative a, p, n = tf.split(0, 3, embeddings) # Calculate triplet loss loss = facenet.triplet_loss(a, p, n) # Build a Graph that trains the model with one batch of examples and updates the model parameters train_op, grads = facenet.train(loss, global_step) # Create a saver saver = tf.train.Saver(tf.all_variables()) # Build the summary operation based on the TF collection of Summaries. summary_op = tf.merge_all_summaries() # Build an initialization operation to run below. init = tf.initialize_all_variables() # Start running operations on the Graph. sess = tf.Session(config=tf.ConfigProto( log_device_placement=FLAGS.log_device_placement)) sess.run(init) summary_writer = tf.train.SummaryWriter(FLAGS.train_dir, graph_def=sess.graph_def) epoch = 0 with sess.as_default(): while epoch < FLAGS.max_nrof_epochs: batch_number = 0 while batch_number < FLAGS.epoch_size: print('Loading new data') image_data, num_per_class, image_paths = facenet.load_data( train_set) print('Selecting suitable triplets for training') start_time = time.time() emb_list = [] # Run a forward pass for the sampled images nrof_examples_per_epoch = FLAGS.people_per_batch * FLAGS.images_per_person nrof_batches_per_epoch = int( np.floor(nrof_examples_per_epoch / FLAGS.batch_size)) if True: for i in xrange(nrof_batches_per_epoch): feed_dict, _ = facenet.get_batch( images_placeholder, image_data, i) emb_list += sess.run([embeddings], feed_dict=feed_dict) emb_array = np.vstack( emb_list ) # Stack the embeddings to a nrof_examples_per_epoch x 128 matrix # Select triplets based on the embeddings apn, nrof_random_negs, nrof_triplets = facenet.select_triplets( emb_array, num_per_class, image_data) duration = time.time() - start_time print( '(nrof_random_negs, nrof_triplets) = (%d, %d): time=%.3f seconds' % (nrof_random_negs, nrof_triplets, duration)) count = 0 while count < nrof_triplets * 3 and batch_number < FLAGS.epoch_size: start_time = time.time() feed_dict, batch = facenet.get_batch( images_placeholder, apn, batch_number) if (batch_number % 20 == 0): err, summary_str, _ = sess.run( [loss, summary_op, train_op], feed_dict=feed_dict) summary_writer.add_summary( summary_str, FLAGS.epoch_size * epoch + batch_number) else: err, _ = sess.run([loss, train_op], feed_dict=feed_dict) duration = time.time() - start_time print( 'Epoch: [%d][%d/%d]\tTime %.3f\ttripErr %2.3f' % (epoch, batch_number, FLAGS.epoch_size, duration, err)) batch_number += 1 count += FLAGS.batch_size else: while batch_number < FLAGS.epoch_size: start_time = time.time() feed_dict, _ = facenet.get_batch( images_placeholder, image_data, batch_number) grad_tensors, grad_vars = zip(*grads) eval_list = (train_op, loss) + grad_tensors result = sess.run(eval_list, feed_dict=feed_dict) grads_eval = result[2:] nrof_parameters = 0 for gt, gv in zip(grads_eval, grad_vars): print('%40s: %6d' % (gv.op.name, np.size(gt))) nrof_parameters += np.size(gt) print('Total number of parameters: %d' % nrof_parameters) err = result[1] batch_number += 1 epoch += 1 # Save the model checkpoint periodically. checkpoint_path = os.path.join(FLAGS.train_dir, 'model.ckpt') saver.save(sess, checkpoint_path, global_step=epoch * FLAGS.epoch_size + batch_number)
def main(args): network = importlib.import_module(args.model_def, 'inference') subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S') log_dir = os.path.join(os.path.expanduser(args.logs_base_dir), subdir) if not os.path.isdir(log_dir): # Create the log directory if it doesn't exist os.makedirs(log_dir) model_dir = os.path.join(os.path.expanduser(args.models_base_dir), subdir) if not os.path.isdir(model_dir): # Create the model directory if it doesn't exist os.makedirs(model_dir) # Store some git revision info in a text file in the log directory src_path,_ = os.path.split(os.path.realpath(__file__)) facenet.store_revision_info(src_path, log_dir, ' '.join(sys.argv)) np.random.seed(seed=args.seed) train_set = facenet.get_dataset(args.data_dir) print('Model directory: %s' % model_dir) print('Log directory: %s' % log_dir) 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.unpack(filenames): file_contents = tf.read_file(filename) image = tf.image.decode_png(file_contents) if args.random_crop: image = tf.random_crop(image, [args.image_size, args.image_size, 3]) else: image = tf.image.resize_image_with_crop_or_pad(image, args.image_size, args.image_size) if args.random_flip: image = tf.image.random_flip_left_right(image) #pylint: disable=no-member image.set_shape((args.image_size, args.image_size, 3)) images.append(tf.image.per_image_standardization(image)) images_and_labels.append([images, label]) image_batch, labels_batch = tf.train.batch_join( images_and_labels, batch_size=batch_size_placeholder, shapes=[(args.image_size, args.image_size, 3), ()], enqueue_many=True, capacity=4 * nrof_preprocess_threads * args.batch_size, allow_smaller_final_batch=True) # Build the inference graph prelogits, _ = network.inference(image_batch, args.keep_probability, phase_train=phase_train_placeholder, weight_decay=args.weight_decay) pre_embeddings = slim.fully_connected(prelogits, args.embedding_size, activation_fn=None, scope='Embeddings', reuse=False) #embedding_size = 1792 embeddings = tf.nn.l2_normalize(pre_embeddings, 1, 1e-10, name='embeddings') # Split embeddings into anchor, positive and negative and calculate triplet loss anchor, positive, negative = tf.unpack(tf.reshape(embeddings, [-1,3,args.embedding_size]), 3, 1) 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') # Create list with variables to restore restore_vars = [] update_gradient_vars = [] if args.pretrained_model: update_gradient_vars = tf.global_variables() for var in tf.global_variables(): if not 'Embeddings/' in var.op.name: restore_vars.append(var) #else: #update_gradient_vars.append(var) else: restore_vars = tf.global_variables() update_gradient_vars = tf.global_variables() # Build a Graph that trains the model with one batch of examples and updates the model parameters train_op = facenet.train(total_loss, global_step, args.optimizer, learning_rate, args.moving_average_decay, update_gradient_vars) # Create a saver restore_saver = tf.train.Saver(restore_vars) saver = tf.train.Saver(tf.global_variables(), max_to_keep=3) # Build the summary operation based on the TF collection of Summaries. summary_op = tf.summary.merge_all() # Start running operations on the Graph. gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=args.gpu_memory_fraction) sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options)) # Initialize variables sess.run(tf.global_variables_initializer()) sess.run(tf.local_variables_initializer()) summary_writer = tf.summary.FileWriter(log_dir, sess.graph) tf.train.start_queue_runners(sess=sess) with sess.as_default(): if args.pretrained_model: print('Restoring pretrained model: %s' % args.pretrained_model) restore_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.seed, 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')) # 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): logging.info('###### all args #####: %s' % args) network = importlib.import_module(args.model_def) subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S') log_dir = os.path.join(os.path.expanduser(args.logs_base_dir), subdir) if not os.path.isdir( log_dir): # Create the log directory if it doesn't exist os.makedirs(log_dir) model_dir = os.path.join(os.path.expanduser(args.models_base_dir), subdir) if not os.path.isdir( model_dir): # Create the model directory if it doesn't exist os.makedirs(model_dir) # Store some git revision info in a text file in the log directory if not args.no_store_revision_info: src_path, _ = os.path.split(os.path.realpath(__file__)) facenet.store_revision_info(src_path, log_dir, ' '.join(sys.argv)) np.random.seed(seed=args.seed) random.seed(args.seed) train_set = facenet.get_dataset(args.data_dir) if args.filter_filename: train_set = filter_dataset(train_set, args.filter_filename, args.filter_percentile, args.filter_min_nrof_images_per_class) nrof_classes = len(train_set) logging.info('Model directory: %s' % model_dir) logging.info('Log directory: %s' % log_dir) pretrained_model = None if args.pretrained_model: pretrained_model = os.path.expanduser(args.pretrained_model) logging.info('Pre-trained model: %s' % pretrained_model) if args.lfw_dir: logging.info('LFW directory: %s' % args.lfw_dir) # Read the file containing the pairs used for testing pairs = lfw.read_pairs(os.path.expanduser(args.lfw_pairs)) # Get the paths for the corresponding images lfw_paths, actual_issame = lfw.get_paths( os.path.expanduser(args.lfw_dir), pairs, args.lfw_file_ext) with tf.Graph().as_default(): tf.set_random_seed(args.seed) global_step = tf.Variable(0, trainable=False) # Get a list of image paths and their labels image_list, label_list = facenet.get_image_paths_and_labels(train_set) assert len(image_list) > 0, 'The dataset should not be empty' logging.info('image_list size %d, label_list size %d' % (len(image_list), len(label_list))) # Create a queue that produces indices into the image_list and label_list labels = ops.convert_to_tensor(label_list, dtype=tf.int32) range_size = array_ops.shape(labels)[0] logging.info('labels shape %s, range size: %s' % (labels.shape, str(range_size))) index_queue = tf.train.range_input_producer(range_size, num_epochs=None, shuffle=True, seed=None, capacity=32) logging.info('batch size:%d, epoch size:%d' % (args.batch_size, args.epoch_size)) index_dequeue_op = index_queue.dequeue_many( args.batch_size * args.epoch_size, 'index_dequeue') learning_rate_placeholder = tf.placeholder(tf.float32, name='learning_rate') batch_size_placeholder = tf.placeholder(tf.int32, name='batch_size') phase_train_placeholder = tf.placeholder(tf.bool, name='phase_train') image_paths_placeholder = tf.placeholder(tf.string, shape=(None, 1), name='image_paths') labels_placeholder = tf.placeholder(tf.int64, shape=(None, 1), name='labels') input_queue = data_flow_ops.FIFOQueue(capacity=100000, dtypes=[tf.string, tf.int64], shapes=[(1, ), (1, )], shared_name=None, name=None) enqueue_op = input_queue.enqueue_many( [image_paths_placeholder, labels_placeholder], name='enqueue_op') nrof_preprocess_threads = 4 images_and_labels = [] for _ in range(nrof_preprocess_threads): filenames, label = input_queue.dequeue() logging.info('# filenames len:%s' % filenames.shape) images = [] for filename in tf.unstack(filenames): # logging.info('#file:%s' % filename) file_contents = tf.read_file(filename) image = tf.image.decode_jpeg(file_contents) # logging.info('#image shape:%s' % image.shape) # if args.random_rotate: # image = tf.py_func(facenet.random_rotate_image, [image], tf.uint8) # # if args.random_crop: # # image = tf.random_crop(image, [args.image_size, args.image_size, 3]) # else: # image = tf.image.resize_image_with_crop_or_pad(image, args.image_size, args.image_size) # if args.random_flip: # image = tf.image.random_flip_left_right(image) image = porcessor.preprocess_image(image, args.image_size, args.image_size, is_training=True) #pylint: disable=no-member image.set_shape((args.image_size, args.image_size, 3)) images.append(tf.image.per_image_standardization(image)) images_and_labels.append([images, label]) image_batch, label_batch = tf.train.batch_join( images_and_labels, batch_size=batch_size_placeholder, shapes=[(args.image_size, args.image_size, 3), ()], enqueue_many=True, capacity=4 * nrof_preprocess_threads * args.batch_size, allow_smaller_final_batch=True) image_batch = tf.identity(image_batch, 'image_batch') image_batch = tf.identity(image_batch, 'input') label_batch = tf.identity(label_batch, 'label_batch') logging.info('Total number of classes: %d' % nrof_classes) logging.info('Total number of examples: %d' % len(image_list)) logging.info('Building training graph') batch_norm_params = { # Decay for the moving averages 'decay': 0.995, # epsilon to prevent 0s in variance 'epsilon': 0.001, # force in-place updates of mean and variance estimates 'updates_collections': None, # Moving averages ends up in the trainable variables collection 'variables_collections': [tf.GraphKeys.TRAINABLE_VARIABLES], # Only update statistics during training mode 'is_training': phase_train_placeholder } # Build the inference graph # with tf.device('/GPU:0'): prelogits, _ = network.inference(image_batch, args.keep_probability, phase_train=phase_train_placeholder, weight_decay=args.weight_decay) bottleneck = slim.fully_connected( prelogits, args.embedding_size, activation_fn=None, weights_initializer=tf.truncated_normal_initializer(stddev=0.1), weights_regularizer=slim.l2_regularizer(args.weight_decay), normalizer_fn=slim.batch_norm, normalizer_params=batch_norm_params, scope='Bottleneck', reuse=False) logits = slim.fully_connected( bottleneck, len(train_set), activation_fn=None, weights_initializer=tf.truncated_normal_initializer(stddev=0.1), weights_regularizer=slim.l2_regularizer(args.weight_decay), scope='Logits', reuse=False) embeddings = tf.nn.l2_normalize(bottleneck, 1, 1e-10, name='embeddings') # Add center loss if args.center_loss_factor > 0.0: prelogits_center_loss, _ = facenet.center_loss( prelogits, label_batch, args.center_loss_alfa, nrof_classes) tf.add_to_collection( tf.GraphKeys.REGULARIZATION_LOSSES, prelogits_center_loss * args.center_loss_factor) learning_rate = tf.train.exponential_decay( learning_rate_placeholder, global_step, args.learning_rate_decay_epochs * args.epoch_size, args.learning_rate_decay_factor, staircase=True) tf.summary.scalar('learning_rate', learning_rate) # Calculate the average cross entropy loss across the batch cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits( labels=label_batch, logits=logits, name='cross_entropy_per_example') cross_entropy_mean = tf.reduce_mean(cross_entropy, name='cross_entropy') tf.add_to_collection('losses', cross_entropy_mean) # Calculate the total losses regularization_losses = tf.get_collection( tf.GraphKeys.REGULARIZATION_LOSSES) total_loss = tf.add_n([cross_entropy_mean] + regularization_losses, name='total_loss') # Build a Graph that trains the model with one batch of examples and updates the model parameters train_op = facenet.train(total_loss, global_step, args.optimizer, learning_rate, args.moving_average_decay, tf.global_variables(), args.log_histograms) # Create a saver saver = tf.train.Saver(tf.trainable_variables(), max_to_keep=10) # Build the summary operation based on the TF collection of Summaries. summary_op = tf.summary.merge_all() # Start running operations on the Graph. gpu_options = tf.GPUOptions( per_process_gpu_memory_fraction=args.gpu_memory_fraction) sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options, log_device_placement=False)) sess.run(tf.global_variables_initializer()) sess.run(tf.local_variables_initializer()) summary_writer = tf.summary.FileWriter(log_dir, sess.graph) coord = tf.train.Coordinator() tf.train.start_queue_runners(coord=coord, sess=sess) with sess.as_default(), tf.device('/gpu:1'): if pretrained_model: logging.info('Restoring pretrained model: %s' % pretrained_model) saver.restore(sess, pretrained_model) # Training and validation loop logging.info('Running training') epoch = 0 while epoch < args.max_nrof_epochs: step = sess.run(global_step, feed_dict=None) epoch = step // args.epoch_size # Train for one epoch train(args, sess, epoch, image_list, label_list, index_dequeue_op, enqueue_op, image_paths_placeholder, labels_placeholder, learning_rate_placeholder, phase_train_placeholder, batch_size_placeholder, global_step, total_loss, train_op, summary_op, summary_writer, regularization_losses, args.learning_rate_schedule_file) # Save variables and the metagraph if it doesn't exist already save_variables_and_metagraph(sess, saver, summary_writer, model_dir, subdir, step) # Evaluate on LFW if args.lfw_dir: evaluate(sess, enqueue_op, image_paths_placeholder, labels_placeholder, phase_train_placeholder, batch_size_placeholder, embeddings, label_batch, lfw_paths, actual_issame, args.lfw_batch_size, args.lfw_nrof_folds, log_dir, step, summary_writer) sess.close() return model_dir
def main(args): 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'))#将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, 'inference') subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S') log_dir = os.path.join(os.path.expanduser(args.logs_base_dir), subdir) if not os.path.isdir(log_dir): # Create the log directory if it doesn't exist os.makedirs(log_dir) model_dir = os.path.join(os.path.expanduser(args.models_base_dir), subdir) if not os.path.isdir(model_dir): # Create the model directory if it doesn't exist os.makedirs(model_dir) if args.minutiae_pairs_dir is not None: minutiae_pairs = args.minutiae_pairs_dir.split(':') evaluate_paths = [] evaluate_paths.append(glob.glob(minutiae_pairs[0]+'*.jpeg')) evaluate_paths[0].sort() evaluate_paths.append(glob.glob(minutiae_pairs[1]+'*.jpeg')) evaluate_paths[1].sort() with open(os.path.join(model_dir, 'args.txt'), 'w') as f: for arg in vars(args): f.write(arg + ' ' + str(getattr(args, arg)) + '\n') # Store some git revision info in a text file in the log directory if not args.no_store_revision_info: src_path,_ = os.path.split(os.path.realpath(__file__)) facenet.store_revision_info(src_path, log_dir, ' '.join(sys.argv)) np.random.seed(seed=args.seed) 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_png(file_contents) image = tf.image.decode_jpeg(file_contents, channels=3) #image = facenet.crop(image, None,args.image_size+30) 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)) image = tf.cast(image,tf.float32) #image = tf.image.per_image_standardization(image) distorted_image = tf.image.random_brightness(image, max_delta=32) image = tf.image.random_contrast(distorted_image, lower=0.5, upper=1.5) #images.append(tf.image.per_image_standardization(image)) images.append(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) batch_norm_params = { # Decay for the moving averages 'decay': 0.995, # epsilon to prevent 0s in variance 'epsilon': 0.001, # force in-place updates of mean and variance estimates 'updates_collections': None, # Moving averages ends up in the trainable variables collection 'variables_collections': [ tf.GraphKeys.TRAINABLE_VARIABLES ], # Only update statistics during training mode 'is_training': phase_train_placeholder } # Build the inference graph prelogits, _ = network.inference(image_batch, args.keep_probability, phase_train=phase_train_placeholder, weight_decay=args.weight_decay) #pre_embeddings = slim.fully_connected(prelogits, args.embedding_size, activation_fn=None, # weights_initializer=tf.truncated_normal_initializer(stddev=0.1), # weights_regularizer=slim.l2_regularizer(args.weight_decay), # normalizer_fn=slim.batch_norm, # normalizer_params=batch_norm_params, # scope='Bottleneck', reuse=False) pre_embeddings = _fully_connected(prelogits, args.embedding_size, name='Bottleneck') embeddings = tf.nn.l2_normalize(pre_embeddings, 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) if evaluate_paths: evaluate_NISTSD27(sess, evaluate_paths, embeddings, labels_batch, image_paths_placeholder, labels_placeholder, batch_size_placeholder, learning_rate_placeholder, phase_train_placeholder, enqueue_op, args.batch_size, log_dir, step, summary_writer, args.embedding_size) # 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) sess.close() 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): # 动态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): # 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): network = importlib.import_module(args.model_def) subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S') log_dir = os.path.join(os.path.expanduser(args.logs_base_dir), subdir) if not os.path.isdir(log_dir): # Create the log directory if it doesn't exist os.makedirs(log_dir) model_dir = os.path.join(os.path.expanduser(args.models_base_dir), subdir) if not os.path.isdir(model_dir): # Create the model directory if it doesn't exist os.makedirs(model_dir) # Store some git revision info in a text file in the log directory src_path,_ = os.path.split(os.path.realpath(__file__)) facenet.store_revision_info(src_path, log_dir, ' '.join(sys.argv)) np.random.seed(seed=args.seed) random.seed(args.seed) train_set = facenet.get_dataset(args.data_dir) if args.filter_filename: train_set = filter_dataset(train_set, os.path.expanduser(args.filter_filename), args.filter_percentile, args.filter_min_nrof_images_per_class) nrof_classes = len(train_set) print('Model directory: %s' % model_dir) print('Log directory: %s' % log_dir) pretrained_model = None if args.pretrained_model: pretrained_model = os.path.expanduser(args.pretrained_model) print('Pre-trained model: %s' % pretrained_model) if args.lfw_dir: print('LFW directory: %s' % args.lfw_dir) # Read the file containing the pairs used for testing pairs = lfw.read_pairs(os.path.expanduser(args.lfw_pairs)) # Get the paths for the corresponding images lfw_paths, actual_issame = lfw.get_paths(os.path.expanduser(args.lfw_dir), pairs, args.lfw_file_ext) with tf.Graph().as_default(): tf.set_random_seed(args.seed) global_step = tf.Variable(0, trainable=False) # Get a list of image paths and their labels image_list, label_list = facenet.get_image_paths_and_labels(train_set) assert len(image_list)>0, 'The dataset should not be empty' # Create a queue that produces indices into the image_list and label_list labels = ops.convert_to_tensor(label_list, dtype=tf.int32) range_size = array_ops.shape(labels)[0] index_queue = tf.train.range_input_producer(range_size, num_epochs=None, shuffle=True, seed=None, capacity=32) index_dequeue_op = index_queue.dequeue_many(args.batch_size*args.epoch_size, 'index_dequeue') learning_rate_placeholder = tf.placeholder(tf.float32, name='learning_rate') batch_size_placeholder = tf.placeholder(tf.int32, name='batch_size') phase_train_placeholder = tf.placeholder(tf.bool, name='phase_train') image_paths_placeholder = tf.placeholder(tf.string, shape=(None,1), name='image_paths') labels_placeholder = tf.placeholder(tf.int64, shape=(None,1), name='labels') input_queue = data_flow_ops.FIFOQueue(capacity=100000, dtypes=[tf.string, tf.int64], shapes=[(1,), (1,)], shared_name=None, name=None) enqueue_op = input_queue.enqueue_many([image_paths_placeholder, labels_placeholder], name='enqueue_op') nrof_preprocess_threads = 4 images_and_labels = [] for _ in range(nrof_preprocess_threads): filenames, label = input_queue.dequeue() images = [] for filename in tf.unstack(filenames): file_contents = tf.read_file(filename) image = tf.image.decode_png(file_contents) if args.random_rotate: image = tf.py_func(facenet.random_rotate_image, [image], tf.uint8) if args.random_crop: image = tf.random_crop(image, [args.image_size, args.image_size, 3]) else: image = tf.image.resize_image_with_crop_or_pad(image, args.image_size, args.image_size) if args.random_flip: image = tf.image.random_flip_left_right(image) #pylint: disable=no-member image.set_shape((args.image_size, args.image_size, 3)) images.append(tf.image.per_image_standardization(image)) images_and_labels.append([images, label]) image_batch, label_batch = tf.train.batch_join( images_and_labels, batch_size=batch_size_placeholder, shapes=[(args.image_size, args.image_size, 3), ()], enqueue_many=True, capacity=4 * nrof_preprocess_threads * args.batch_size, allow_smaller_final_batch=True) image_batch = tf.identity(image_batch, 'image_batch') image_batch = tf.identity(image_batch, 'input') label_batch = tf.identity(label_batch, 'label_batch') print('Total number of classes: %d' % nrof_classes) print('Total number of examples: %d' % len(image_list)) print('Building training graph') # Build the inference graph prelogits, _ = network.inference(image_batch, args.keep_probability, phase_train=phase_train_placeholder, bottleneck_layer_size=args.embedding_size, weight_decay=args.weight_decay) logits = slim.fully_connected(prelogits, len(train_set), activation_fn=None, weights_initializer=tf.truncated_normal_initializer(stddev=0.1), weights_regularizer=slim.l2_regularizer(args.weight_decay), scope='Logits', reuse=False) embeddings = tf.nn.l2_normalize(prelogits, 1, 1e-10, name='embeddings') # Add center loss if args.center_loss_factor>0.0: prelogits_center_loss, _ = facenet.center_loss(prelogits, label_batch, args.center_loss_alfa, nrof_classes) tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES, prelogits_center_loss * args.center_loss_factor) learning_rate = tf.train.exponential_decay(learning_rate_placeholder, global_step, args.learning_rate_decay_epochs*args.epoch_size, args.learning_rate_decay_factor, staircase=True) tf.summary.scalar('learning_rate', learning_rate) # Calculate the average cross entropy loss across the batch cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits( labels=label_batch, logits=logits, name='cross_entropy_per_example') cross_entropy_mean = tf.reduce_mean(cross_entropy, name='cross_entropy') tf.add_to_collection('losses', cross_entropy_mean) # Calculate the total losses regularization_losses = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES) total_loss = tf.add_n([cross_entropy_mean] + regularization_losses, name='total_loss') # Build a Graph that trains the model with one batch of examples and updates the model parameters train_op = facenet.train(total_loss, global_step, args.optimizer, learning_rate, args.moving_average_decay, tf.global_variables(), args.log_histograms) # Create a saver saver = tf.train.Saver(tf.trainable_variables(), max_to_keep=3) # Build the summary operation based on the TF collection of Summaries. summary_op = tf.summary.merge_all() # Start running operations on the Graph. gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=args.gpu_memory_fraction) sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options, log_device_placement=False)) sess.run(tf.global_variables_initializer()) sess.run(tf.local_variables_initializer()) summary_writer = tf.summary.FileWriter(log_dir, sess.graph) coord = tf.train.Coordinator() tf.train.start_queue_runners(coord=coord, sess=sess) with sess.as_default(): if pretrained_model: print('Restoring pretrained model: %s' % pretrained_model) saver.restore(sess, pretrained_model) # Training and validation loop print('Running training') epoch = 0 while epoch < args.max_nrof_epochs: step = sess.run(global_step, feed_dict=None) epoch = step // args.epoch_size # Train for one epoch train(args, sess, epoch, image_list, label_list, index_dequeue_op, enqueue_op, image_paths_placeholder, labels_placeholder, learning_rate_placeholder, phase_train_placeholder, batch_size_placeholder, global_step, total_loss, train_op, summary_op, summary_writer, regularization_losses, args.learning_rate_schedule_file) # Save variables and the metagraph if it doesn't exist already save_variables_and_metagraph(sess, saver, summary_writer, model_dir, subdir, step) # Evaluate on LFW if args.lfw_dir: evaluate(sess, enqueue_op, image_paths_placeholder, labels_placeholder, phase_train_placeholder, batch_size_placeholder, embeddings, label_batch, lfw_paths, actual_issame, args.lfw_batch_size, args.lfw_nrof_folds, log_dir, step, summary_writer) sess.close() return model_dir
def main(args): #network = importlib.import_module(args.model_def, 'inception_v3') network = importlib.import_module(args.model_def) subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S') log_dir = os.path.join(os.path.expanduser(args.logs_base_dir), subdir) if not os.path.isdir( log_dir): # Create the log directory if it doesn't exist os.makedirs(log_dir) model_dir = os.path.join(os.path.expanduser(args.models_base_dir), subdir) if not os.path.isdir( model_dir): # Create the model directory if it doesn't exist os.makedirs(model_dir) with open(os.path.join(model_dir, 'args.txt'), 'w') as f: for arg in vars(args): f.write(arg + ' ' + str(getattr(args, arg)) + '\n') # Store some git revision info in a text file in the log directory src_path, _ = os.path.split(os.path.realpath(__file__)) facenet.store_revision_info(src_path, log_dir, ' '.join(sys.argv)) np.random.seed(seed=args.seed) #train_set = facenet.get_dataset(args.data_dir) train_set = facenet.get_dataset_with_enhanced(args.data_dir) nrof_classes = len(train_set) print('Model directory: %s' % model_dir) print('Log directory: %s' % log_dir) pretrained_model = None if args.pretrained_model: pretrained_model = os.path.expanduser(args.pretrained_model) print('Pre-trained model: %s' % pretrained_model) if args.lfw_dir: print('LFW directory: %s' % args.lfw_dir) # Read the file containing the pairs used for testing pairs = lfw.read_pairs(os.path.expanduser(args.lfw_pairs)) # Get the paths for the corresponding images lfw_paths, actual_issame = lfw.get_paths( os.path.expanduser(args.lfw_dir), pairs, args.lfw_file_ext) with tf.Graph().as_default(): tf.set_random_seed(args.seed) global_step = tf.Variable(0, trainable=False) # Get a list of image paths and their labels image_list, label_list = facenet.get_image_paths_and_labels(train_set) # Read data and apply label preserving distortions image_batch, label_batch = facenet.read_and_augument_data( image_list, label_list, args.image_size, args.batch_size, args.max_nrof_epochs, args.random_rotate, args.random_crop, args.random_flip, args.nrof_preprocess_threads, args.padding_size, args.patch_type) #print('Total number of classes: %d' % len(train_set)) print('Total number of examples: %d' % len(image_list)) # Node for input images image_batch = tf.identity(image_batch, name='input') # Placeholder for the learning rate learning_rate_placeholder = tf.placeholder(tf.float32, name='learning_rate') # Placeholder for phase_train phase_train_placeholder = tf.placeholder(tf.bool, name='phase_train') # Placeholder for keep probability keep_probability_placeholder = tf.placeholder(tf.float32, name='keep_prob') # Build the inference graph # prelogits = network.inference(image_batch, keep_probability_placeholder, # phase_train=phase_train_placeholder, weight_decay=args.weight_decay) batch_norm_params = { # Decay for the moving averages 'decay': 0.995, # epsilon to prevent 0s in variance 'epsilon': 0.001, # force in-place updates of mean and variance estimates 'updates_collections': None, # Moving averages ends up in the trainable variables collection 'variables_collections': [tf.GraphKeys.TRAINABLE_VARIABLES], # Only update statistics during training mode 'is_training': phase_train_placeholder } #prelogits, _ = network.inception_v3(image_batch, num_classes=len(train_set),is_training=True) prelogits, _ = network.inference(image_batch, args.keep_probability, phase_train=phase_train_placeholder, weight_decay=args.weight_decay) #prelogits = tf.identity(prelogits, name="prelogits") bottleneck = _fully_connected(prelogits, args.embedding_size, name='pre_embedding') #bottleneck = tf.nn.l2_normalize(bottleneck, dim=1,name='embedding') logits = _fully_connected_classifier(bottleneck, len(train_set), name='logits') """ bottleneck = slim.fully_connected(prelogits, args.embedding_size, activation_fn=None, weights_initializer=tf.truncated_normal_initializer(stddev=0.1), weights_regularizer=slim.l2_regularizer(args.weight_decay), normalizer_fn=slim.batch_norm, normalizer_params=batch_norm_params, scope='Bottleneck', reuse=False) logits = slim.fully_connected(bottleneck, len(train_set), activation_fn=None, weights_initializer=tf.truncated_normal_initializer(stddev=0.1), weights_regularizer=slim.l2_regularizer(args.weight_decay), scope='Logits', reuse=False) logits = tf.identity(logits, name="logits") """ # Add DeCov regularization loss if args.decov_loss_factor > 0.0: logits_decov_loss = facenet.decov_loss( logits) * args.decov_loss_factor tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES, logits_decov_loss) # Add center loss update_centers = tf.no_op('update_centers') if args.center_loss_factor > 0.0: prelogits_center_loss, update_centers = facenet.center_loss( bottleneck, label_batch, args.center_loss_alfa, nrof_classes) tf.add_to_collection( tf.GraphKeys.REGULARIZATION_LOSSES, prelogits_center_loss * args.center_loss_factor) #embeddings = tf.nn.l2_normalize(bottleneck, 1, 1e-10, name='embeddings') learning_rate = tf.train.exponential_decay( learning_rate_placeholder, global_step, args.learning_rate_decay_epochs * args.epoch_size, args.learning_rate_decay_factor, staircase=True) tf.summary.scalar('learning_rate', learning_rate) # Calculate the average cross entropy loss across the batch cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits( labels=label_batch, logits=logits, name='cross_entropy_per_example') cross_entropy_mean = tf.reduce_mean(cross_entropy, name='cross_entropy') """ # Multi-label loss: sigmoid loss sigmoid_loss = tf.nn.sigmoid_cross_entropy_with_logits(labels=label_batch, logits=logits, name='sigmoid_loss_per_example') sigmoid_loss_mean = tf.reduce_mean(sigmoid_loss, name='sigmoid_loss') """ tf.add_to_collection('losses', cross_entropy_mean) # Calculate the total losses regularization_losses = tf.get_collection( tf.GraphKeys.REGULARIZATION_LOSSES) total_loss = tf.add_n([cross_entropy_mean] + regularization_losses, name='total_loss') #total_loss = tf.add_n([cross_entropy_mean], name='total_loss') # prediction prediction = tf.argmax(logits, axis=1, name='prediction') acc = slim.metrics.accuracy(predictions=tf.cast(prediction, dtype=tf.int32), labels=tf.cast(label_batch, dtype=tf.int32)) # Build a Graph that trains the model with one batch of examples and updates the model parameters train_op = facenet.train(total_loss, global_step, args.optimizer, learning_rate, args.moving_average_decay, tf.global_variables()) # Create a saver # save_variables = list(set(tf.all_variables())-set([w])-set([b])) save_variables = tf.trainable_variables() saver = tf.train.Saver(save_variables, max_to_keep=3) # Build the summary operation based on the TF collection of Summaries. summary_op = tf.summary.merge_all() # Start running operations on the Graph. # gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=args.gpu_memory_fraction) # sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options, log_device_placement=False)) config = tf.ConfigProto() config.gpu_options.allow_growth = True sess = tf.Session(config=config) sess.run(tf.global_variables_initializer()) sess.run(tf.local_variables_initializer()) summary_writer = tf.summary.FileWriter(log_dir, sess.graph) tf.train.start_queue_runners(sess=sess) with sess.as_default(): if pretrained_model: saver.restore(sess, pretrained_model) # Training and validation loop epoch = 0 while epoch < args.max_nrof_epochs: step = sess.run(global_step, feed_dict=None) epoch = step // args.epoch_size # Train for one epoch train(args, sess, epoch, phase_train_placeholder, learning_rate_placeholder, keep_probability_placeholder, global_step, total_loss, acc, train_op, summary_op, summary_writer, regularization_losses, args.learning_rate_schedule_file, update_centers) # Evaluate on LFW if args.lfw_dir: start_time = time.time() _, _, accuracy, val, val_std, far = lfw.validate( sess, lfw_paths, actual_issame, args.seed, args.batch_size, image_batch, phase_train_placeholder, keep_probability_placeholder, embeddings, nrof_folds=args.lfw_nrof_folds) print('Accuracy: %1.3f+-%1.3f' % (np.mean(accuracy), np.std(accuracy))) print('Validation rate: %2.5f+-%2.5f @ FAR=%2.5f' % (val, val_std, far)) lfw_time = time.time() - start_time # Add validation loss and accuracy to summary summary = tf.Summary() #pylint: disable=maybe-no-member summary.value.add(tag='lfw/accuracy', simple_value=np.mean(accuracy)) summary.value.add(tag='lfw/val_rate', simple_value=val) summary.value.add(tag='time/lfw', simple_value=lfw_time) summary_writer.add_summary(summary, step) with open(os.path.join(log_dir, 'lfw_result.txt'), 'at') as f: f.write('%d\t%.5f\t%.5f\n' % (step, np.mean(accuracy), val)) # Save variables and the metagraph if it doesn't exist already save_variables_and_metagraph(sess, saver, summary_writer, model_dir, subdir, step) return model_dir
def main(args): 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): #此处导入的是: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): network = importlib.import_module(args.model_def, 'inference') if args.model_name: subdir = args.model_name preload_model = True else: subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S') preload_model = False log_dir = os.path.join(os.path.expanduser(args.logs_base_dir), subdir) if not os.path.isdir( log_dir): # Create the log directory if it doesn't exist os.makedirs(log_dir) model_dir = os.path.join(os.path.expanduser(args.models_base_dir), subdir) if not os.path.isdir( model_dir): # Create the model directory if it doesn't exist os.makedirs(model_dir) # Store some git revision info in a text file in the log directory src_path, _ = os.path.split(os.path.realpath(__file__)) facenet.store_revision_info(src_path, log_dir, ' '.join(sys.argv)) np.random.seed(seed=args.seed) train_set = facenet.get_dataset(args.data_dir) print('Model directory: %s' % model_dir) print('Log directory: %s' % log_dir) # 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 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 input images images_placeholder = tf.placeholder(tf.float32, shape=(None, args.image_size, args.image_size, 3), name='input') # Placeholder for the learning rate labels_placeholder = tf.placeholder(tf.int64, name='labels') # Placeholder for phase_train phase_train_placeholder = tf.placeholder(tf.bool, name='phase_train') # Placeholder for the learning rate learning_rate_placeholder = tf.placeholder(tf.float32, name='learing_rate') # Build the inference graph logits1, _ = network.inference(images_placeholder, [128, len(train_set)], args.keep_probability, phase_train=phase_train_placeholder, weight_decay=args.weight_decay) # Split example embeddings into anchor, positive and negative and calculate triplet loss embeddings = tf.nn.l2_normalize(logits1, 1, 1e-10, name='embeddings') anchor, positive, negative = tf.split(0, 3, embeddings) 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.scalar_summary('learning_rate', learning_rate) # Calculate the total losses regularization_losses = tf.get_collection( tf.GraphKeys.REGULARIZATION_LOSSES) total_triplet_loss = tf.add_n([triplet_loss] + regularization_losses, name='total_triplet_loss') # Build a Graph that trains the model with one batch of examples and updates the model parameters triplet_loss_train_op = facenet.train('tripletloss_', total_triplet_loss, global_step, args.optimizer, learning_rate, args.moving_average_decay) # Create a saver saver = tf.train.Saver(tf.all_variables(), max_to_keep=0) # Build the summary operation based on the TF collection of Summaries. summary_op = tf.merge_all_summaries() # Build an initialization operation to run below. init = tf.initialize_all_variables() # 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)) sess.run(init) summary_writer = tf.train.SummaryWriter(log_dir, sess.graph) with sess.as_default(): if preload_model: ckpt = tf.train.get_checkpoint_state(model_dir) #pylint: disable=maybe-no-member if ckpt and ckpt.model_checkpoint_path: saver.restore(sess, ckpt.model_checkpoint_path) else: raise ValueError('Checkpoint not found') # Training and validation loop epoch = 0 while epoch < args.max_nrof_epochs: epoch = sess.run(global_step, feed_dict=None) // args.epoch_size # Train for one epoch step = train_triplet_loss( args, sess, train_set, epoch, images_placeholder, labels_placeholder, phase_train_placeholder, learning_rate_placeholder, global_step, embeddings, total_triplet_loss, triplet_loss_train_op, summary_op, summary_writer) if args.lfw_dir: _, _, accuracy, val, val_std, far = lfw.validate( sess, paths, actual_issame, args.seed, args.batch_size, images_placeholder, phase_train_placeholder, embeddings, nrof_folds=args.lfw_nrof_folds) print('Accuracy: %1.3f+-%1.3f' % (np.mean(accuracy), np.std(accuracy))) print('Validation rate: %2.5f+-%2.5f @ FAR=%2.5f' % (val, val_std, far)) # Add validation loss and accuracy to summary summary = tf.Summary() #pylint: disable=maybe-no-member summary.value.add(tag='lfw/accuracy', simple_value=np.mean(accuracy)) summary.value.add(tag='lfw/val_rate', simple_value=val) summary_writer.add_summary(summary, step) if (epoch % args.checkpoint_period == 0) or (epoch == args.max_nrof_epochs - 1): # Save the model checkpoint print('Saving checkpoint') checkpoint_path = os.path.join(model_dir, 'model.ckpt') saver.save(sess, checkpoint_path, global_step=step) return model_dir
def main(args): network = importlib.import_module(args.model_def, 'inference') subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S') log_dir = os.path.join(os.path.expanduser(args.logs_base_dir), subdir) # 创建模型文件夹 if not os.path.isdir(log_dir): # Create the log directory if it doesn't exist os.makedirs(log_dir) model_dir = os.path.join(os.path.expanduser(args.models_base_dir), subdir) if not os.path.isdir(model_dir): # Create the model directory if it doesn't exist os.makedirs(model_dir) # Store some git revision info in a text file in the log directory src_path, _ = os.path.split(os.path.realpath(__file__)) facenet.store_revision_info(src_path, log_dir, ' '.join(sys.argv)) np.random.seed(seed=args.seed) train_set = facenet.get_dataset(args.data_dir) nrof_classes = len(train_set) print('Model directory: %s' % model_dir) print('Log directory: %s' % log_dir) pretrained_model = None if args.pretrained_model: pretrained_model = os.path.expanduser(args.pretrained_model) print('Pre-trained model: %s' % pretrained_model) if args.lfw_dir: print('LFW directory: %s' % args.lfw_dir) # Read the file containing the pairs used for testing pairs = lfw.read_pairs(os.path.expanduser(args.lfw_pairs)) # Get the paths for the corresponding images lfw_paths, actual_issame = lfw.get_paths(os.path.expanduser(args.lfw_dir), pairs, args.lfw_file_ext) if args.baihe_pack_file: print('load baihe dataset') lfw_paths, actual_issame = msgpack_numpy.load(open(args.baihe_pack_file)) with tf.Graph().as_default(): tf.set_random_seed(args.seed) # 迭代轮数, 不同的轮数可以使用不同的学习率 global_step = tf.Variable(0, trainable=False) # Get a list of image paths and their labels image_list, label_list = facenet.get_image_paths_and_labels(train_set) # Read data and apply label preserving distortions image_batch, label_batch = facenet.read_and_augment_data(image_list, label_list, args.image_size, args.batch_size, args.max_nrof_epochs, args.random_crop, args.random_flip, args.random_rotate, args.nrof_preprocess_threads) print('Total number of classes: %d' % nrof_classes) print('Total number of examples: %d' % len(image_list)) print('Building training graph') # Placeholder for the learning rate learning_rate_placeholder = tf.placeholder(tf.float32, name='learning_rate') # Build the inference graph, 返回的是网络结构 prelogits, _ = network.inference(image_batch, args.keep_probability, phase_train=True, weight_decay=args.weight_decay) # 初始化采用截断的正态分布噪声, 标准差为0.1 # tf.truncated_normal_initializer(stddev=0.1) logits = slim.fully_connected(prelogits, len(train_set), activation_fn=None, weights_initializer=tf.truncated_normal_initializer(stddev=0.1), weights_regularizer=slim.l2_regularizer(args.weight_decay), scope='Logits', reuse=False) # Add DeCov regularization loss if args.decov_loss_factor > 0.0: logits_decov_loss = facenet.decov_loss(logits) * args.decov_loss_factor # 将decov_loss加入到名字为tf.GraphKeys.REGULARIZATION_LOSSES的集合当中来 tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES, logits_decov_loss) # Add center loss (center_loss作为一个正则项加入到collections) if args.center_loss_factor > 0.0: prelogits_center_loss, _ = facenet.center_loss(prelogits, label_batch, args.center_loss_alfa, nrof_classes) # 将center加入到名字为tf.GraphKeys.REGULARIZATION_LOSSES的集合当中来 tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES, prelogits_center_loss * args.center_loss_factor) # 对学习率进行指数衰退 learning_rate = tf.train.exponential_decay(learning_rate_placeholder, global_step, args.learning_rate_decay_epochs*args.epoch_size, args.learning_rate_decay_factor, staircase=True) tf.scalar_summary('learning_rate', learning_rate) # Calculate the average cross entropy loss across the batch # 将softmax和交叉熵一起做,得到最后的损失函数,提高效率 cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits( logits, label_batch, name='cross_entropy_per_example') cross_entropy_mean = tf.reduce_mean(cross_entropy, name='cross_entropy') tf.add_to_collection('losses', cross_entropy_mean) # Calculate the total losses # 获取正则loss regularization_losses = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES) total_loss = tf.add_n([cross_entropy_mean] + regularization_losses, name='total_loss') # Build a Graph that trains the model with one batch of examples and updates the model parameters train_op = facenet.train(total_loss, global_step, args.optimizer, learning_rate, args.moving_average_decay, tf.all_variables(), args.log_histograms) # Evaluation print('Building evaluation graph') lfw_label_list = range(0, len(lfw_paths)) assert (len(lfw_paths) % args.lfw_batch_size == 0), \ "The number of images in the LFW test set need to be divisible by the lfw_batch_size" eval_image_batch, eval_label_batch = facenet.read_and_augment_data(lfw_paths, lfw_label_list, args.image_size, args.lfw_batch_size, None, False, False, False, args.nrof_preprocess_threads, shuffle=False) # Node for input images eval_image_batch.set_shape((None, args.image_size, args.image_size, 3)) eval_image_batch = tf.identity(eval_image_batch, name='input') eval_prelogits, _ = network.inference(eval_image_batch, 1.0, phase_train=False, weight_decay=0.0, reuse=True) eval_embeddings = tf.nn.l2_normalize(eval_prelogits, 1, 1e-10, name='embeddings') # Create a saver saver = tf.train.Saver(tf.all_variables(), max_to_keep=10) # saver = tf.train.Saver(tf.global_variables(), max_to_keep=10) # Build the summary operation based on the TF collection of Summaries. summary_op = tf.merge_all_summaries() # Start running operations on the Graph. gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=args.gpu_memory_fraction) sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options, log_device_placement=False)) # sess.run(tf.global_variables_initializer()) # sess.run(tf.local_variables_initializer()) sess.run(tf.initialize_all_variables()) sess.run(tf.initialize_local_variables()) summary_writer = tf.train.SummaryWriter(log_dir, sess.graph) tf.train.start_queue_runners(sess=sess) # 将队列runner启动,队列就开始运行,返回启动的线程 # 注意input_queue是先入列,再出列,由于入列的时候输入是place holder,因此到后的线程的时候,会阻塞, # 直到下train中sess run (enqueue_op)的时候, 会向队列中载入值,后面的出列才有对象,才在各自的队列中开始执行 with sess.as_default(): if pretrained_model: print('Restoring pretrained model: %s' % pretrained_model) saver.restore(sess, pretrained_model) # Training and validation loop print('Running training') epoch = 0 while epoch < args.max_nrof_epochs: try: step = sess.run(global_step, feed_dict=None) epoch = step // args.epoch_size # Train for one epoch train(args, sess, epoch, learning_rate_placeholder, global_step, total_loss, train_op, summary_op, summary_writer, regularization_losses, args.learning_rate_schedule_file) # Save variables and the metagraph if it doesn't exist already save_variables_and_metagraph(sess, saver, summary_writer, model_dir, subdir, step) # Evaluate on LFW if args.lfw_dir: evaluate(sess, eval_embeddings, eval_label_batch, actual_issame, args.lfw_batch_size, args.seed, args.lfw_nrof_folds, log_dir, step, summary_writer) # Evaluate on baihe_data if args.baihe_pack_file: evaluate(sess, eval_embeddings, eval_label_batch, actual_issame, args.lfw_batch_size, args.seed, args.lfw_nrof_folds, log_dir, step, summary_writer) except: traceback.print_exc() continue return model_dir
def train(): dataset = facenet.get_dataset(FLAGS.data_dir) train_set, test_set = facenet.split_dataset(dataset, 0.9) fileName = "/home/david/debug4.h5" f = h5py.File(fileName, "r") for item in f.values(): print(item) w1 = f['1w'][:] b1 = f['1b'][:] f.close() print(w1.shape) print(b1.shape) """Train CIFAR-10 for a number of steps.""" with tf.Graph().as_default(): global_step = tf.Variable(0, trainable=False) # Placeholder for input images images_placeholder = tf.placeholder(tf.float32, shape=(FLAGS.batch_size, 96, 96, 3), name='Input') # Build a Graph that computes the logits predictions from the inference model #embeddings = facenet.inference_nn4_max_pool_96(images_placeholder, phase_train=True) conv1 = _conv(images_placeholder, 3, 64, 7, 7, 2, 2, 'SAME', 'conv1_7x7', phase_train=False, use_batch_norm=False, init_weight=w1, init_bias=b1) resh1 = tf.reshape(conv1, [-1, 294912]) embeddings = _affine(resh1, 294912, 128) # Split example embeddings into anchor, positive and negative a, p, n = tf.split(0, 3, embeddings) # Calculate triplet loss loss = facenet.triplet_loss(a, p, n) # Build a Graph that trains the model with one batch of examples and updates the model parameters train_op, grads = facenet.train(loss, global_step) # Create a saver saver = tf.train.Saver(tf.all_variables()) # Build the summary operation based on the TF collection of Summaries. summary_op = tf.merge_all_summaries() # Build an initialization operation to run below. init = tf.initialize_all_variables() # Start running operations on the Graph. sess = tf.Session(config=tf.ConfigProto(log_device_placement=FLAGS.log_device_placement)) sess.run(init) summary_writer = tf.train.SummaryWriter(FLAGS.train_dir, graph_def=sess.graph_def) epoch = 0 with sess.as_default(): while epoch<FLAGS.max_nrof_epochs: batch_number = 0 while batch_number<FLAGS.epoch_size: print('Loading new data') image_data, num_per_class, image_paths = facenet.load_data(train_set) print('Selecting suitable triplets for training') start_time = time.time() emb_list = [] # Run a forward pass for the sampled images nrof_examples_per_epoch = FLAGS.people_per_batch*FLAGS.images_per_person nrof_batches_per_epoch = int(np.floor(nrof_examples_per_epoch/FLAGS.batch_size)) if True: for i in xrange(nrof_batches_per_epoch): feed_dict, _ = facenet.get_batch(images_placeholder, image_data, i) emb_list += sess.run([embeddings], feed_dict=feed_dict) emb_array = np.vstack(emb_list) # Stack the embeddings to a nrof_examples_per_epoch x 128 matrix # Select triplets based on the embeddings apn, nrof_random_negs, nrof_triplets = facenet.select_triplets(emb_array, num_per_class, image_data) duration = time.time() - start_time print('(nrof_random_negs, nrof_triplets) = (%d, %d): time=%.3f seconds' % (nrof_random_negs, nrof_triplets, duration)) count = 0 while count<nrof_triplets*3 and batch_number<FLAGS.epoch_size: start_time = time.time() feed_dict, batch = facenet.get_batch(images_placeholder, apn, batch_number) if (batch_number%20==0): err, summary_str, _ = sess.run([loss, summary_op, train_op], feed_dict=feed_dict) summary_writer.add_summary(summary_str, FLAGS.epoch_size*epoch+batch_number) else: err, _ = sess.run([loss, train_op], feed_dict=feed_dict) duration = time.time() - start_time print('Epoch: [%d][%d/%d]\tTime %.3f\ttripErr %2.3f' % (epoch, batch_number, FLAGS.epoch_size, duration, err)) batch_number+=1 count+=FLAGS.batch_size else: while batch_number<FLAGS.epoch_size: start_time = time.time() feed_dict, _ = facenet.get_batch(images_placeholder, image_data, batch_number) grad_tensors, grad_vars = zip(*grads) eval_list = (train_op, loss) + grad_tensors result = sess.run(eval_list, feed_dict=feed_dict) grads_eval = result[2:] nrof_parameters = 0 for gt, gv in zip(grads_eval, grad_vars): print('%40s: %6d' % (gv.op.name, np.size(gt))) nrof_parameters += np.size(gt) print('Total number of parameters: %d' % nrof_parameters) err = result[1] batch_number+=1 epoch+=1 # Save the model checkpoint periodically. checkpoint_path = os.path.join(FLAGS.train_dir, 'model.ckpt') saver.save(sess, checkpoint_path, global_step=epoch*FLAGS.epoch_size+batch_number)
def main(args): network = importlib.import_module(args.model_def, 'inference') if args.model_name: subdir = args.model_name preload_model = True else: subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S') preload_model = False 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.mkdir(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.mkdir(model_dir) # Store some git revision info in a text file in the log directory src_path,_ = os.path.split(os.path.realpath(__file__)) facenet.store_revision_info(src_path, log_dir, ' '.join(sys.argv)) np.random.seed(seed=args.seed) train_set = facenet.get_dataset(args.data_dir) print('Model directory: %s' % model_dir) # 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 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 input images images_placeholder = tf.placeholder(tf.float32, shape=(None, args.image_size, args.image_size, 3), name='input') # Placeholder for phase_train phase_train_placeholder = tf.placeholder(tf.bool, name='phase_train') # Build the inference graph embeddings = network.inference(images_placeholder, args.pool_type, args.use_lrn, args.keep_probability, phase_train=phase_train_placeholder, weight_decay=args.weight_decay) # Split example embeddings into anchor, positive and negative anchor, positive, negative = tf.split(0, 3, embeddings) # Calculate triplet loss loss = facenet.triplet_loss(anchor, positive, negative, args.alpha) # Calculate the total loss regularization_losses = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES) total_loss = tf.add_n([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, args.learning_rate, args.learning_rate_decay_epochs*args.epoch_size, args.learning_rate_decay_factor, args.moving_average_decay) # Create a saver saver = tf.train.Saver(tf.all_variables(), max_to_keep=0) # Build the summary operation based on the TF collection of Summaries. summary_op = tf.merge_all_summaries() # Build an initialization operation to run below. init = tf.initialize_all_variables() # Start running operations on the Graph. sess = tf.Session() sess.run(init) summary_writer = tf.train.SummaryWriter(log_dir, sess.graph) with sess.as_default(): if preload_model: ckpt = tf.train.get_checkpoint_state(model_dir) if ckpt and ckpt.model_checkpoint_path: saver.restore(sess, ckpt.model_checkpoint_path) else: raise ValueError('Checkpoint not found') # Training and validation loop for epoch in range(args.max_nrof_epochs): # Train for one epoch step = train(args, sess, train_set, epoch, images_placeholder, phase_train_placeholder, global_step, embeddings, loss, train_op, summary_op, summary_writer) _, _, accuracy, val, val_std, far = lfw.validate(sess, paths, actual_issame, args.seed, args.batch_size, images_placeholder, phase_train_placeholder, embeddings, nrof_folds=args.lfw_nrof_folds) print('Accuracy: %1.3f+-%1.3f' % (np.mean(accuracy), np.std(accuracy))) print('Validation rate: %2.5f+-%2.5f @ FAR=%2.5f' % (val, val_std, far)) # Add validation loss and accuracy to summary summary = tf.Summary() summary.value.add(tag='lfw/accuracy', simple_value=np.mean(accuracy)) summary.value.add(tag='lfw/val_rate', simple_value=val) summary_writer.add_summary(summary, step) if (epoch % args.checkpoint_period == 0) or (epoch==args.max_nrof_epochs-1): # Save the model checkpoint print('Saving checkpoint') checkpoint_path = os.path.join(model_dir, 'model.ckpt') saver.save(sess, checkpoint_path, global_step=step) return model_dir
def main(args): os.environ["CUDA_VISIBLE_DEVICES"] = '0' network = importlib.import_module(args.model_def) subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S') log_dir = os.path.join(os.path.expanduser(args.logs_base_dir), subdir) if not os.path.isdir( log_dir): # Create the log directory if it doesn't exist os.makedirs(log_dir) model_dir = os.path.join(os.path.expanduser(args.models_base_dir), subdir) if not os.path.isdir( model_dir): # Create the model directory if it doesn't exist os.makedirs(model_dir) # Write arguments to a text file facenet.write_arguments_to_file(args, os.path.join(log_dir, 'arguments.txt')) # Store some git revision info in a text file in the log directory src_path, _ = os.path.split(os.path.realpath(__file__)) facenet.store_revision_info(src_path, log_dir, ' '.join(sys.argv)) np.random.seed(seed=args.seed) random.seed(args.seed) train_set = facenet.get_dataset(args.data_dir) train_set, test_set = facenet.split_dataset(train_set, 0.8, mode='SPLIT_IMAGES') if args.filter_filename: train_set = filter_dataset(train_set, os.path.expanduser(args.filter_filename), args.filter_percentile, args.filter_min_nrof_images_per_class) nrof_classes = len(train_set) test_nrof_classes = len(test_set) print('Model directory: %s' % model_dir) print('Log directory: %s' % log_dir) pretrained_model = None if args.pretrained_model: pretrained_model = os.path.expanduser(args.pretrained_model) # meta_file, ckpt_model=facenet.get_model_filenames(pretrained_model) # pretrained_model=ckpt_model print('Pre-trained model: %s' % pretrained_model) if args.lfw_dir: print('LFW directory: %s' % args.lfw_dir) # Read the file containing the pairs used for testing pairs = lfw.read_pairs(os.path.expanduser(args.lfw_pairs)) # Get the paths for the corresponding images lfw_paths, actual_issame = lfw.get_paths( os.path.expanduser(args.lfw_dir), pairs, args.lfw_file_ext) with tf.Graph().as_default(): tf.set_random_seed(args.seed) global_step = tf.Variable(0, trainable=False) # Get a list of image paths and their labels image_list, label_list = facenet.get_image_paths_and_labels(train_set) assert len(image_list) > 0, 'The dataset should not be empty' test_image_list, test_label_list = facenet.get_image_paths_and_labels( test_set) assert len(test_image_list) > 0, 'The dataset should not be empty' # Create a queue that produces indices into the image_list and label_list labels = ops.convert_to_tensor(label_list, dtype=tf.int32) range_size = array_ops.shape(labels)[0] index_queue = tf.train.range_input_producer(range_size, num_epochs=None, shuffle=True, seed=None, capacity=32) index_dequeue_op = index_queue.dequeue_many( args.batch_size * args.epoch_size, 'index_dequeue') learning_rate_placeholder = tf.placeholder(tf.float32, name='learning_rate') batch_size_placeholder = tf.placeholder(tf.int32, name='batch_size') phase_train_placeholder = tf.placeholder(tf.bool, name='phase_train') image_paths_placeholder = tf.placeholder(tf.string, shape=(None, 1), name='image_paths') labels_placeholder = tf.placeholder(tf.int64, shape=(None, 1), name='labels') input_queue = data_flow_ops.FIFOQueue(capacity=100000, dtypes=[tf.string, tf.int64], shapes=[(1, ), (1, )], shared_name=None, name=None) enqueue_op = input_queue.enqueue_many( [image_paths_placeholder, labels_placeholder], name='enqueue_op') nrof_preprocess_threads = 4 images_and_labels = [] for _ in range(nrof_preprocess_threads): filenames, label = input_queue.dequeue() images = [] for filename in tf.unstack(filenames): file_contents = tf.read_file(filename) image = tf.image.decode_image(file_contents, channels=3) if args.random_rotate: image = tf.py_func(facenet.random_rotate_image, [image], tf.uint8) if args.random_crop: image = tf.random_crop( image, [args.image_size, args.image_size, 3]) else: image = tf.image.resize_image_with_crop_or_pad( image, args.image_size, args.image_size) if args.random_flip: image = tf.image.random_flip_left_right(image) #pylint: disable=no-member image.set_shape((args.image_size, args.image_size, 3)) images.append(tf.image.per_image_standardization(image)) images_and_labels.append([images, label]) image_batch, label_batch = tf.train.batch_join( images_and_labels, batch_size=batch_size_placeholder, shapes=[(args.image_size, args.image_size, 3), ()], enqueue_many=True, capacity=4 * nrof_preprocess_threads * args.batch_size, allow_smaller_final_batch=True) image_batch = tf.identity(image_batch, 'image_batch') image_batch = tf.identity(image_batch, 'input') label_batch = tf.identity(label_batch, 'label_batch') print('Total number of classes: %d' % nrof_classes) print('Total number of examples: %d' % len(image_list)) # Create a queue that produces indices into the test_image_list and test_label_list test_labels = ops.convert_to_tensor(test_label_list, dtype=tf.int32) test_range_size = array_ops.shape(test_labels)[0] test_index_queue = tf.train.range_input_producer(test_range_size, num_epochs=None, shuffle=True, seed=None, capacity=32) # global test_batch_size # test_batch_size=args.batch_size test_index_dequeue_op = test_index_queue.dequeue_many( test_batch_size * test_epoch_size, 'test_index_dequeue') test_input_queue = data_flow_ops.FIFOQueue( capacity=100000, dtypes=[tf.string, tf.int64], shapes=[(1, ), (1, )], shared_name=None, name=None) test_enqueue_op = test_input_queue.enqueue_many( [image_paths_placeholder, labels_placeholder], name='test_enqueue_op') test_nrof_preprocess_threads = 4 test_images_and_labels = [] for _ in range(test_nrof_preprocess_threads): filenames, label = test_input_queue.dequeue() images = [] for filename in tf.unstack(filenames): file_contents = tf.read_file(filename) image = tf.image.decode_image(file_contents, channels=3) if args.random_rotate: image = tf.py_func(facenet.random_rotate_image, [image], tf.uint8) if args.random_crop: image = tf.random_crop( image, [args.image_size, args.image_size, 3]) else: image = tf.image.resize_image_with_crop_or_pad( image, args.image_size, args.image_size) if args.random_flip: image = tf.image.random_flip_left_right(image) # pylint: disable=no-member image.set_shape((args.image_size, args.image_size, 3)) images.append(tf.image.per_image_standardization(image)) test_images_and_labels.append([images, label]) test_image_batch, test_label_batch = tf.train.batch_join( test_images_and_labels, batch_size=test_batch_size, shapes=[(args.image_size, args.image_size, 3), ()], enqueue_many=True, capacity=4 * test_nrof_preprocess_threads * test_batch_size, allow_smaller_final_batch=True) test_image_batch = tf.identity(test_image_batch, 'test_image_batch') test_image_batch = tf.identity(test_image_batch, 'test_input') test_label_batch = tf.identity(test_label_batch, 'test_label_batch') print('Total number of test classes: %d' % test_nrof_classes) print('Total number of test examples: %d' % len(test_image_list)) image_input_placeholder = tf.get_default_graph().get_tensor_by_name( "input:0") label_input_placeholder = tf.get_default_graph().get_tensor_by_name( "label_batch:0") print('Building training graph') # Build the inference graph print("embeddings size is: %s" % (str(args.embedding_size))) prelogits, _ = network.inference( image_batch, args.keep_probability, phase_train=phase_train_placeholder, bottleneck_layer_size=args.embedding_size, weight_decay=args.weight_decay) logits = slim.fully_connected( prelogits, len(train_set), activation_fn=None, weights_initializer=tf.truncated_normal_initializer(stddev=0.1), weights_regularizer=slim.l2_regularizer(args.weight_decay), scope='Logits', reuse=False) embeddings = tf.nn.l2_normalize(prelogits, 1, 1e-10, name='embeddings') # Add center loss if args.center_loss_factor > 0.0: prelogits_center_loss, _ = facenet.center_loss( prelogits, label_batch, args.center_loss_alfa, nrof_classes) tf.add_to_collection( tf.GraphKeys.REGULARIZATION_LOSSES, prelogits_center_loss * args.center_loss_factor) learning_rate = tf.train.exponential_decay( learning_rate_placeholder, global_step, args.learning_rate_decay_epochs * args.epoch_size, args.learning_rate_decay_factor, staircase=True) tf.summary.scalar('learning_rate', learning_rate) # Calculate the average cross entropy loss across the batch cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits( labels=label_batch, logits=logits, name='cross_entropy_per_example') cross_entropy_mean = tf.reduce_mean(cross_entropy, name='cross_entropy') tf.add_to_collection('losses', cross_entropy_mean) # Calculate the total losses regularization_losses = tf.get_collection( tf.GraphKeys.REGULARIZATION_LOSSES) total_loss = tf.add_n([cross_entropy_mean] + regularization_losses, name='total_loss') # Build a Graph that trains the model with one batch of examples and updates the model parameters train_op = facenet.train(total_loss, global_step, args.optimizer, learning_rate, args.moving_average_decay, tf.global_variables(), args.log_histograms) # Create a saver if args.pretrained_model: variables = [] for v in tf.trainable_variables(): if v.name.startswith("Logits") or v.name.startswith( "InceptionResnetV1/Block8") or v.name.startswith( "InceptionResnetV1/Block17"): print("skip variable %s" % v.name) continue else: print("var name %s" % v.name) variables.append(v) # if not v.name.startswith("Logits") and not v.name.startswith("Block8"): # variables.append(v) saver = tf.train.Saver(variables, max_to_keep=3) else: saver = tf.train.Saver(tf.trainable_variables(), max_to_keep=3) # Build the summary operation based on the TF collection of Summaries. summary_op = tf.summary.merge_all() # Start running operations on the Graph. gpu_options = tf.GPUOptions( per_process_gpu_memory_fraction=args.gpu_memory_fraction) sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options, log_device_placement=False)) sess.run(tf.global_variables_initializer()) sess.run(tf.local_variables_initializer()) summary_writer = tf.summary.FileWriter(log_dir, sess.graph) coord = tf.train.Coordinator() tf.train.start_queue_runners(coord=coord, sess=sess) with sess.as_default(): if pretrained_model: print('Restoring pretrained model: %s' % pretrained_model) saver.restore(sess, pretrained_model) # Training and validation loop print('Running training') epoch = 0 while epoch < args.max_nrof_epochs: step = sess.run(global_step, feed_dict=None) #epoch = step // args.epoch_size # Train for one epoch step=train(args, sess, epoch, image_list, label_list, index_dequeue_op, enqueue_op, image_paths_placeholder, labels_placeholder, learning_rate_placeholder, phase_train_placeholder, batch_size_placeholder, global_step, total_loss, train_op, summary_op, summary_writer, regularization_losses, args.learning_rate_schedule_file\ ,test_image_list, test_label_list, test_index_dequeue_op, test_enqueue_op,image_batch, label_batch) # Save variables and the metagraph if it doesn't exist already save_variables_and_metagraph(sess, saver, summary_writer, model_dir, subdir, step) epoch += 1 # Evaluate on LFW if args.lfw_dir: evaluate(sess, enqueue_op, image_paths_placeholder, labels_placeholder, phase_train_placeholder, batch_size_placeholder, embeddings, label_batch, lfw_paths, actual_issame, args.lfw_batch_size, args.lfw_nrof_folds, log_dir, step, summary_writer) # constant_graph = graph_util.convert_variables_to_constants(sess, sess.graph_def, ["embeddings"]) # with tf.gfile.FastGFile(model_dir + '/video-faces_%d_model.pb'%args.max_nrof_epochs, mode='wb') as f: # f.write(constant_graph.SerializeToString()) return model_dir
def main(args): network = importlib.import_module(args.model_def, 'inference') subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S') log_dir = os.path.join(os.path.expanduser(args.logs_base_dir), subdir) if not os.path.isdir(log_dir): # Create the log directory if it doesn't exist os.makedirs(log_dir) model_dir = os.path.join(os.path.expanduser(args.models_base_dir), subdir) if not os.path.isdir(model_dir): # Create the model directory if it doesn't exist os.makedirs(model_dir) # Store some git revision info in a text file in the log directory src_path,_ = os.path.split(os.path.realpath(__file__)) facenet.store_revision_info(src_path, log_dir, ' '.join(sys.argv)) np.random.seed(seed=args.seed) train_set = facenet.get_dataset(args.data_dir) print('Model directory: %s' % model_dir) print('Log directory: %s' % log_dir) 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 input images images_placeholder = tf.placeholder(tf.float32, shape=(None, args.image_size, args.image_size, 3), name='input') # Placeholder for phase_train phase_train_placeholder = tf.placeholder(tf.bool, name='phase_train') # Placeholder for the learning rate learning_rate_placeholder = tf.placeholder(tf.float32, name='learning_rate') # Build the inference graph prelogits, _ = network.inference(images_placeholder, args.keep_probability, phase_train=True, weight_decay=args.weight_decay) pre_embeddings = slim.fully_connected(prelogits, 128, activation_fn=None, scope='Embeddings', reuse=False) # Split example embeddings into anchor, positive and negative and calculate triplet loss embeddings = tf.nn.l2_normalize(pre_embeddings, 1, 1e-10, name='embeddings') anchor, positive, negative = tf.split(0, 3, embeddings) 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.scalar_summary('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') # Create list with variables to restore restore_vars = [] update_gradient_vars = [] if args.pretrained_model: for var in tf.all_variables(): if not 'Embeddings/' in var.op.name: restore_vars.append(var) else: update_gradient_vars.append(var) else: restore_vars = tf.all_variables() update_gradient_vars = tf.all_variables() # Build a Graph that trains the model with one batch of examples and updates the model parameters train_op = facenet.train(total_loss, global_step, args.optimizer, learning_rate, args.moving_average_decay, update_gradient_vars) # Create a saver restore_saver = tf.train.Saver(restore_vars) saver = tf.train.Saver(tf.all_variables(), max_to_keep=3) # Build the summary operation based on the TF collection of Summaries. summary_op = tf.merge_all_summaries() # Start running operations on the Graph. gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=args.gpu_memory_fraction) sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options)) # Initialize variables sess.run(tf.initialize_all_variables()) sess.run(tf.initialize_local_variables()) summary_writer = tf.train.SummaryWriter(log_dir, sess.graph) tf.train.start_queue_runners(sess=sess) with sess.as_default(): if args.pretrained_model: restore_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 step = train(args, sess, train_set, epoch, images_placeholder, learning_rate_placeholder, global_step, embeddings, total_loss, train_op, summary_op, summary_writer) if args.lfw_dir: _, _, accuracy, val, val_std, far = lfw.validate(sess, lfw_paths, actual_issame, args.seed, 60, images_placeholder, phase_train_placeholder, embeddings, nrof_folds=args.lfw_nrof_folds) print('Accuracy: %1.3f+-%1.3f' % (np.mean(accuracy), np.std(accuracy))) print('Validation rate: %2.5f+-%2.5f @ FAR=%2.5f' % (val, val_std, far)) # Add validation loss and accuracy to summary summary = tf.Summary() #pylint: disable=maybe-no-member summary.value.add(tag='lfw/accuracy', simple_value=np.mean(accuracy)) summary.value.add(tag='lfw/val_rate', simple_value=val) summary_writer.add_summary(summary, step) # Save the model checkpoint print('Saving checkpoint') checkpoint_path = os.path.join(model_dir, 'model.ckpt') saver.save(sess, checkpoint_path, global_step=step) return model_dir