def main(args):
    subdir = time.strftime('%Y%m%d-%H%M%S', time.localtime())
    log_dir = os.path.join(os.path.expanduser(args.logs_base_dir), subdir)
    if not os.path.isdir(
            log_dir):  # Create the log directory if it doesn't exist
        os.makedirs(log_dir)
    model_dir = os.path.join(os.path.expanduser(args.models_base_dir), subdir)
    if not os.path.isdir(
            model_dir):  # Create the model directory if it doesn't exist
        os.makedirs(model_dir)

    # Write arguments to a text file
    facenet.write_arguments_to_file(args, os.path.join(log_dir,
                                                       'arguments.txt'))
    with tf.Graph().as_default():
        with tf.Session() as sess:
            facenet.load_model(model_path)
            images_placeholder = tf.get_default_graph().get_tensor_by_name(
                'input:0')
            embeddings = tf.get_default_graph().get_tensor_by_name(
                'embeddings:0')
            phase_train_placeholder = tf.get_default_graph(
            ).get_tensor_by_name('phase_train:0')

            target = tf.placeholder(dtype=tf.int64,
                                    shape=(None, 2),
                                    name='target_output')

            fc1 = tf.layers.dense(inputs=embeddings,
                                  units=64,
                                  activation='relu',
                                  use_bias=True)
            fc2 = tf.layers.dense(inputs=fc1, units=2, use_bias=True)
            res = tf.nn.softmax(logits=fc2)

            loss = tf.reduce_sum(
                tf.multiply(tf.subtract(res, target), tf.subtract(res,
                                                                  target)))

            train_step = tf.train.GradientDescentOptimizer(0.5).minimize(loss)

            tf.global_variables_initializer().run()
Beispiel #2
0
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
Beispiel #3
0
def main(args):

    img_mean = np.array([134.10714722, 102.52040863, 87.15436554])
    img_stddev = np.sqrt(
        np.array([3941.30175781, 2856.94287109, 2519.35791016]))

    vae_def = importlib.import_module(args.vae_def)
    vae = vae_def.Vae(args.latent_var_size)
    gen_image_size = vae.get_image_size()

    subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S')
    model_dir = os.path.join(os.path.expanduser(args.models_base_dir), subdir)
    if not os.path.isdir(
            model_dir):  # Create the model directory if it doesn't exist
        os.makedirs(model_dir)
    log_file_name = os.path.join(model_dir, 'logs.h5')

    # Write arguments to a text file
    facenet.write_arguments_to_file(args,
                                    os.path.join(model_dir, 'arguments.txt'))

    # Store some git revision info in a text file in the log directory
    src_path, _ = os.path.split(os.path.realpath(__file__))
    facenet.store_revision_info(src_path, model_dir, ' '.join(sys.argv))

    with tf.Graph().as_default():
        tf.set_random_seed(args.seed)
        global_step = tf.Variable(0, trainable=False)

        train_set = facenet.get_dataset(args.data_dir)
        image_list, _ = facenet.get_image_paths_and_labels(train_set)

        # Create the input queue
        input_queue = tf.train.string_input_producer(image_list, shuffle=True)

        nrof_preprocess_threads = 4
        image_per_thread = []
        for _ in range(nrof_preprocess_threads):
            file_contents = tf.read_file(input_queue.dequeue())
            image = tf.image.decode_image(file_contents, channels=3)
            image = tf.image.resize_image_with_crop_or_pad(
                image, args.input_image_size, args.input_image_size)
            image.set_shape((args.input_image_size, args.input_image_size, 3))
            image = tf.cast(image, tf.float32)
            #pylint: disable=no-member
            image_per_thread.append([image])

        images = tf.train.batch_join(image_per_thread,
                                     batch_size=args.batch_size,
                                     capacity=4 * nrof_preprocess_threads *
                                     args.batch_size,
                                     allow_smaller_final_batch=False)

        # Normalize
        images_norm = (images - img_mean) / img_stddev

        # Resize to appropriate size for the encoder
        images_norm_resize = tf.image.resize_images(
            images_norm, (gen_image_size, gen_image_size))

        # Create encoder network
        mean, log_variance = vae.encoder(images_norm_resize, True)

        epsilon = tf.random_normal((tf.shape(mean)[0], args.latent_var_size))
        std = tf.exp(log_variance / 2)
        latent_var = mean + epsilon * std

        # Create decoder network
        reconstructed_norm = vae.decoder(latent_var, True)

        # Un-normalize
        reconstructed = (reconstructed_norm * img_stddev) + img_mean

        # Create reconstruction loss
        if args.reconstruction_loss_type == 'PLAIN':
            images_resize = tf.image.resize_images(
                images, (gen_image_size, gen_image_size))
            reconstruction_loss = tf.reduce_mean(
                tf.reduce_sum(tf.pow(images_resize - reconstructed, 2)))
        elif args.reconstruction_loss_type == 'PERCEPTUAL':
            network = importlib.import_module(args.model_def)

            reconstructed_norm_resize = tf.image.resize_images(
                reconstructed_norm,
                (args.input_image_size, args.input_image_size))

            # Stack images from both the input batch and the reconstructed batch in a new tensor
            shp = [-1] + images_norm.get_shape().as_list()[1:]
            input_images = tf.reshape(
                tf.stack([images_norm, reconstructed_norm_resize], axis=0),
                shp)
            _, end_points = network.inference(input_images,
                                              1.0,
                                              phase_train=False,
                                              bottleneck_layer_size=128,
                                              weight_decay=0.0)

            # Get a list of feature names to use for loss terms
            feature_names = args.loss_features.replace(' ', '').split(',')

            # Calculate L2 loss between original and reconstructed images in feature space
            reconstruction_loss_list = []
            for feature_name in feature_names:
                feature_flat = slim.flatten(end_points[feature_name])
                image_feature, reconstructed_feature = tf.unstack(tf.reshape(
                    feature_flat, [2, args.batch_size, -1]),
                                                                  num=2,
                                                                  axis=0)
                reconstruction_loss = tf.reduce_mean(tf.reduce_sum(
                    tf.pow(image_feature - reconstructed_feature, 2)),
                                                     name=feature_name +
                                                     '_loss')
                reconstruction_loss_list.append(reconstruction_loss)
            # Sum up the losses in for the different features
            reconstruction_loss = tf.add_n(reconstruction_loss_list,
                                           'reconstruction_loss')
        else:
            pass

        # Create KL divergence loss
        kl_loss = kl_divergence_loss(mean, log_variance)
        kl_loss_mean = tf.reduce_mean(kl_loss)

        total_loss = args.alfa * kl_loss_mean + args.beta * reconstruction_loss

        learning_rate = tf.train.exponential_decay(
            args.initial_learning_rate,
            global_step,
            args.learning_rate_decay_steps,
            args.learning_rate_decay_factor,
            staircase=True)

        # Calculate gradients and make sure not to include parameters for the perceptual loss model
        opt = tf.train.AdamOptimizer(learning_rate)
        grads = opt.compute_gradients(total_loss,
                                      var_list=get_variables_to_train())

        # Apply gradients
        apply_gradient_op = opt.apply_gradients(grads, global_step=global_step)
        with tf.control_dependencies([apply_gradient_op]):
            train_op = tf.no_op(name='train')

        # Create a saver
        saver = tf.train.Saver(tf.trainable_variables(), max_to_keep=3)

        facenet_saver = tf.train.Saver(get_facenet_variables_to_restore())

        # Start running operations on the Graph
        gpu_memory_fraction = 1.0
        gpu_options = tf.compat.v1.GPUOptions(
            per_process_gpu_memory_fraction=gpu_memory_fraction)
        sess = tf.compat.v1.Session(config=tf.compat.v1.ConfigProto(
            gpu_options=gpu_options, log_device_placement=False))
        sess.run(tf.global_variables_initializer())
        sess.run(tf.local_variables_initializer())
        coord = tf.train.Coordinator()
        tf.train.start_queue_runners(coord=coord, sess=sess)

        with sess.as_default():

            if args.reconstruction_loss_type == 'PERCEPTUAL':
                if not args.pretrained_model:
                    raise ValueError(
                        'A pretrained model must be specified when using perceptual loss'
                    )
                pretrained_model_exp = os.path.expanduser(
                    args.pretrained_model)
                print('Restoring pretrained model: %s' % pretrained_model_exp)
                facenet_saver.restore(sess, pretrained_model_exp)

            log = {
                'total_loss': np.zeros((0, ), np.float),
                'reconstruction_loss': np.zeros((0, ), np.float),
                'kl_loss': np.zeros((0, ), np.float),
                'learning_rate': np.zeros((0, ), np.float),
            }

            step = 0
            print('Running training')
            while step < args.max_nrof_steps:
                start_time = time.time()
                step += 1
                save_state = step > 0 and (step % args.save_every_n_steps == 0
                                           or step == args.max_nrof_steps)
                if save_state:
                    _, reconstruction_loss_, kl_loss_mean_, total_loss_, learning_rate_, rec_ = sess.run(
                        [
                            train_op, reconstruction_loss, kl_loss_mean,
                            total_loss, learning_rate, reconstructed
                        ])
                    img = facenet.put_images_on_grid(rec_, shape=(16, 8))
                    misc.imsave(
                        os.path.join(model_dir,
                                     'reconstructed_%06d.png' % step), img)
                else:
                    _, reconstruction_loss_, kl_loss_mean_, total_loss_, learning_rate_ = sess.run(
                        [
                            train_op, reconstruction_loss, kl_loss_mean,
                            total_loss, learning_rate
                        ])
                log['total_loss'] = np.append(log['total_loss'], total_loss_)
                log['reconstruction_loss'] = np.append(
                    log['reconstruction_loss'], reconstruction_loss_)
                log['kl_loss'] = np.append(log['kl_loss'], kl_loss_mean_)
                log['learning_rate'] = np.append(log['learning_rate'],
                                                 learning_rate_)

                duration = time.time() - start_time
                print(
                    'Step: %d \tTime: %.3f \trec_loss: %.3f \tkl_loss: %.3f \ttotal_loss: %.3f'
                    % (step, duration, reconstruction_loss_, kl_loss_mean_,
                       total_loss_))

                if save_state:
                    print('Saving checkpoint file')
                    checkpoint_path = os.path.join(model_dir, 'model.ckpt')
                    saver.save(sess,
                               checkpoint_path,
                               global_step=step,
                               write_meta_graph=False)
                    print('Saving log')
                    with h5py.File(log_file_name, 'w') as f:
                        for key, value in iteritems(log):
                            f.create_dataset(key, data=value)
Beispiel #4
0
def main(args):
  
    network = importlib.import_module(args.model_def)

    subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S')
    log_dir = os.path.join(os.path.expanduser(args.logs_base_dir), subdir)
    if not os.path.isdir(log_dir):  # Create the log directory if it doesn't exist
        os.makedirs(log_dir)
    model_dir = os.path.join(os.path.expanduser(args.models_base_dir), subdir)
    if not os.path.isdir(model_dir):  # Create the model directory if it doesn't exist
        os.makedirs(model_dir)

    # Write arguments to a text file
    facenet.write_arguments_to_file(args, os.path.join(log_dir, 'arguments.txt'))
        
    # Store some git revision info in a text file in the log directory
    src_path,_ = os.path.split(os.path.realpath(__file__))
    facenet.store_revision_info(src_path, log_dir, ' '.join(sys.argv))

    np.random.seed(seed=args.seed)
    random.seed(args.seed)
    train_set = facenet.get_dataset(args.data_dir)
    if args.filter_filename:
        train_set = filter_dataset(train_set, os.path.expanduser(args.filter_filename), 
            args.filter_percentile, args.filter_min_nrof_images_per_class)
    nrof_classes = len(train_set)
    
    print('Model directory: %s' % model_dir)
    print('Log directory: %s' % log_dir)
    pretrained_model = None
    if args.pretrained_model:
        pretrained_model = os.path.expanduser(args.pretrained_model)
        print('Pre-trained model: %s' % pretrained_model)
    
    if args.lfw_dir:
        print('LFW directory: %s' % args.lfw_dir)
        # Read the file containing the pairs used for testing
        pairs = lfw.read_pairs(os.path.expanduser(args.lfw_pairs))
        # Get the paths for the corresponding images
        lfw_paths, actual_issame = lfw.get_paths(os.path.expanduser(args.lfw_dir), pairs, args.lfw_file_ext)
    
    with tf.Graph().as_default(), tf.device('/cpu:0'):
        tf.set_random_seed(args.seed)
        global_step = tf.Variable(0, trainable=False)
        
        # Get a list of image paths and their labels
        image_list, label_list = facenet.get_image_paths_and_labels(train_set)
        assert len(image_list)>0, 'The dataset should not be empty'
        
        # Create a queue that produces indices into the image_list and label_list 
        labels = ops.convert_to_tensor(label_list, dtype=tf.int32)
        range_size = array_ops.shape(labels)[0]
        index_queue = tf.train.range_input_producer(range_size, num_epochs=None,
                             shuffle=True, seed=None, capacity=32)
        
        index_dequeue_op = index_queue.dequeue_many(args.batch_size*args.epoch_size, 'index_dequeue')
        
        learning_rate_placeholder = tf.placeholder(tf.float32, name='learning_rate')

        batch_size_placeholder = tf.placeholder(tf.int32, name='batch_size')
        
        phase_train_placeholder = tf.placeholder(tf.bool, name='phase_train')
        
        image_paths_placeholder = tf.placeholder(tf.string, shape=(None,1), name='image_paths')

        labels_placeholder = tf.placeholder(tf.int64, shape=(None,1), name='labels')
        
        input_queue = data_flow_ops.FIFOQueue(capacity=100000,
                                    dtypes=[tf.string, tf.int64],
                                    shapes=[(1,), (1,)],
                                    shared_name=None, name=None)
        enqueue_op = input_queue.enqueue_many([image_paths_placeholder, labels_placeholder], name='enqueue_op')
        args.input_queue = input_queue
        nrof_preprocess_threads = 4
        images_and_labels = []
        for _ in range(nrof_preprocess_threads):
            filenames, label = input_queue.dequeue()
            images = []
            for filename in tf.unstack(filenames):
                file_contents = tf.read_file(filename)
                image = tf.image.decode_image(file_contents, channels=3)
                if args.random_rotate:
                    image = tf.py_func(facenet.random_rotate_image, [image], tf.uint8)
                if args.random_crop:
                    image = tf.random_crop(image, [args.image_size, args.image_size, 3])
                else:
                    image = tf.image.resize_image_with_crop_or_pad(image, args.image_size, args.image_size)
                if args.random_flip:
                    image = tf.image.random_flip_left_right(image)
    
                #pylint: disable=no-member
                image.set_shape((args.image_size, args.image_size, 3))
                images.append(tf.image.per_image_standardization(image))
            images_and_labels.append([images, label])
    
        image_batch, label_batch = tf.train.batch_join(
            images_and_labels, batch_size=batch_size_placeholder, 
            shapes=[(args.image_size, args.image_size, 3), ()], enqueue_many=True,
            capacity=4 * nrof_preprocess_threads * args.batch_size,
            allow_smaller_final_batch=True)
        image_batch = tf.identity(image_batch, 'image_batch')
        image_batch = tf.identity(image_batch, 'input')
        label_batch = tf.identity(label_batch, 'label_batch')
        
        print('Total number of classes: %d' % nrof_classes)
        print('Total number of examples: %d' % len(image_list))
        
        print('Building training graph')
        learning_rate = tf.train.exponential_decay(learning_rate_placeholder, global_step,
            args.learning_rate_decay_epochs*args.epoch_size, args.learning_rate_decay_factor, staircase=True)
        tf.summary.scalar('learning_rate', learning_rate)
#        opt = tf.train.GradientDescentOptimizer(learning_rate)
        total_grads = []
        loss_reg = []
        loss_cross = []
        loss_center = []
        images_splits = tf.split(axis=0, num_or_size_splits=args.num_gpus, value=image_batch)
        labels_splits = tf.split(axis=0, num_or_size_splits=args.num_gpus, value=label_batch)
        embedding_list = []
        with tf.variable_scope(tf.get_variable_scope()):
            for i in range(args.num_gpus):
                with tf.device('/gpu:%d' % i):
                    with tf.name_scope('facenet_%d' % (i)) as scope:
                        print('Build training graph on gpu %d' % i)
                        # Build the inference graph
                        prelogits, _ = network.inference(images_splits[i], args.keep_probability, 
                            phase_train=phase_train_placeholder, bottleneck_layer_size=args.embedding_size, 
                            weight_decay=args.weight_decay)
                        embeddings = tf.nn.l2_normalize(prelogits, 1, 1e-10, name='embeddings')
                        if args.l2_softmax_alpha > 0:
                            prelogits = embeddings * args.l2_softmax_alpha
                        logits = slim.fully_connected(prelogits, len(train_set), activation_fn=None, 
                                weights_initializer=tf.truncated_normal_initializer(stddev=0.1), 
                                weights_regularizer=slim.l2_regularizer(args.weight_decay),
                                scope='Logits', reuse=False)

                        embedding_list.append(embeddings)
                        regularization_losses = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES)
                        regularization_losses = sum(regularization_losses)
                        loss_reg.append(regularization_losses)
                        tf.add_to_collection('losses', regularization_losses)
                        # Add center loss
                        if args.center_loss_factor>0.0:
                            prelogits_center_loss, _ = facenet.center_loss(prelogits, labels_splits[i], args.center_loss_alfa, nrof_classes)
                            center_loss = tf.identity(prelogits_center_loss * args.center_loss_factor, 'center_loss')
                            loss_center.append(center_loss)
                            tf.add_to_collection('losses', center_loss)

                        # Reuse variables for the next tower.
                        tf.get_variable_scope().reuse_variables()

                        # Calculate the average cross entropy loss across the batch
                        cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(
                            labels=labels_splits[i], logits=logits, name='cross_entropy_per_example')
                        cross_entropy_mean = tf.reduce_mean(cross_entropy, name='cross_entropy')
                        loss_cross.append(cross_entropy_mean)
                        tf.add_to_collection('losses', cross_entropy_mean)
                        
                        # Calculate the total losses
                        total_loss = cross_entropy_mean + regularization_losses
                        if args.center_loss_factor>0.0:
                            total_loss = total_loss + center_loss
                        total_loss = tf.identity(total_loss, name='total_loss')
                        opt = facenet.optimizer(total_loss, global_step, args.optimizer, 
                            learning_rate, args.moving_average_decay, tf.global_variables(), args.log_histograms)
                        grads = opt.compute_gradients(total_loss)
                        total_grads.append(grads)
        print('Build training total graph')
        regularization_losses = tf.add_n(loss_reg) / args.num_gpus
        tf.summary.scalar('loss/regularization', regularization_losses)
        tf.summary.scalar('loss/center', tf.add_n(loss_center) / args.num_gpus)
        tf.summary.scalar('loss/cross', tf.add_n(loss_cross) / args.num_gpus)
        total_loss = tf.add_n(loss_reg + loss_cross + loss_center) / args.num_gpus
        tf.summary.scalar('loss/total', total_loss)
        embeddings = tf.concat(axis=0, values=embedding_list)
        # We must calculate the mean of each gradient. Note that this is the
        # synchronization point across all towers.
        grads = average_gradients(total_grads)

        # Apply the gradients to adjust the shared variables.
        apply_gradient_op = opt.apply_gradients(grads, global_step=global_step)

        # Track the moving averages of all trainable variables.
        variable_averages = tf.train.ExponentialMovingAverage(
            args.moving_average_decay, global_step)
        variables_averages_op = variable_averages.apply(tf.trainable_variables())

        # Group all updates to into a single train op.
        train_op = tf.group(apply_gradient_op, variables_averages_op)
        
        # Create a saver
        saver = tf.train.Saver(tf.trainable_variables(), max_to_keep=3)

        # Build the summary operation based on the TF collection of Summaries.
        summary_op = tf.summary.merge_all()

        # Start running operations on the Graph.
        gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=args.gpu_memory_fraction)
        sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options, log_device_placement=False))
        sess.run(tf.global_variables_initializer())
        sess.run(tf.local_variables_initializer())
        summary_writer = tf.summary.FileWriter(log_dir, sess.graph)
        coord = tf.train.Coordinator()
        tf.train.start_queue_runners(coord=coord, sess=sess)

        with sess.as_default():

            if pretrained_model:
                print('Restoring pretrained model: %s' % pretrained_model)
                saver.restore(sess, pretrained_model)

            # Training and validation loop
            print('Running training')
            epoch = 0
            while epoch < args.max_nrof_epochs:
                step = sess.run(global_step, feed_dict=None)
                epoch = step // args.epoch_size
                # Train for one epoch
                train(args, sess, epoch, image_list, label_list, index_dequeue_op, enqueue_op, image_paths_placeholder, labels_placeholder,
                    learning_rate_placeholder, phase_train_placeholder, batch_size_placeholder, global_step, 
                    total_loss, train_op, summary_op, summary_writer, regularization_losses, args.learning_rate_schedule_file)

                # Save variables and the metagraph if it doesn't exist already
                save_variables_and_metagraph(sess, saver, summary_writer, model_dir, subdir, step)

                # Evaluate on LFW
                if args.lfw_dir:
                    evaluate(sess, enqueue_op, image_paths_placeholder, labels_placeholder, phase_train_placeholder, batch_size_placeholder, 
                        embeddings, label_batch, lfw_paths, actual_issame, args.lfw_batch_size, args.lfw_nrof_folds, log_dir, step, summary_writer)
    return model_dir
Beispiel #5
0
def main(args):
    # # 导入 model_def 代表的网络结构
    # network = importlib.import_module(args.model_def)

    subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S')
    log_dir = os.path.join(os.path.expanduser(args.logs_base_dir), subdir)
    if not os.path.isdir(
            log_dir):  # Create the log directory if it doesn't exist
        os.makedirs(log_dir)
    model_dir = os.path.join(os.path.expanduser(args.models_base_dir), subdir)
    if not os.path.isdir(
            model_dir):  # Create the model directory if it doesn't exist
        os.makedirs(model_dir)

    # Write arguments to a text file
    # 将 参数 写入到 text 文件中
    facenet.write_arguments_to_file(args, os.path.join(log_dir,
                                                       'arguments.txt'))

    # Store some git revision info in a text file in the log directory
    # 将一些 git 修订信息存储在日志目录的文本文件中
    src_path, _ = os.path.split(os.path.realpath(__file__))
    facenet.store_revision_info(src_path, log_dir, ' '.join(sys.argv))

    # 获取 facenet 的数据集
    np.random.seed(seed=args.seed)
    # train_set = facenet.get_dataset(args.data_dir)

    # 训练数据集
    train_set = facenet.dataset_from_list(args.data_dir, args.list_file)
    nrof_classes = len(train_set)
    print('nrof_classes: ', nrof_classes)
    # 获取 图像 的 路径 和 labels
    image_list, label_list = facenet.get_image_paths_and_labels(train_set)
    print('total images: ', len(image_list))
    image_list = np.array(image_list)
    label_list = np.array(label_list, dtype=np.int32)

    dataset_size = len(image_list)
    # 单个 batch_size  = 每个 batch 中的人数 * 每个人的图像数
    single_batch_size = args.people_per_batch * args.images_per_person
    indices = range(dataset_size)
    np.random.shuffle(indices)

    # 从 dataset 中抽取 样本,将 image_path 和 image_label 返回
    def _sample_people_softmax(x):
        global softmax_ind
        if softmax_ind >= dataset_size:
            np.random.shuffle(indices)
            softmax_ind = 0
        true_num_batch = min(single_batch_size, dataset_size - softmax_ind)

        sample_paths = image_list[indices[softmax_ind:softmax_ind +
                                          true_num_batch]]
        sample_labels = label_list[indices[softmax_ind:softmax_ind +
                                           true_num_batch]]

        softmax_ind += true_num_batch

        return (np.array(sample_paths), np.array(sample_labels,
                                                 dtype=np.int32))

    def _sample_people(x):
        '''We sample people based on tf.data, where we can use transform and prefetch.
        Desc:
            我们基于 tf.data 对人进行抽样,这样我们可以使用 transform 和 prefetch 。
        '''

        image_paths, num_per_class = sample_people(
            train_set, args.people_per_batch * (args.num_gpus - 1),
            args.images_per_person)
        labels = []
        for i in range(len(num_per_class)):
            labels.extend([i] * num_per_class[i])
        return (np.array(image_paths), np.array(labels, dtype=np.int32))

    # 解析函数,将 image 的路径和 label 解析出来,对应着 image 和 label
    def _parse_function(filename, label):
        # 使用 tf.read_file() 进行读取,并使用 tf.image.decode_image() 进行转换为 tensor 的形式
        file_contents = tf.read_file(filename)
        image = tf.image.decode_image(file_contents, channels=3)
        #image = tf.image.decode_jpeg(file_contents, channels=3)
        print(image.shape)

        # 判断是否对图像进行随机裁剪
        if args.random_crop:
            print('use random crop')
            image = tf.random_crop(image,
                                   [args.image_size, args.image_size, 3])
        else:
            print('Not use random crop')
            #image.set_shape((args.image_size, args.image_size, 3))
            image.set_shape((None, None, 3))
            # 将图片进行 resize ,转换为我们传入的参数的大小
            image = tf.image.resize_images(image,
                                           size=(args.image_height,
                                                 args.image_width))
            #print(image.shape)
        # 判断是否进行随机水平翻转
        if args.random_flip:
            image = tf.image.random_flip_left_right(image)

        #pylint: disable=no-member
        #image.set_shape((args.image_size, args.image_size, 3))
        image.set_shape((args.image_height, args.image_width, 3))
        # 强制转换数据类型
        image = tf.cast(image, tf.float32)
        image = tf.subtract(image, 127.5)
        image = tf.div(image, 128.)
        #image = tf.image.per_image_standardization(image)
        return image, label

    # 将 model 目录和 log 目录先打印一下
    print('Model directory: %s' % model_dir)
    print('Log directory: %s' % log_dir)
    # # 如果已经提供了 预训练好的模型
    # if args.pretrained_model:
    #     # os.path.expanduser() 把路径中包含 ~ 或者 ~user 的地方转换为用户目录
    #     print('Pre-trained model: %s' % os.path.expanduser(args.pretrained_model))
    # # 如果提供了 lfw 数据,读取 lfw 目录中的 pairs 和 lfw 数据集中图像的 path
    # if args.lfw_dir:
    #     print('LFW directory: %s' % args.lfw_dir)
    #     # Read the file containing the pairs used for testing
    #     pairs = lfw.read_pairs(os.path.expanduser(args.lfw_pairs))
    #     # Get the paths for the corresponding images
    #     lfw_paths, actual_issame = lfw.get_paths(os.path.expanduser(args.lfw_dir), pairs)

    with tf.Graph().as_default():
        # 设置随机生成数的种子
        tf.set_random_seed(args.seed)
        # 全局的 step
        global_step = tf.Variable(0, trainable=False, name='global_step')

        # Placeholder for the learning rate
        learning_rate_placeholder = tf.placeholder(tf.float32,
                                                   name='learning_rate')

        # batch_size_placeholder = tf.placeholder(tf.int32, name='batch_size')

        phase_train_placeholder = tf.placeholder(tf.bool, name='phase_train')

        # image_paths_placeholder = tf.placeholder(tf.string, shape=(None,3), name='image_paths')
        # labels_placeholder = tf.placeholder(tf.int64, shape=(None,3), name='labels')

        # input_queue = data_flow_ops.FIFOQueue(capacity=100000,
        #                             dtypes=[tf.string, tf.int64],
        #                             shapes=[(3,), (3,)],
        #                             shared_name=None, name=None)
        # enqueue_op = input_queue.enqueue_many([image_paths_placeholder, labels_placeholder])

        # the image is generated by sequence
        # 在 cpu 中将 训练数据集的 batch 进行拆分,分成 num_gpus 份数据
        with tf.device("/cpu:0"):

            softmax_dataset = tf_data.Dataset.range(args.epoch_size *
                                                    args.max_nrof_epochs * 100)
            softmax_dataset = softmax_dataset.map(lambda x: tf.py_func(
                _sample_people_softmax, [x], [tf.string, tf.int32]))
            softmax_dataset = softmax_dataset.flat_map(_from_tensor_slices)
            softmax_dataset = softmax_dataset.map(_parse_function,
                                                  num_parallel_calls=2000)
            softmax_dataset = softmax_dataset.batch(args.num_gpus *
                                                    single_batch_size)
            softmax_iterator = softmax_dataset.make_initializable_iterator()
            softmax_next_element = softmax_iterator.get_next()
            softmax_next_element[0].set_shape(
                (args.num_gpus * single_batch_size, args.image_height,
                 args.image_width, 3))
            softmax_next_element[1].set_shape(args.num_gpus *
                                              single_batch_size)
            batch_image_split = tf.split(softmax_next_element[0],
                                         args.num_gpus)
            batch_label_split = tf.split(softmax_next_element[1],
                                         args.num_gpus)

            # # 在整体数据集上选出 3 元组(triplets)
            # select_start_time = time.time()
            # # Select triplets based on the embeddings
            # print('Selecting suitable triplets for training')
            # # 修改版本的 triplets
            # nrof_examples = args.people_per_batch * args.images_per_person
            # triplets, nrof_random_negs, nrof_triplets = select_triplets(emb_array, num_per_class,
            #     image_paths, args.people_per_batch, args.alpha)
            # selection_time = time.time() - start_time
            # print('(nrof_random_negs, nrof_triplets) = (%d, %d): time=%.3f seconds' %
            #     (nrof_random_negs, nrof_triplets, selection_time))

        # 学习率设置
        learning_rate = tf.train.exponential_decay(
            learning_rate_placeholder,
            global_step,
            args.learning_rate_decay_epochs * args.epoch_size,
            args.learning_rate_decay_factor,
            staircase=True)
        tf.summary.scalar('learning_rate', learning_rate)
        # 优化器设置
        print('Using optimizer: {}'.format(args.optimizer))
        if args.optimizer == 'ADAGRAD':
            opt = tf.train.AdagradOptimizer(learning_rate)
        elif args.optimizer == 'MOM':
            opt = tf.train.MomentumOptimizer(learning_rate, 0.9)
        elif args.optimizer == 'ADAM':
            opt = tf.train.AdamOptimizer(learning_rate,
                                         beta1=0.9,
                                         beta2=0.999,
                                         epsilon=0.1)
        else:
            raise Exception("Not supported optimizer: {}".format(
                args.optimizer))

        tower_losses = []
        tower_cross = []
        tower_dist = []
        tower_reg = []
        for i in range(args.num_gpus):
            with tf.device("/gpu:" + str(i)):
                with tf.name_scope("tower_" + str(i)) as scope:
                    with slim.arg_scope([slim.model_variable, slim.variable],
                                        device="/cpu:0"):
                        with tf.variable_scope(
                                tf.get_variable_scope()) as var_scope:
                            reuse = False if i == 0 else True
                            if args.network == 'inception_resnet_v1':
                                with tf.variable_scope(name_or_scope='',
                                                       reuse=tf.AUTO_REUSE):
                                    prelogits, _ = inception_net.inference(
                                        batch_image_split[i],
                                        args.keep_probability,
                                        phase_train=phase_train_placeholder,
                                        bottleneck_layer_size=args.
                                        embedding_size,
                                        weight_decay=args.weight_decay)
                                print(prelogits)

                            # elif args.network == 'inception_net_v2':
                            #     with tf.variable_scope(name_or_scope='', reuse=tf.AUTO_REUSE):
                            #         prelogits, _ = inception_net_v2.inference(image_batch, args.keep_probability,
                            #         phase_train=phase_train_placeholder, bottleneck_layer_size=args.embedding_size,
                            #         weight_decay=args.weight_decay)
                            #     print(prelogits)
                            # elif args.network == 'squeezenet':
                            #     with tf.variable_scope(name_or_scope='', reuse=tf.AUTO_REUSE):
                            #         prelogits, _ = squeezenet.inference(image_batch, args.keep_probability,
                            #         phase_train=phase_train_placeholder, bottleneck_layer_size=args.embedding_size,
                            #         weight_decay=args.weight_decay)
                            #     print(prelogits)
                            else:
                                raise Exception(
                                    "Not supported network: {}".format(
                                        args.network))
                            if args.fc_bn:

                                prelogits = slim.batch_norm(
                                    prelogits,
                                    is_training=True,
                                    decay=0.997,
                                    epsilon=1e-5,
                                    scale=True,
                                    updates_collections=tf.GraphKeys.
                                    UPDATE_OPS,
                                    reuse=reuse,
                                    scope='softmax_bn')
                            if args.loss_type == 'triplet':
                                embeddings = tf.nn.l2_normalize(
                                    prelogits, 1, 1e-10, name='embeddings')
                                # Split embeddings into anchor, positive and negative and calculate triplet loss
                                anchor, positive, negative = tf.unstack(
                                    tf.reshape(embeddings,
                                               [-1, 3, args.embedding_size]),
                                    3, 1)
                                triplet_loss = facenet.triplet_loss(
                                    anchor, positive, negative, args.alpha)
                                regularization_losses = tf.get_collection(
                                    tf.GraphKeys.REGULARIZATION_LOSSES)
                                if args.network == 'sphere_network':
                                    print(
                                        'reg loss using weight_decay * tf.add_n'
                                    )
                                    reg_loss = args.weight_decay * tf.add_n(
                                        regularization_losses)
                                else:
                                    print('reg loss using tf.add_n')
                                    # reg_loss = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES)
                                    reg_loss = tf.add_n(regularization_losses)
                                loss = triplet_loss + reg_loss

                                tower_losses.append(loss)
                                tower_reg.append(reg_loss)
                            # elif args.loss_type =='cosface':

                            #loss = tf.add_n([cross_entropy_mean] + regularization_losses, name='total_loss')
                            tf.get_variable_scope().reuse_variables()
        # 计算 total loss
        total_loss = tf.reduce_mean(tower_losses)
        total_reg = tf.reduce_mean(tower_reg)
        losses = {}
        losses['total_loss'] = total_loss
        losses['total_reg'] = total_reg

        # # Build a Graph that trains the model with one batch of examples and updates the model parameters
        # train_op = facenet.train(total_loss, global_step, args.optimizer,
        #     learning_rate, args.moving_average_decay, tf.global_variables())

        grads = opt.compute_gradients(total_loss,
                                      tf.trainable_variables(),
                                      colocate_gradients_with_ops=True)
        apply_gradient_op = opt.apply_gradients(grads, global_step=global_step)
        update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS)
        with tf.control_dependencies(update_ops):
            train_op = tf.group(apply_gradient_op)

        # Create a saver
        # saver = tf.train.Saver(tf.trainable_variables(), max_to_keep=3)
        save_vars = [
            var for var in tf.global_variables()
            if 'Adagrad' not in var.name and 'global_step' not in var.name
        ]
        saver = tf.train.Saver(save_vars, max_to_keep=3)

        # Build the summary operation based on the TF collection of Summaries.
        summary_op = tf.summary.merge_all()

        # Start running operations on the Graph.
        gpu_options = tf.GPUOptions(
            per_process_gpu_memory_fraction=args.gpu_memory_fraction)
        sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options,
                                                allow_soft_placement=True))

        # Initialize variables
        sess.run(tf.global_variables_initializer(),
                 feed_dict={phase_train_placeholder: True})
        sess.run(tf.local_variables_initializer(),
                 feed_dict={phase_train_placeholder: True})

        sess.run(softmax_iterator.initializer)

        summary_writer = tf.summary.FileWriter(log_dir, sess.graph)
        coord = tf.train.Coordinator()
        tf.train.start_queue_runners(coord=coord, sess=sess)

        with sess.as_default():
            # 如果有预训练好的 model,那就进行 restore 操作,将模型加载进行以后的 测试阶段
            if args.pretrained_model:
                print('Restoring pretrained model: %s' % args.pretrained_model)
                saver.restore(sess, os.path.expanduser(args.pretrained_model))

            # Training and validation loop
            epoch = 0
            while epoch < args.max_nrof_epochs:
                step = sess.run(global_step, feed_dict=None)
                epoch = step // args.epoch_size
                # Train for one epoch
                train(args, sess, epoch, learning_rate_placeholder,
                      phase_train_placeholder, global_step, losses, train_op,
                      summary_op, summary_writer,
                      args.learning_rate_schedule_file)

                # Save variables and the metagraph if it doesn't exist already
                save_variables_and_metagraph(sess, saver, summary_writer,
                                             model_dir, subdir, step)

                # # Evaluate on LFW
                # if args.lfw_dir:
                #     evaluate(sess, lfw_paths, embeddings, labels_batch, image_paths_placeholder, labels_placeholder,
                #             batch_size_placeholder, learning_rate_placeholder, phase_train_placeholder, enqueue_op, actual_issame, args.batch_size,
                #             args.lfw_nrof_folds, log_dir, step, summary_writer, args.embedding_size)
    # 将训练好的模型 返回
    return model_dir
Beispiel #6
0
def main(args):
    print('args used to train the model:')
    print(args)

    # =========================================================================== #
    # 数据预处理,路径问题等
    # =========================================================================== #
    network = importlib.import_module(args.model_def)
    image_size = (args.image_size, args.image_size)

    subdir = datetime.strftime(datetime.now(),
                               '%Y%m%d-%H%M%S')  # '20180614-100359'
    subdir += args.dir_postfix
    log_dir = os.path.join(os.path.expanduser(args.logs_base_dir),
                           subdir)  # 本地保存log的路径
    log_dir += args.dir_postfix
    val_log_dir = log_dir  # 本地保存validation result的路径
    if not os.path.isdir(
            log_dir):  # Create the log directory if it doesn't exist
        os.makedirs(log_dir)
    model_dir = os.path.join(os.path.expanduser(args.models_base_dir),
                             subdir)  # 本地保存model的路径,最后一层目录用上面生成的日期命名
    if not os.path.isdir(
            model_dir):  # Create the model directory if it doesn't exist
        os.makedirs(model_dir)

    stat_file_name = os.path.join(log_dir, 'stat.h5')

    # Write arguments to a text file, 把训练时用的所有参数保存到txt中
    facenet.write_arguments_to_file(args, os.path.join(log_dir,
                                                       'arguments.txt'))

    # Store some git revision info in a text file in the log directory
    src_path, _ = os.path.split(os.path.realpath(__file__))
    facenet.store_revision_info(src_path, log_dir, ' '.join(sys.argv))

    np.random.seed(seed=args.seed)
    random.seed(args.seed)
    # dataset中是多个ImageClass对象,每个对象中有类名(name)和该类所有图片的路径(image_paths)
    dataset = facenet.get_dataset(args.data_dir)
    # filter_name default='', 这个训练的时候没用到, 先不管了
    if args.filter_filename:
        dataset = filter_dataset(dataset,
                                 os.path.expanduser(args.filter_filename),
                                 args.filter_percentile,
                                 args.filter_min_nrof_images_per_class)

    # validation_set_split_ratio default=0.0, 如果需要验证操作的话设置这个
    # 划分验证集有两种方式:按类划分和按图片划分(默认)
    if args.validation_set_split_ratio > 0.0:
        train_set, val_set = facenet.split_dataset(
            dataset, args.validation_set_split_ratio,
            args.min_nrof_val_images_per_class, 'SPLIT_IMAGES')
    else:
        train_set, val_set = dataset, []

    nrof_classes = len(train_set)

    print('Model directory: %s' % model_dir)
    print('Log directory: %s' % log_dir)
    pretrained_model = None
    if args.pretrained_model:
        pretrained_model = os.path.expanduser(args.pretrained_model)
        print('Pre-trained model: %s' % pretrained_model)

    if args.lfw_dir:
        print('LFW directory: %s' % args.lfw_dir)
        # Read the file containing the pairs used for testing
        # pairs[0] = ['Abel_Pacheco', '1', '4']
        # args.lfw_pairs: data/pairs.txt, 这个文件中每一行或有三个字段或有四个字段
        # 如果有三个字段表示从一个人的所有图片中选择两个(正样本, actual_issame=True)
        # 如果有四个字段表示从两个人的所有图片中各选一个(负样本, actual_issame=False)
        pairs = lfw.read_pairs(os.path.expanduser(args.lfw_pairs))
        # Get the paths for the corresponding images
        # lfw_paths里的每个值都是一个元组(path0, path1), actual_issame里对应的是这个元组是正样本还是副样本
        lfw_paths, actual_issame = lfw.get_paths(
            os.path.expanduser(args.lfw_dir), pairs)

    # =========================================================================== #
    # 下面开始处理TensorFlow相关的东西
    # =========================================================================== #
    with tf.Graph().as_default():

        # =========================================================================== #
        # Input pipeline
        # =========================================================================== #
        tf.set_random_seed(args.seed)
        global_step = tf.Variable(0, trainable=False)

        # Get a list of image paths and their labels
        # 这两个list是训练集中的所有数据
        image_list, label_list = facenet.get_image_paths_and_labels(train_set)
        assert len(image_list) > 0, 'The training set should not be empty'

        val_image_list, val_label_list = facenet.get_image_paths_and_labels(
            val_set)

        # Create a queue that produces indices into the image_list and label_list
        labels = ops.convert_to_tensor(label_list, dtype=tf.int32)
        range_size = array_ops.shape(labels)[0]
        # num_epochs=None时,循环生成0到range_size-1的数
        index_queue = tf.train.range_input_producer(range_size,
                                                    num_epochs=None,
                                                    shuffle=True,
                                                    seed=None,
                                                    capacity=32)
        # 这个op是用来生成索引值的,每次从队列里取出一个epoch中所有图片数量的下标
        index_dequeue_op = index_queue.dequeue_many(
            args.batch_size * args.epoch_size, 'index_dequeue')

        learning_rate_placeholder = tf.placeholder(tf.float32,
                                                   name='learning_rate')
        batch_size_placeholder = tf.placeholder(tf.int32, name='batch_size')
        phase_train_placeholder = tf.placeholder(tf.bool, name='phase_train')
        image_paths_placeholder = tf.placeholder(tf.string,
                                                 shape=(None, 1),
                                                 name='image_paths')
        labels_placeholder = tf.placeholder(tf.int32,
                                            shape=(None, 1),
                                            name='labels')
        control_placeholder = tf.placeholder(tf.int32,
                                             shape=(None, 1),
                                             name='control')

        nrof_preprocess_threads = 4
        input_queue = data_flow_ops.FIFOQueue(
            capacity=2000000,
            dtypes=[tf.string, tf.int32, tf.int32],
            shapes=[(1, ), (1, ), (1, )],
            shared_name=None,
            name=None)
        enqueue_op = input_queue.enqueue_many(
            [image_paths_placeholder, labels_placeholder, control_placeholder],
            name='enqueue_op')
        # create input pipeline, 将上面image path中的文件取出来
        image_batch, label_batch = facenet.create_input_pipeline(
            input_queue, image_size, nrof_preprocess_threads,
            batch_size_placeholder)

        image_batch = tf.identity(image_batch, 'image_batch')
        image_batch = tf.identity(image_batch, 'input')
        label_batch = tf.identity(label_batch, 'label_batch')

        print('Number of classes in training set: %d' % nrof_classes)
        print('Number of examples in training set: %d' % len(image_list))

        print('Number of classes in validation set: %d' % len(val_set))
        print('Number of examples in validation set: %d' % len(val_image_list))

        print('Building training graph')

        ### Build the inference graph
        # prelogits是128维的向量
        prelogits, _ = network.inference(
            image_batch,
            args.keep_probability,
            phase_train=phase_train_placeholder,
            bottleneck_layer_size=args.embedding_size,
            weight_decay=args.weight_decay)

        # TODO: Inject some code here for fine tuning

        # logits的shape: [None, len(train_set)]
        logits = slim.fully_connected(
            prelogits,
            len(train_set),
            activation_fn=None,
            weights_initializer=slim.initializers.xavier_initializer(),
            weights_regularizer=slim.l2_regularizer(args.weight_decay),
            scope='Logits',
            reuse=False)
        # 这步操作之后在测试时就可以拿到这个值了
        logits = tf.identity(logits, name='logits')

        # axis=1, 是把每行进行normalize, 每行是一个样本, 128维(或512维)的向量
        embeddings = tf.nn.l2_normalize(prelogits, 1, 1e-10, name='embeddings')

        # Norm for the prelogits
        eps = 1e-4
        prelogits_norm = tf.reduce_mean(
            tf.norm(tf.abs(prelogits) + eps, ord=args.prelogits_norm_p,
                    axis=1))
        # 把prelogits进行norm操作得到的是一个数,这个数乘个weight作为loss的一部分,--prelogits_norm_loss_factor 5e-4
        tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES,
                             prelogits_norm * args.prelogits_norm_loss_factor)

        # Add center loss, 这个center loss作为正则化loss的一部分, 出自一篇人脸识别的论文, 先不管
        # 这个loss默认权重是0, 文档中给出的训练脚本并没有用这个loss
        prelogits_center_loss, _ = facenet.center_loss(prelogits, label_batch,
                                                       args.center_loss_alfa,
                                                       nrof_classes)
        tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES,
                             prelogits_center_loss * args.center_loss_factor)

        learning_rate = tf.train.exponential_decay(
            learning_rate_placeholder,
            global_step,
            args.learning_rate_decay_epochs * args.epoch_size,
            args.learning_rate_decay_factor,
            staircase=True)
        tf.summary.scalar('learning_rate', learning_rate)

        # Calculate the average cross entropy loss across the batch
        cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(
            labels=label_batch,
            logits=logits,
            name='cross_entropy_per_example')
        cross_entropy_mean = tf.reduce_mean(cross_entropy,
                                            name='cross_entropy')
        tf.add_to_collection('losses', cross_entropy_mean)

        correct_prediction = tf.cast(
            tf.equal(tf.argmax(logits, 1), tf.cast(label_batch, tf.int64)),
            tf.float32)
        accuracy = tf.reduce_mean(correct_prediction)

        # Calculate the total losses
        regularization_losses = tf.get_collection(
            tf.GraphKeys.REGULARIZATION_LOSSES)
        # 这个total_loss是ce和regular loss的和,应该是已经把所有loss的值都加起来了
        total_loss = tf.add_n([cross_entropy_mean] + regularization_losses,
                              name='total_loss')

        # Build a Graph that trains the model with one batch of examples and updates the model parameters
        train_op = facenet.train(total_loss, global_step, args.optimizer,
                                 learning_rate, args.moving_average_decay,
                                 tf.global_variables(), args.log_histograms)

        # Create a saver
        saver = tf.train.Saver(tf.trainable_variables(), max_to_keep=20)

        # Build the summary operation based on the TF collection of Summaries.
        summary_op = tf.summary.merge_all()

        ### Start running operations on the Graph.
        gpu_options = tf.GPUOptions(
            per_process_gpu_memory_fraction=args.gpu_memory_fraction)
        sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options,
                                                log_device_placement=False))
        sess.run(tf.global_variables_initializer())
        sess.run(tf.local_variables_initializer())
        summary_writer = tf.summary.FileWriter(log_dir, sess.graph)
        coord = tf.train.Coordinator()
        tf.train.start_queue_runners(coord=coord, sess=sess)

        # =========================================================================== #
        # Start training
        # =========================================================================== #
        with sess.as_default():

            if pretrained_model:
                print('Restoring pretrained model: %s' % pretrained_model)
                # saver.restore(sess, pretrained_model)
                if args.checkpoint_exclude_scopes:
                    exclusions = [args.checkpoint_exclude_scopes.split(',')]
                else:
                    exclusions = []
                # load from pre-trained model
                tf.contrib.framework.assign_from_checkpoint_fn(
                    pretrained_model, [
                        var for var in tf.trainable_variables()
                        if all(not var.op.name.startswith(exclusion)
                               for exclusion in exclusions)
                    ],
                    ignore_missing_vars=args.ignore_missing_vars)(sess)

            # Training and validation loop
            print('Running training')

            # max_nrof_epochs: number of epochs to run, default=500
            # epoch_size: number of batches per epoch,default=1000
            nrof_steps = args.max_nrof_epochs * args.epoch_size  # total batch number

            # 在验证集上验证的次数
            nrof_val_samples = int(
                math.ceil(args.max_nrof_epochs / args.validate_every_n_epochs)
            )  # Validate every validate_every_n_epochs as well as in the last epoch
            stat = {
                # 每一个batch记录一次
                'loss':
                np.zeros((nrof_steps, ), np.float32),
                'center_loss':
                np.zeros((nrof_steps, ), np.float32),
                'reg_loss':
                np.zeros((nrof_steps, ), np.float32),
                'xent_loss':
                np.zeros((nrof_steps, ), np.float32),
                'prelogits_norm':
                np.zeros((nrof_steps, ), np.float32),
                'accuracy':
                np.zeros((nrof_steps, ), np.float32),
                # 每验证一次记录一次
                'val_loss':
                np.zeros((nrof_val_samples, ), np.float32),
                'val_xent_loss':
                np.zeros((nrof_val_samples, ), np.float32),
                'val_accuracy':
                np.zeros((nrof_val_samples, ), np.float32),
                # 每个epoch记录一次
                'lfw_accuracy':
                np.zeros((args.max_nrof_epochs, ), np.float32),
                'lfw_valrate':
                np.zeros((args.max_nrof_epochs, ), np.float32),
                'learning_rate':
                np.zeros((args.max_nrof_epochs, ), np.float32),
                'time_train':
                np.zeros((args.max_nrof_epochs, ), np.float32),
                'time_validate':
                np.zeros((args.max_nrof_epochs, ), np.float32),
                'time_evaluate':
                np.zeros((args.max_nrof_epochs, ), np.float32),
                'prelogits_hist':
                np.zeros((args.max_nrof_epochs, 1000), np.float32),
            }
            for epoch in range(1, args.max_nrof_epochs + 1):
                step = sess.run(global_step, feed_dict=None)  # step = 0
                ### Train for one epoch
                t = time.time()

                # =========================================================================== #
                # 一次训练的过程,学习率是在这里设置的,如果参数中的学习率小于0,就用调度文件中的学习率
                # =========================================================================== #
                cont = train(
                    args, sess, epoch, image_list, label_list,
                    index_dequeue_op, enqueue_op, image_paths_placeholder,
                    labels_placeholder, learning_rate_placeholder,
                    phase_train_placeholder, batch_size_placeholder,
                    control_placeholder, global_step, total_loss, train_op,
                    summary_op, summary_writer, regularization_losses,
                    args.learning_rate_schedule_file, stat, cross_entropy_mean,
                    accuracy, learning_rate, prelogits, prelogits_center_loss,
                    args.random_rotate, args.random_crop, args.random_flip,
                    prelogits_norm, args.prelogits_hist_max,
                    args.use_fixed_image_standardization)
                stat['time_train'][epoch - 1] = time.time() - t

                if not cont:
                    # 每次结束一轮训练,train函数返回True
                    break

                ### validate on val_set
                t = time.time()
                if len(val_image_list) > 0 and \
                        ((
                                 epoch - 1) % args.validate_every_n_epochs == args.validate_every_n_epochs - 1 or epoch == args.max_nrof_epochs):
                    # =========================================================================== #
                    # 如果验证集不为空 并且 到了设置的每n个epoch验证一次或者到了最后一个epoch, 则进行一次验证
                    # =========================================================================== #
                    validate(args, sess, epoch, val_image_list, val_label_list,
                             enqueue_op, image_paths_placeholder,
                             labels_placeholder, control_placeholder,
                             phase_train_placeholder, batch_size_placeholder,
                             stat, total_loss, regularization_losses,
                             cross_entropy_mean, accuracy,
                             args.validate_every_n_epochs,
                             args.use_fixed_image_standardization, val_log_dir)
                stat['time_validate'][epoch - 1] = time.time() - t

                # Save variables and the metagraph if it doesn't exist
                save_variables_and_metagraph(sess, saver, summary_writer,
                                             model_dir, subdir, epoch)

                ### Evaluate on LFW
                t = time.time()
                if args.lfw_dir:
                    evaluate(sess, enqueue_op, image_paths_placeholder,
                             labels_placeholder, phase_train_placeholder,
                             batch_size_placeholder, control_placeholder,
                             args.lfw_nrof_folds, log_dir, step,
                             summary_writer, stat, epoch, embeddings,
                             label_batch, lfw_paths, actual_issame,
                             args.lfw_batch_size, args.lfw_distance_metric,
                             args.lfw_subtract_mean,
                             args.lfw_use_flipped_images,
                             args.use_fixed_image_standardization)
                stat['time_evaluate'][epoch - 1] = time.time() - t

                print('Saving statistics')
                with h5py.File(stat_file_name, 'w') as f:
                    for key, value in stat.items():
                        f.create_dataset(key, data=value)

    return model_dir
def main(args):

    network = importlib.import_module(args.model_def)

    subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S')
    log_dir = os.path.join(os.path.expanduser(args.logs_base_dir), subdir)
    if not os.path.isdir(
            log_dir):  # Create the log directory if it doesn't exist
        os.makedirs(log_dir)
    model_dir = os.path.join(os.path.expanduser(args.models_base_dir), subdir)
    if not os.path.isdir(
            model_dir):  # Create the model directory if it doesn't exist
        os.makedirs(model_dir)

    # Write arguments to a text file
    facenet.write_arguments_to_file(args, os.path.join(log_dir,
                                                       'arguments.txt'))

    # Store some git revision info in a text file in the log directory
    src_path, _ = os.path.split(os.path.realpath(__file__))
    facenet.store_revision_info(src_path, log_dir, ' '.join(sys.argv))

    np.random.seed(seed=args.seed)
    random.seed(args.seed)
    train_set = facenet.get_dataset(args.data_dir)
    if args.filter_filename:
        train_set = filter_dataset(train_set,
                                   os.path.expanduser(args.filter_filename),
                                   args.filter_percentile,
                                   args.filter_min_nrof_images_per_class)
    nrof_classes = len(train_set)

    #-------------------------------------------------------------------------------------------------------------------
    test_set = facenet.get_dataset(args.lfw_dir)
    if args.filter_filename:
        test_set = filter_dataset(test_set,
                                  os.path.expanduser(args.filter_filename),
                                  args.filter_percentile,
                                  args.filter_min_nrof_images_per_class)
    nrof_classes = len(test_set)
    #----------------------------------------------------------------------------------------------------------------
    image_test_list, label_test_list = facenet.get_image_paths_and_labels(
        test_set)
    assert len(image_test_list) > 0, 'The dataset should not be empty'
    #-----------------------------------------------------------------------------------------------------------------
    #-------------------------------------------------------------------------------------------------------------------

    print('Model directory: %s' % model_dir)
    print('Log directory: %s' % log_dir)
    pretrained_model = None
    if args.pretrained_model:
        pretrained_model = os.path.expanduser(args.pretrained_model)
        print('Pre-trained model: %s' % pretrained_model)

    if args.lfw_dir:
        print('LFW directory: %s' % args.lfw_dir)
        # Read the file containing the pairs used for testing
        pairs = lfw.read_pairs(os.path.expanduser(args.lfw_pairs))
        # Get the paths for the corresponding images
        lfw_paths, actual_issame = lfw.get_paths(
            os.path.expanduser(args.lfw_dir), pairs, args.lfw_file_ext)

    with tf.Graph().as_default():
        tf.set_random_seed(args.seed)
        global_step = tf.Variable(0, trainable=False)

        # Get a list of image paths and their labels
        image_list, label_list = facenet.get_image_paths_and_labels(train_set)
        assert len(image_list) > 0, 'The dataset should not be empty'

        # Create a queue that produces indices into the image_list and label_list
        labels = ops.convert_to_tensor(label_list, dtype=tf.int32)
        range_size = array_ops.shape(labels)[0]
        index_queue = tf.train.range_input_producer(range_size,
                                                    num_epochs=None,
                                                    shuffle=True,
                                                    seed=None,
                                                    capacity=32)

        index_dequeue_op = index_queue.dequeue_many(
            args.batch_size * args.epoch_size, 'index_dequeue')

        learning_rate_placeholder = tf.placeholder(tf.float32,
                                                   name='learning_rate')

        batch_size_placeholder = tf.placeholder(tf.int32, name='batch_size')

        phase_train_placeholder = tf.placeholder(tf.bool, name='phase_train')

        image_paths_placeholder = tf.placeholder(tf.string,
                                                 shape=(None, 1),
                                                 name='image_paths')

        labels_placeholder = tf.placeholder(tf.int64,
                                            shape=(None, 1),
                                            name='labels')

        input_queue = data_flow_ops.FIFOQueue(capacity=100000,
                                              dtypes=[tf.string, tf.int64],
                                              shapes=[(1, ), (1, )],
                                              shared_name=None,
                                              name=None)
        enqueue_op = input_queue.enqueue_many(
            [image_paths_placeholder, labels_placeholder], name='enqueue_op')
        #------------------------------------------------------------------------------------------------------------------------
        test_labels = ops.convert_to_tensor(label_test_list, dtype=tf.int32)
        test_range_size = array_ops.shape(test_labels)[0]
        test_index_queue = tf.train.range_input_producer(test_range_size,
                                                         num_epochs=None,
                                                         shuffle=True,
                                                         seed=None,
                                                         capacity=32)

        test_index_dequeue_op = test_index_queue.dequeue_many(
            args.batch_size * args.epoch_size, 'index_dequeue')

        learning_rate_placeholder = tf.placeholder(tf.float32,
                                                   name='learning_rate')

        batch_size_placeholder = tf.placeholder(tf.int32, name='batch_size')

        phase_train_placeholder = tf.placeholder(tf.bool, name='phase_train')

        test_image_paths_placeholder = tf.placeholder(tf.string,
                                                      shape=(None, 1),
                                                      name='test_image_paths')

        test_labels_placeholder = tf.placeholder(tf.int64,
                                                 shape=(None, 1),
                                                 name='test_labels')

        input_test_queue = data_flow_ops.FIFOQueue(
            capacity=8000000,
            dtypes=[tf.string, tf.int64],
            shapes=[(1, ), (1, )],
            shared_name=None,
            name=None)
        vali_enqueue_op = input_test_queue.enqueue_many(
            [test_image_paths_placeholder, test_labels_placeholder],
            name='vali_enqueue_op')
        #-----------------------------------------------------------------------------------------------------------------------
        nrof_preprocess_threads = 4
        images_and_labels = []
        for _ in range(nrof_preprocess_threads):
            filenames, label = input_queue.dequeue()
            images = []
            for filename in tf.unstack(filenames):
                file_contents = tf.read_file(filename)
                image = tf.image.decode_image(file_contents, channels=3)
                if args.random_rotate:
                    image = tf.py_func(facenet.random_rotate_image, [image],
                                       tf.uint8)
                if args.random_crop:
                    image = tf.random_crop(
                        image, [args.image_size, args.image_size, 3])
                else:
                    image = tf.image.resize_image_with_crop_or_pad(
                        image, args.image_size, args.image_size)
                if args.random_flip:
                    image = tf.image.random_flip_left_right(image)

                #pylint: disable=no-member
                image.set_shape((args.image_size, args.image_size, 3))
                images.append(tf.image.per_image_standardization(image))
            images_and_labels.append([images, label])

#--------------------------------------------------------------------------------------------------------------------------------
        test_images_and_labels = []
        test_filenames, test_label = input_test_queue.dequeue()
        test_images = []
        for test_filename in tf.unstack(test_filenames):
            test_file_contents = tf.read_file(test_filename)
            test_image = tf.image.decode_image(test_file_contents, channels=3)
            test_image.set_shape((args.image_size, args.image_size, 3))
            test_images.append(tf.image.per_image_standardization(test_image))
        test_images_and_labels.append([test_images, test_label])

        test_image_batch, test_label_batch = tf.train.batch_join(
            test_images_and_labels,
            batch_size=batch_size_placeholder,
            shapes=[(args.image_size, args.image_size, 3), ()],
            enqueue_many=True,
            capacity=4 * args.batch_size,
            allow_smaller_final_batch=True)
        test_image_batch = tf.identity(test_image_batch, 'test_image_batch')
        test_image_batch = tf.identity(test_image_batch, 'test_input')
        test_label_batch = tf.identity(test_label_batch, 'test_label_batch')
        #---------------------------------------------------------------------------------------------------------------------------------

        image_batch, label_batch = tf.train.batch_join(
            images_and_labels,
            batch_size=batch_size_placeholder,
            shapes=[(args.image_size, args.image_size, 3), ()],
            enqueue_many=True,
            capacity=4 * nrof_preprocess_threads * args.batch_size,
            allow_smaller_final_batch=True)
        print(image_batch)
        image_batch = tf.identity(image_batch, 'image_batch')
        image_batch = tf.identity(image_batch, 'input')
        label_batch = tf.identity(label_batch, 'label_batch')

        print('Total number of classes: %d' % nrof_classes)
        print('Total number of examples: %d' % len(image_list))

        print('Building training graph')

        # Build the inference graph
        prelogits, _ = network.inference(
            image_batch,
            args.keep_probability,
            phase_train=phase_train_placeholder,
            bottleneck_layer_size=args.embedding_size,
            weight_decay=args.weight_decay)
        logits = slim.fully_connected(
            prelogits,
            len(train_set),
            activation_fn=None,
            weights_initializer=tf.truncated_normal_initializer(stddev=0.1),
            weights_regularizer=slim.l2_regularizer(args.weight_decay),
            scope='Logits',
            reuse=False)
        logits = tf.identity(logits, 'final_Logits')
        #trainable=False,

        #----------------------------------------------------------------------------------------------------------------------------------

        test_prelogits, _ = network.inference(
            test_image_batch,
            1,
            phase_train=phase_train_placeholder,
            bottleneck_layer_size=args.embedding_size,
            weight_decay=args.weight_decay,
            reuse=True)
        test_logits = slim.fully_connected(
            test_prelogits,
            len(test_set),
            activation_fn=None,
            weights_initializer=tf.truncated_normal_initializer(stddev=0.1),
            weights_regularizer=slim.l2_regularizer(args.weight_decay),
            scope='Logits',
            reuse=True)
        with tf.name_scope('accuracy'):
            onehot_labels = tf.one_hot(test_label_batch, 7)
            correct_prediction = tf.equal(tf.argmax(test_logits, 1),
                                          tf.argmax(onehot_labels, 1))
            correct_prediction = tf.cast(correct_prediction, tf.float32)
        accuracy_ = tf.cast(tf.reduce_mean(correct_prediction), tf.float32)
        #print(accuracy_)

        with tf.name_scope('confusion'):
            confusion = tf.contrib.metrics.confusion_matrix(test_label_batch,
                                                            tf.argmax(
                                                                test_logits,
                                                                1),
                                                            num_classes=7)
            #print(confusion)


#-----------------------------------------------------------------------------------------------------------------------------------

        embeddings = tf.nn.l2_normalize(prelogits, 1, 1e-10, name='embeddings')

        # Add center loss
        if args.center_loss_factor > 0.0:
            prelogits_center_loss, _ = facenet.center_loss(
                prelogits, label_batch, args.center_loss_alfa, nrof_classes)
            tf.add_to_collection(
                tf.GraphKeys.REGULARIZATION_LOSSES,
                prelogits_center_loss * args.center_loss_factor)

        learning_rate = tf.train.exponential_decay(
            learning_rate_placeholder,
            global_step,
            args.learning_rate_decay_epochs * args.epoch_size,
            args.learning_rate_decay_factor,
            staircase=True)
        tf.summary.scalar('learning_rate', learning_rate)

        # Calculate the average cross entropy loss across the batch
        cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(
            labels=label_batch,
            logits=logits,
            name='cross_entropy_per_example')
        cross_entropy_mean = tf.reduce_mean(cross_entropy,
                                            name='cross_entropy')
        # cross_entropy_mean = focal_loss(onehot_labels=label_batch, cls_preds=logits,
        #                     alpha=0.25, gamma=2, name=None, scope=None)

        tf.add_to_collection('losses', cross_entropy_mean)

        # Calculate the total losses
        regularization_losses = tf.get_collection(
            tf.GraphKeys.REGULARIZATION_LOSSES)
        total_loss = tf.add_n([cross_entropy_mean] + regularization_losses,
                              name='total_loss')

        # Build a Graph that trains the model with one batch of examples and updates the model parameters
        train_op = facenet.train(total_loss, global_step, args.optimizer,
                                 learning_rate, args.moving_average_decay,
                                 tf.global_variables(), args.log_histograms)

        # Create a saver
        saver1 = tf.train.Saver(tf.trainable_variables()[0:-1],
                                max_to_keep=200)
        saver = tf.train.Saver(max_to_keep=200)
        # Build the summary operation based on the TF collection of Summaries.
        summary_op = tf.summary.merge_all()

        # Start running operations on the Graph.
        gpu_options = tf.GPUOptions(
            per_process_gpu_memory_fraction=args.gpu_memory_fraction)
        sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options,
                                                log_device_placement=False))
        sess.run(tf.global_variables_initializer())
        sess.run(tf.local_variables_initializer())
        summary_writer = tf.summary.FileWriter(log_dir, sess.graph)
        coord = tf.train.Coordinator()
        tf.train.start_queue_runners(coord=coord, sess=sess)

        with sess.as_default():

            if pretrained_model:
                print('Restoring pretrained model: %s' % pretrained_model)
                # init_0 = tf.global_variables_initializer()
                # sess.run(init_0)
                # var_names = []
                # name2var = dict(zip(map(lambda x:x.name.split(':')[0], tf.global_variables()),tf.global_variables()))
                # with tf.variable_scope('',reuse=True):
                #     for var_name, saved_var_name in var_names[:-1]:
                #         curr_var = name2var[saved_var_name]
                #         var_shape = curr_var.get_shape().as_list()
                #         if var_shape == saved_shapes[saved_var_name]:
                #             restore_vars.append(curr_var)
                # saver = tf.train.Saver(restore_vars,max_to_keep=3)
                saver1.restore(sess, pretrained_model)

            # Training and validation loop
            print('Running training')
            epoch = 0
            while epoch < args.max_nrof_epochs:
                step = sess.run(global_step, feed_dict=None)
                epoch = step // args.epoch_size
                #     print(step)
                # Train for one epoch
                train(args, sess, epoch, image_list, label_list,
                      index_dequeue_op, enqueue_op, image_paths_placeholder,
                      labels_placeholder, learning_rate_placeholder,
                      phase_train_placeholder, batch_size_placeholder,
                      global_step, total_loss, train_op, summary_op,
                      summary_writer, regularization_losses,
                      args.learning_rate_schedule_file)
                sum_ = 0
                confusion_m = tf.zeros((7, 7))
                for i in range(7):
                    acc, m = test(
                        confusion, accuracy_, args, sess, epoch,
                        image_test_list, label_test_list, index_dequeue_op,
                        vali_enqueue_op, test_image_paths_placeholder,
                        test_labels_placeholder, learning_rate_placeholder,
                        phase_train_placeholder, batch_size_placeholder,
                        global_step, total_loss, train_op, summary_op,
                        summary_writer, regularization_losses,
                        args.learning_rate_schedule_file)
                    sum_ = sum_ + acc
                    confusion_m = confusion_m + m
                avg = sum_ / 7
                confusion_m = confusion_m / tf.reduce_sum(confusion_m, 1)
                print(avg)
                np.set_printoptions(precision=4)
                print(confusion_m.eval())

                summary = tf.Summary()
                #pylint: disable=maybe-no-member
                summary.value.add(tag='lfw/accuracy', simple_value=avg)
                #summary.value.add(tag='lfw/c_matrix', simple_value=m)
                summary_writer.add_summary(summary, step)
                with open(os.path.join(log_dir, 'lfw_result.txt'), 'at') as f:
                    f.write('\n%d\t%.5f\t\n' % (step, avg))
                    f.write(np.array_str(confusion_m.eval()))
                    # Save variables and the metagraph if it doesn't exist already
                    save_variables_and_metagraph(sess, saver, summary_writer,
                                                 model_dir, subdir, step)

                    # # Evaluate on LFW
                    # if args.lfw_dir:
                    #     evaluate(sess, enqueue_op, image_paths_placeholder, labels_placeholder, phase_train_placeholder, batch_size_placeholder,
                    #         embeddings, label_batch, lfw_paths, actual_issame, args.lfw_batch_size, args.lfw_nrof_folds, log_dir, step, summary_writer)
    return model_dir
Beispiel #8
0
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
Beispiel #9
0
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
Beispiel #10
0
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
Beispiel #11
0
def main(args):
  
    img_mean = np.array([134.10714722, 102.52040863, 87.15436554])
    img_stddev = np.sqrt(np.array([3941.30175781, 2856.94287109, 2519.35791016]))
  
    vae_def = importlib.import_module(args.vae_def)
    vae = vae_def.Vae(args.latent_var_size)
    gen_image_size = vae.get_image_size()

    subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S')
    model_dir = os.path.join(os.path.expanduser(args.models_base_dir), subdir)
    if not os.path.isdir(model_dir):  # Create the model directory if it doesn't exist
        os.makedirs(model_dir)
    log_file_name = os.path.join(model_dir, 'logs.h5')
    
    # Write arguments to a text file
    facenet.write_arguments_to_file(args, os.path.join(model_dir, 'arguments.txt'))
        
    # Store some git revision info in a text file in the log directory
    src_path,_ = os.path.split(os.path.realpath(__file__))
    facenet.store_revision_info(src_path, model_dir, ' '.join(sys.argv))
    
    with tf.Graph().as_default():
        tf.set_random_seed(args.seed)
        global_step = tf.Variable(0, trainable=False)
        
        train_set = facenet.get_dataset(args.data_dir)
        image_list, _ = facenet.get_image_paths_and_labels(train_set)
        
        # Create the input queue
        input_queue = tf.train.string_input_producer(image_list, shuffle=True)
    
        nrof_preprocess_threads = 4
        image_per_thread = []
        for _ in range(nrof_preprocess_threads):
            file_contents = tf.read_file(input_queue.dequeue())
            image = tf.image.decode_image(file_contents, channels=3)
            image = tf.image.resize_image_with_crop_or_pad(image, args.input_image_size, args.input_image_size)
            image.set_shape((args.input_image_size, args.input_image_size, 3))
            image = tf.cast(image, tf.float32)
            #pylint: disable=no-member
            image_per_thread.append([image])
    
        images = tf.train.batch_join(
            image_per_thread, batch_size=args.batch_size,
            capacity=4 * nrof_preprocess_threads * args.batch_size,
            allow_smaller_final_batch=False)
        
        # Normalize
        images_norm = (images-img_mean) / img_stddev

        # Resize to appropriate size for the encoder 
        images_norm_resize = tf.image.resize_images(images_norm, (gen_image_size,gen_image_size))
        
        # Create encoder network
        mean, log_variance = vae.encoder(images_norm_resize, True)
        
        epsilon = tf.random_normal((tf.shape(mean)[0], args.latent_var_size))
        std = tf.exp(log_variance/2)
        latent_var = mean + epsilon * std
        
        # Create decoder network
        reconstructed_norm = vae.decoder(latent_var, True)
        
        # Un-normalize
        reconstructed = (reconstructed_norm*img_stddev) + img_mean
        
        # Create reconstruction loss
        if args.reconstruction_loss_type=='PLAIN':
            images_resize = tf.image.resize_images(images, (gen_image_size,gen_image_size))
            reconstruction_loss = tf.reduce_mean(tf.reduce_sum(tf.pow(images_resize - reconstructed,2)))
        elif args.reconstruction_loss_type=='PERCEPTUAL':
            network = importlib.import_module(args.model_def)

            reconstructed_norm_resize = tf.image.resize_images(reconstructed_norm, (args.input_image_size,args.input_image_size))

            # Stack images from both the input batch and the reconstructed batch in a new tensor 
            shp = [-1] + images_norm.get_shape().as_list()[1:]
            input_images = tf.reshape(tf.stack([images_norm, reconstructed_norm_resize], axis=0), shp)
            _, end_points = network.inference(input_images, 1.0, 
                phase_train=False, bottleneck_layer_size=128, weight_decay=0.0)

            # Get a list of feature names to use for loss terms
            feature_names = args.loss_features.replace(' ', '').split(',')

            # Calculate L2 loss between original and reconstructed images in feature space
            reconstruction_loss_list = []
            for feature_name in feature_names:
                feature_flat = slim.flatten(end_points[feature_name])
                image_feature, reconstructed_feature = tf.unstack(tf.reshape(feature_flat, [2,args.batch_size,-1]), num=2, axis=0)
                reconstruction_loss = tf.reduce_mean(tf.reduce_sum(tf.pow(image_feature-reconstructed_feature, 2)), name=feature_name+'_loss')
                reconstruction_loss_list.append(reconstruction_loss)
            # Sum up the losses in for the different features
            reconstruction_loss = tf.add_n(reconstruction_loss_list, 'reconstruction_loss')
        else:
            pass
        
        # Create KL divergence loss
        kl_loss = kl_divergence_loss(mean, log_variance)
        kl_loss_mean = tf.reduce_mean(kl_loss)
        
        total_loss = args.alfa*kl_loss_mean + args.beta*reconstruction_loss
        
        learning_rate = tf.train.exponential_decay(args.initial_learning_rate, global_step,
            args.learning_rate_decay_steps, args.learning_rate_decay_factor, staircase=True)
        
        # Calculate gradients and make sure not to include parameters for the perceptual loss model
        opt = tf.train.AdamOptimizer(learning_rate)
        grads = opt.compute_gradients(total_loss, var_list=get_variables_to_train())
        
        # Apply gradients
        apply_gradient_op = opt.apply_gradients(grads, global_step=global_step)
        with tf.control_dependencies([apply_gradient_op]):
            train_op = tf.no_op(name='train')

        # Create a saver
        saver = tf.train.Saver(tf.trainable_variables(), max_to_keep=3)
        
        facenet_saver = tf.train.Saver(get_facenet_variables_to_restore())

        # Start running operations on the Graph
        gpu_memory_fraction = 1.0
        gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=gpu_memory_fraction)
        sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options, log_device_placement=False))
        sess.run(tf.global_variables_initializer())
        sess.run(tf.local_variables_initializer())
        coord = tf.train.Coordinator()
        tf.train.start_queue_runners(coord=coord, sess=sess)

        with sess.as_default():
            
            if args.reconstruction_loss_type=='PERCEPTUAL':
                if not args.pretrained_model:
                    raise ValueError('A pretrained model must be specified when using perceptual loss')
                pretrained_model_exp = os.path.expanduser(args.pretrained_model)
                print('Restoring pretrained model: %s' % pretrained_model_exp)
                facenet_saver.restore(sess, pretrained_model_exp)
          
            log = {
                'total_loss': np.zeros((0,), np.float),
                'reconstruction_loss': np.zeros((0,), np.float),
                'kl_loss': np.zeros((0,), np.float),
                'learning_rate': np.zeros((0,), np.float),
                }
            
            step = 0
            print('Running training')
            while step < args.max_nrof_steps:
                start_time = time.time()
                step += 1
                save_state = step>0 and (step % args.save_every_n_steps==0 or step==args.max_nrof_steps)
                if save_state:
                    _, reconstruction_loss_, kl_loss_mean_, total_loss_, learning_rate_, rec_ = sess.run(
                          [train_op, reconstruction_loss, kl_loss_mean, total_loss, learning_rate, reconstructed])
                    img = facenet.put_images_on_grid(rec_, shape=(16,8))
                    misc.imsave(os.path.join(model_dir, 'reconstructed_%06d.png' % step), img)
                else:
                    _, reconstruction_loss_, kl_loss_mean_, total_loss_, learning_rate_ = sess.run(
                          [train_op, reconstruction_loss, kl_loss_mean, total_loss, learning_rate])
                log['total_loss'] = np.append(log['total_loss'], total_loss_)
                log['reconstruction_loss'] = np.append(log['reconstruction_loss'], reconstruction_loss_)
                log['kl_loss'] = np.append(log['kl_loss'], kl_loss_mean_)
                log['learning_rate'] = np.append(log['learning_rate'], learning_rate_)

                duration = time.time() - start_time
                print('Step: %d \tTime: %.3f \trec_loss: %.3f \tkl_loss: %.3f \ttotal_loss: %.3f' % (step, duration, reconstruction_loss_, kl_loss_mean_, total_loss_))

                if save_state:
                    print('Saving checkpoint file')
                    checkpoint_path = os.path.join(model_dir, 'model.ckpt')
                    saver.save(sess, checkpoint_path, global_step=step, write_meta_graph=False)
                    print('Saving log')
                    with h5py.File(log_file_name, 'w') as f:
                        for key, value in log.iteritems():
                            f.create_dataset(key, data=value)
Beispiel #12
0
def main(args):
    #define three networks
    network_G = importlib.import_module(args.model_def)              #import G Network  
    network_D = importlib.import_module(args.discriminator_def)      #import D Network (connected with G)
    network_F = importlib.import_module(args.Net_def)                #F network(same with G)

    #model dir
    subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S')      #model name (named by time)1
    log_dir = os.path.join(os.path.expanduser(args.logs_base_dir), subdir)
    if not os.path.isdir(log_dir):                                   # Create the log directory if it doesn't exist 1
        os.makedirs(log_dir)
    model_dir = os.path.join(os.path.expanduser(args.models_base_dir), subdir)
    if not os.path.isdir(model_dir):                                 # Create the model directory if it doesn't exist 1 
        os.makedirs(model_dir)

    # Write arguments to a text file 1
    facenet.write_arguments_to_file(args, os.path.join(log_dir, 'arguments.txt'))    #mark arguments
        
    # Store some git revision info in a text file in the log directory 1
    src_path,_ = os.path.split(os.path.realpath(__file__))
    facenet.store_revision_info(src_path, log_dir, ' '.join(sys.argv))

    np.random.seed(seed=args.seed)
    random.seed(args.seed)
    train_set = facenet.get_dataset(args.data_dir)            #get train dataset
    if args.filter_filename:                           #not used
        train_set = filter_dataset(train_set, os.path.expanduser(args.filter_filename), 
            args.filter_percentile, args.filter_min_nrof_images_per_class)
    nrof_classes = len(train_set)
    
    print('Model directory: %s' % model_dir)
    print('Log directory: %s' % log_dir)
    pretrained_model = None
    if args.pretrained_model:
        pretrained_model = os.path.expanduser(args.pretrained_model)       #facenet model
        print('Pre-trained model: %s' % pretrained_model)
   
    # not used here
    if args.lfw_dir:
        print('LFW directory: %s' % args.lfw_dir)
        # Read the file containing the pairs used for testing
        pairs = lfw.read_pairs(os.path.expanduser(args.lfw_pairs))
        # Get the paths for the corresponding images
        lfw_paths, actual_issame = lfw.get_paths(os.path.expanduser(args.lfw_dir), pairs, args.lfw_file_ext)



    # copy from faceNet
    def get_image_paths_and_labels(dataset):
        image_paths_flat = []
        labels_flat = []
        for i in range(len(dataset)):
            image_paths_flat += dataset[i].image_paths
            #print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')#++++++++++++++++++++++++++++++++
            #print(dataset[i].image_paths)#++++++++++++++++++++++++++++++++
            labels_flat += [i] * len(dataset[i].image_paths)#labels_flat=age??????????????????????????????????????
        return image_paths_flat, labels_flat
    
    
    
    with tf.Graph().as_default():
        tf.set_random_seed(args.seed)
        global_step = tf.Variable(0, trainable=False)
        # Get a list of image paths and their labels
        image_list, label_list = get_image_paths_and_labels(train_set)   #[path, path, ..., path], [1,1,2,2,2,3,3,4,...,9]
        assert len(image_list)>0, 'The dataset should not be empty'

        # Create a queue that produces indices into the image_list and label_list 
        #labels and images into queue
        labels = ops.convert_to_tensor(label_list, dtype=tf.int32)
        
        range_size = array_ops.shape(labels)[0]
        
        index_queue = tf.train.range_input_producer(range_size, num_epochs=None,
                             shuffle=True, seed=None, capacity=32) 
        index_dequeue_op = index_queue.dequeue_many(args.batch_size*args.epoch_size, 'index_dequeue')
        
        #placeholder
        learning_rate_placeholder = tf.placeholder(tf.float32, name='learning_rate')

        batch_size_placeholder = tf.placeholder(tf.int32, name='batch_size')
        
        phase_train_placeholder = tf.placeholder(tf.bool, name='phase_train')    #connected to validate
        
        image_paths_placeholder = tf.placeholder(tf.string, shape=(None,1), name='image_paths')

        image_embeddings_placeholder = tf.placeholder(tf.float32, shape=(None,1,args.embedding_size), name='image_embs')

        labels_placeholder = tf.placeholder(tf.int64, shape=(None,1), name='labels')
        
        input_queue = data_flow_ops.FIFOQueue(capacity=100000, dtypes=[tf.string, tf.int64,tf.float32],
                                    shapes=[(1,), (1,),(1,args.embedding_size,)], shared_name=None, name=None)   #(image path, labels, embedding)
        
        enqueue_op = input_queue.enqueue_many([image_paths_placeholder, labels_placeholder,image_embeddings_placeholder], name='enqueue_op')
        
        nrof_preprocess_threads = 4
        images_and_labels = []

        #preprocess some images to extend database

        for _ in range(nrof_preprocess_threads):
            filenames, label ,image_embeddings= input_queue.dequeue()    #get (image path, labels, embedding) from queue
            print('filenames.shape, label.shape, image_embeddings.shape:')
            print(filenames.shape,label.shape,image_embeddings.shape)
            #print(filenames[1,1])  #queueeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeecheck
            images = []
            for filename in tf.unstack(filenames):
                file_contents = tf.read_file(filename)
                image = tf.image.decode_image(file_contents, channels=3)  #BGR, , Decode .PNG read an image from filename=image path
                
                if args.random_rotate:
                    image = tf.py_func(facenet.random_rotate_image, [image], tf.uint8)
                if args.random_crop:
                    image = tf.random_crop(image, [args.image_size, args.image_size, 3])
                else:  #run here
                    image = tf.image.resize_image_with_crop_or_pad(image, args.image_size, args.image_size)
                if args.random_flip:
                    image = tf.image.random_flip_left_right(image)
               
                
                #pylint: disable=no-member
                image.set_shape((args.image_size, args.image_size, 3))
                images.append(tf.image.per_image_standardization(image)) #add into image set named images
            #print(len(images))                                                  #1?????
            images_and_labels.append([images, label,image_embeddings])

        #from queue into batch
        image_batch, label_batch ,embeddings_batch= tf.train.batch_join(
            images_and_labels, batch_size=batch_size_placeholder, 
            shapes=[(args.image_size, args.image_size, 3), (),(128)], enqueue_many=True,
            capacity=4 * nrof_preprocess_threads * args.batch_size,
            allow_smaller_final_batch=True)
        print('Shape of embeddings_batch:')
        print(embeddings_batch.shape)
        image_batch = tf.identity(image_batch, 'image_batch')
        image_batch = tf.identity(image_batch, 'input')
        label_batch = tf.identity(label_batch, 'label_batch')
        embeddings_batch = tf.identity(embeddings_batch, 'emb_batch')
        
        print('Total number of classes:%d' %nrof_classes)
        print('Length of image list:%d' % len(image_list))
        print('Building training graph ...')

        # Build the inference graph, from inception resnet.py
        prelogits, ep = network_G.inference(image_batch, args.keep_probability,
            phase_train=phase_train_placeholder, bottleneck_layer_size=args.embedding_size, 
            weight_decay=args.weight_decay)
        prelogits2, _ = network_D.inference(prelogits,ep, args.keep_probability,
            phase_train=phase_train_placeholder, bottleneck_layer_size=args.embedding_size, 
            weight_decay=args.weight_decay)
        prelogits3, ep2 = network_F.inference(image_batch, args.keep_probability,
            phase_train=phase_train_placeholder, bottleneck_layer_size=args.embedding_size, 
            weight_decay=args.weight_decay)
        logits = slim.fully_connected(prelogits2, len(train_set), activation_fn=None, 
                weights_initializer=tf.truncated_normal_initializer(stddev=0.1), 
                weights_regularizer=slim.l2_regularizer(args.weight_decay),
                scope='DiscriminatorLogits', reuse=False)

        embeddings = tf.nn.l2_normalize(prelogits, 1, 1e-10, name='embeddings')     #G feature
        embeddings2 = tf.nn.l2_normalize(prelogits3, 1, 1e-10, name='embeddings2')    #F feature
        labels = tf.nn.l2_normalize(prelogits2, 1, 1e-10, name='labels')              #D decision
        print('embeddingsshape:',embeddings.shape,embeddings_batch.shape)

        emb_loss = args.beta * tf.reduce_mean(tf.square(embeddings - embeddings_batch)) #!!!!!!!!!!!!!!!!!!!!!!!emb_loss=pretrained feature-F feature
        #print('emb_loss')
        #print(np.sum(emb_loss))

        # Add center loss for D
        center_loss_all=0.0
        if args.center_loss_factor>0.0:
            prelogits_center_loss, _ = facenet.center_loss(prelogits2, label_batch, args.center_loss_alfa, nrof_classes)
            center_loss_all = prelogits_center_loss * args.center_loss_factor
            # Do not add the center loss to regularization
            #regularization_losses = tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES)

        learning_rate = tf.train.exponential_decay(learning_rate_placeholder, global_step,
            args.learning_rate_decay_epochs*args.epoch_size, args.learning_rate_decay_factor, staircase=True)
        tf.summary.scalar('learning_rate', learning_rate)

        # Calculate the average cross entropy loss across the batch 1
        cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(
            labels=label_batch, logits=logits, name='cross_entropy_per_example')
        cross_entropy_mean = tf.reduce_mean(cross_entropy, name='cross_entropy')
        tf.add_to_collection('losses', cross_entropy_mean)
        
        # Calculate the reg losses
        regularization_losses = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES)

        #********************************************consistency_loss************************************************************************
        consistency_loss_G = args.betaG * tf.reduce_mean(tf.square(embeddings - embeddings2))
        consistency_loss_F = args.betaF * tf.reduce_mean(tf.square(embeddings - embeddings2))  #different coefficients

        #*******************************************unsupervised id loss*********************************************************************
        #anchor, positive, negative = tf.unstack(tf.reshape(embeddings, [-1,3,args.embedding_size]), 3, 1)
        anchor = embeddings
        positive = embeddings2
        negative = embeddings
        id_loss = args.betaI * identity_loss(anchor, positive, negative, args.alpha, args.batch_size)

        #************************************************************************************************************************************


        # losses of three networks
        total_loss_G = tf.add_n([-cross_entropy_mean] +[-center_loss_all]+ [emb_loss]+[consistency_loss_G]+ regularization_losses, name='total_loss_G')   # loss of G_network, to decrease the discriminant
                                                                                                                                        #  of age while not change embeddings
        total_loss_D = tf.add_n([cross_entropy_mean] +[center_loss_all]+ regularization_losses, name='total_loss_D') 
        total_loss_F = tf.add_n([id_loss]+ [consistency_loss_F]+ regularization_losses, name='total_loss_F') 


        #optimizer###########################################################################################################################
        optimizer=args.optimizer
        loss_averages_op1 = facenet._add_loss_summaries(total_loss_D)
        loss_averages_op2 = facenet._add_loss_summaries(total_loss_G)
        loss_averages_op3 = facenet._add_loss_summaries(total_loss_F)  #just add an op?

        learning_rate2=learning_rate
        learning_rate3=learning_rate
        if optimizer=='ADAGRAD':
            opt1 = tf.train.AdagradOptimizer(learning_rate)
            opt2 = tf.train.AdagradOptimizer(learning_rate2)
            opt3 = tf.train.AdagradOptimizer(learning_rate3)
        elif optimizer=='ADADELTA':
            opt1 = tf.train.AdadeltaOptimizer(learning_rate, rho=0.9, epsilon=1e-6)
            opt2 = tf.train.AdadeltaOptimizer(learning_rate2, rho=0.9, epsilon=1e-6)
            opt3 = tf.train.AdadeltaOptimizer(learning_rate3, rho=0.9, epsilon=1e-6)
        elif optimizer=='ADAM':
            opt1 = tf.train.AdamOptimizer(learning_rate, beta1=0.9, beta2=0.999, epsilon=0.1)
            opt2 = tf.train.AdamOptimizer(learning_rate2, beta1=0.9, beta2=0.999, epsilon=0.1)
            opt3 = tf.train.AdadeltaOptimizer(learning_rate3, beta1=0.9, beta2=0.999, epsilon=0.1)
        elif optimizer=='RMSPROP':
            opt1 = tf.train.RMSPropOptimizer(learning_rate, decay=0.9, momentum=0.9, epsilon=1.0)
            opt2 = tf.train.RMSPropOptimizer(learning_rate2, decay=0.9, momentum=0.9, epsilon=1.0)
            opt3 = tf.train.AdadeltaOptimizer(learning_rate3, decay=0.9, momentum=0.9, epsilon=1.0)
        elif optimizer=='MOM':
            opt1 = tf.train.MomentumOptimizer(learning_rate, 0.9, use_nesterov=True)
            opt2 = tf.train.MomentumOptimizer(learning_rate2, 0.9, use_nesterov=True)
            opt3 = tf.train.AdadeltaOptimizer(learning_rate3, 0.9, use_nesterov=True)
        else:
            raise ValueError('Invalid optimization algorithm2')
        t_vars=tf.trainable_variables()

        varlog=open('tvar.txt','w')
        for var in t_vars:
            varlog.write(var.name+'\n')
        varlog.close()

        #variables
        d_vars=[var for var in t_vars if 'Discriminator' in var.name]
        g_vars=[var for var in t_vars if 'InceptionResnetV1' in var.name]    #Generator? how to 
        f_vars=[var for var in t_vars if 'InceptionResnetV2' in var.name]    #Generator? how to
        #true loss for age discriminator and false loss for generator
        dt_grads = opt1.compute_gradients(total_loss_D, d_vars)
        df_grads = opt2.compute_gradients(total_loss_G, g_vars)
        di_grads = opt3.compute_gradients(total_loss_F, f_vars)
        dt_train_op = opt1.apply_gradients(dt_grads, global_step=global_step)
        df_train_op = opt2.apply_gradients(df_grads, global_step=global_step)
        di_train_op = opt3.apply_gradients(di_grads, global_step=global_step)
        for var in tf.trainable_variables():
            tf.summary.histogram(var.op.name, var)


        # Add histograms for gradients. copy from train2
        
        for grad, var in dt_grads:
            if grad is not None:
                tf.summary.histogram(var.op.name + '/gradients', grad)
        for grad, var in df_grads:
            if grad is not None:
                tf.summary.histogram(var.op.name + '/gradients', grad)
        for grad, var in di_grads:
            if grad is not None:
                tf.summary.histogram(var.op.name + '/gradients', grad)
  
        # Track the moving averages of all trainable variables.
        variable_averages = tf.train.ExponentialMovingAverage(
            args.moving_average_decay, global_step)
        variables_averages_op = variable_averages.apply(tf.trainable_variables())
  
        with tf.control_dependencies([dt_train_op,df_train_op, variables_averages_op]):
            train_op = tf.no_op(name='train')
        
        # Create a saver
        saver = tf.train.Saver(tf.trainable_variables(), max_to_keep=3) # save all variables++++++++++++++++++++++++++++++++++++0
        saver_G = tf.train.Saver(g_vars, max_to_keep=3)   #only save G variables0
        saver_F = tf.train.Saver(f_vars, max_to_keep=3)   #only save G variables0

        # Build the summary operation based on the TF collection of Summaries. 1
        summary_op = tf.summary.merge_all()

        # Start running operations on the Graph. 1
        gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=args.gpu_memory_fraction)
        sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options, log_device_placement=False))
        sess.run(tf.global_variables_initializer())
        sess.run(tf.local_variables_initializer())
        summary_writer = tf.summary.FileWriter(log_dir, sess.graph)
        coord = tf.train.Coordinator()
        tf.train.start_queue_runners(coord=coord, sess=sess)


        with sess.as_default():

            if pretrained_model:
                print('Restoring pretrained model: %s' % pretrained_model)
                saver_G.restore(sess, pretrained_model)

            print('Running pretrain embeddings')#see embs**********************************
            len_all=len(label_list)  #*****This is ok 397459
            #print('len_all=')
            #print(len_all)
            emb_list=np.zeros((len_all,args.embedding_size))
            print(len_all//(args.batch_size*args.epoch_size)+1)

            #obtain pretain feature
            for ii in range(0,len_all//(args.batch_size*args.epoch_size)+1):
                emb_list=first_train(args, sess, 0, image_list, label_list, index_dequeue_op, enqueue_op, image_paths_placeholder, labels_placeholder,
                    image_embeddings_placeholder,emb_list,embeddings,label_batch,
                    learning_rate_placeholder, phase_train_placeholder, batch_size_placeholder, global_step, 
                    total_loss_D, train_op, summary_op, summary_writer, regularization_losses, args.learning_rate_schedule_file)


            for ii in range(0,len_all):
                #print('pretrain embeddings')
                #print(np.sum(emb_list[ii,:]),file=f)    #cannot be printed,why~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!
                print(emb_list[ii,:],file=f) 

            # Training and validation loop
            print('Running training')
            epoch = 0
            while epoch < args.max_nrof_epochs:
                step = sess.run(global_step, feed_dict=None)
                epoch = step // args.epoch_size//2
                # Train for one epoch
                train(args, sess, epoch, image_list, label_list, index_dequeue_op, enqueue_op, image_paths_placeholder, labels_placeholder,
                    image_embeddings_placeholder,emb_list,
                    learning_rate_placeholder, phase_train_placeholder, batch_size_placeholder, global_step, 
                    total_loss_D, train_op, summary_op, summary_writer, regularization_losses, args.learning_rate_schedule_file, anchor, positive, negative, id_loss, consistency_loss_G, emb_loss)

                # Save variables and the metagraph if it doesn't exist already 1
                save_variables_and_metagraph(sess, saver, summary_writer, model_dir, subdir, step)

                # Evaluate on LFW 1
                if args.lfw_dir:
                    evaluate(sess, enqueue_op, image_paths_placeholder, labels_placeholder, phase_train_placeholder, batch_size_placeholder, 
                        embeddings, label_batch, lfw_paths, actual_issame, args.lfw_batch_size, args.lfw_nrof_folds, log_dir, step, summary_writer)
    return model_dir
Beispiel #13
0
def main(args):
    network = importlib.import_module(args.model_def)
    subdir = time.strftime('%Y%m%d-%H%M%S', time.localtime())
    log_dir = os.path.join(os.path.expanduser(args.logs_base_dir), subdir)
    if not os.path.isdir(
            log_dir):  # Create the log directory if it doesn't exist
        os.makedirs(log_dir)
    model_dir = os.path.join(os.path.expanduser(args.models_base_dir), subdir)
    if not os.path.isdir(
            model_dir):  # Create the model directory if it doesn't exist
        os.makedirs(model_dir)

    # Write arguments to a text file
    facenet.write_arguments_to_file(args, os.path.join(log_dir,
                                                       'arguments.txt'))

    np.random.seed(seed=args.seed)

    train_set = utils.___get_dataset(args.file_exp)

    print('Model directory: %s' % model_dir)
    print('Log directory: %s' % log_dir)
    # 如果选择了预训练的模型的话,这里我们会选取facenet的网络作预训练
    if args.pretrained_model:
        print('Pre-trained model: %s' %
              os.path.expanduser(args.pretrained_model))

    with tf.Graph().as_default():
        tf.set_random_seed(args.seed)
        global_step = tf.Variable(0, trainable=False)

        # Placeholder for the learning rate
        learning_rate_placeholder = tf.placeholder(tf.float32,
                                                   name='learning_rate')

        batch_size_placeholder = tf.placeholder(tf.int32, name='batch_size')

        phase_train_placeholder = tf.placeholder(tf.bool, name='phase_train')

        image_paths_placeholder = tf.placeholder(tf.string,
                                                 shape=(None, 3),
                                                 name='image_paths')
        labels_placeholder = tf.placeholder(tf.int64,
                                            shape=(None, 3),
                                            name='labels')
        # input queue 其实就是 路径/label,三元组,也就是make好pair的
        # label的必要性?
        input_queue = data_flow_ops.FIFOQueue(capacity=100000,
                                              dtypes=[tf.string, tf.int64],
                                              shapes=[(3, ), (3, )],
                                              shared_name=None,
                                              name=None)
        enqueue_op = input_queue.enqueue_many(
            [image_paths_placeholder, labels_placeholder])

        nrof_preprocess_threads = 4
        images_and_labels = []
        # 这里其实就是对数据进行预处理,通过从queue中获取到数据,读取路径下的图片并且预处理后做成一个list
        for _ in range(nrof_preprocess_threads):
            filenames, label = input_queue.dequeue()
            images = []
            for filename in tf.unstack(filenames):
                file_contents = tf.read_file(filename)
                image = tf.image.decode_image(file_contents, channels=3)

                if args.random_crop:
                    image = tf.random_crop(
                        image, [args.image_size, args.image_size, 3])
                else:
                    image = tf.image.resize_image_with_crop_or_pad(
                        image, args.image_size, args.image_size)
                if args.random_flip:
                    image = tf.image.random_flip_left_right(image)

                # pylint: disable=no-member
                image.set_shape((args.image_size, args.image_size, 3))
                images.append(tf.image.per_image_standardization(image))
            images_and_labels.append([images, label])
            # print('image input successfully!')

        # 其实就是对于list里面进行获取batch
        image_batch, labels_batch = tf.train.batch_join(
            images_and_labels,
            batch_size=batch_size_placeholder,
            shapes=[(args.image_size, args.image_size, 3), ()],
            enqueue_many=True,
            capacity=4 * nrof_preprocess_threads * args.batch_size,
            allow_smaller_final_batch=True)
        # 返回一个节点,那么就可以做到更新节点,每次产生新的batch
        image_batch = tf.identity(image_batch, 'image_batch')
        image_batch = tf.identity(image_batch, 'input')
        labels_batch = tf.identity(labels_batch, 'label_batch')

        # Build the inference graph
        # 网络的参数设置,返回的是输出的dropout和fc(bottleneck)之后的输出,那么label到底作用在哪里
        prelogits, _ = network.inference(
            image_batch,
            args.keep_probability,
            phase_train=phase_train_placeholder,
            bottleneck_layer_size=args.embedding_size,
            weight_decay=args.weight_decay)
        # embedding 其实就是对于softmax进行距离的l2正则化
        embeddings = tf.nn.l2_normalize(prelogits, 1, 1e-10, name='embeddings')
        # 把我们输入进去的图片集得到的结果拆分为三元组
        # Split embeddings into anchor, positive and negative and calculate triplet loss
        anchor, positive, negative = tf.unstack(
            tf.reshape(embeddings, [-1, 3, args.embedding_size]), 3, 1)
        triplet_loss = facenet.triplet_loss(anchor, positive, negative,
                                            args.alpha)
        # get到了,把learning rate 坐成一个placeholder就可以动态调整learning rate啦
        learning_rate = tf.train.exponential_decay(
            learning_rate_placeholder,
            global_step,
            args.learning_rate_decay_epochs * args.epoch_size,
            args.learning_rate_decay_factor,
            staircase=True)
        tf.summary.scalar('learning_rate', learning_rate)

        # Calculate the total losses
        # 正则化损失是什么
        # 图构建过程当中的所有的回归损失?哪里加进去了呢
        regularization_losses = tf.get_collection(
            tf.GraphKeys.REGULARIZATION_LOSSES)
        total_loss = tf.add_n([triplet_loss] + regularization_losses,
                              name='total_loss')

        # Build a Graph that trains the model with one batch of examples and updates the model parameters
        train_op = facenet.train(total_loss, global_step, args.optimizer,
                                 learning_rate, args.moving_average_decay,
                                 tf.global_variables())

        # Create a saver
        saver = tf.train.Saver(tf.trainable_variables(), max_to_keep=3)

        # Build the summary operation based on the TF collection of Summaries.
        summary_op = tf.summary.merge_all()

        # Start running operations on the Graph.
        # gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=args.gpu_memory_fraction)
        config = tf.ConfigProto()
        config.gpu_options.allow_growth = True
        sess = tf.Session(config=config)

        # Initialize variables
        sess.run(tf.global_variables_initializer(),
                 feed_dict={phase_train_placeholder: True})
        sess.run(tf.local_variables_initializer(),
                 feed_dict={phase_train_placeholder: True})
        # print('variable inti successfully!')
        summary_writer = tf.summary.FileWriter(log_dir, sess.graph)
        # 线程管理器
        coord = tf.train.Coordinator()
        tf.train.start_queue_runners(coord=coord, sess=sess)

        # print('begin to train!')
        with sess.as_default():
            # 读取预训练模型
            if args.pretrained_model:
                print('Restoring pretrained model: %s' % args.pretrained_model)
                saver.restore(sess, os.path.expanduser(args.pretrained_model))

            # Training and validation loop

            epoch = 0
            while epoch < args.max_nrof_epochs:
                step = sess.run(global_step, feed_dict=None)
                epoch = step // args.epoch_size
                # Train for one epoch
                # print('train another epoch')
                train(args, sess, train_set, epoch, image_paths_placeholder,
                      labels_placeholder, labels_batch, batch_size_placeholder,
                      learning_rate_placeholder, phase_train_placeholder,
                      enqueue_op, input_queue, global_step, embeddings,
                      total_loss, train_op, summary_op, summary_writer,
                      args.learning_rate_schedule_file, args.embedding_size,
                      anchor, positive, negative, triplet_loss)

                # Save variables and the metagraph if it doesn't exist already
                save_variables_and_metagraph(sess, saver, summary_writer,
                                             model_dir, subdir, step)
    return model_dir
Beispiel #14
0
def generate_input_fn(set, mode=tf.estimator.ModeKeys.EVAL, batch_size=1):
    def parse_function(filename, label):
        image_string = tf.read_file(filename)
        # Don't use tf.image.decode_image, or the output shape will be undefined
        image = tf.image.decode_jpeg(image_string, channels=3)
        # This will convert to float values in [0, 1]
        image = tf.image.convert_image_dtype(image, tf.float32)
        image = tf.image.resize_images(image, [args.image_size, args.image_size])
        return image, label

    def _input_fn():
        is_training = (mode == tf.estimator.ModeKeys.TRAIN)

        image_list, label_list = facenet.get_image_paths_and_labels(set)
        assert len(image_list)>0, 'The training set should not be empty'
        dataset = tf.data.Dataset.from_tensor_slices((filenames, labels))
        dataset = dataset.shuffle(len(filenames))
        dataset = dataset.map(parse_function, num_parallel_calls=args.nrof_preprocess_threads)

        if is_training:

        dataset = dataset.map(train_preprocess, num_parallel_calls=args.nrof_preprocess_threads)
        dataset = dataset.batch(args.batch_size)
        dataset = dataset.prefetch(args.prefetch_value)
        features = {'images': images}
        return features, label_list
  
  return _input_fn

def get_feature_columns():
    feature_columns = {
    'images': tf.feature_column.numeric_column('images', (IMAGE_HEIGHT, IMAGE_WIDTH, IMAGE_DEPTH)),
    }
    return feature_columns

def model_fn(features, labels, mode, params):
    # Create the input layers from the features                                                                                               
    feature_columns = list(get_feature_columns().values())

    images = tf.feature_column.input_layer(
    features=features, feature_columns=feature_columns)

    images = tf.reshape(
    images, shape=(-1, IMAGE_HEIGHT, IMAGE_WIDTH, IMAGE_DEPTH))

    # Calculate logits through CNN  
    network = importlib.import_module(args.model_def)    

    learning_rate_placeholder = tf.placeholder(tf.float32, name='learning_rate')
    batch_size_placeholder = tf.placeholder(tf.int32, name='batch_size')
    phase_train_placeholder = tf.placeholder(tf.bool, name='phase_train')
    image_paths_placeholder = tf.placeholder(tf.string, shape=(None,1), name='image_paths')
    labels_placeholder = tf.placeholder(tf.int32, shape=(None,1), name='labels')
    control_placeholder = tf.placeholder(tf.int32, shape=(None,1), name='control')

    # Build the inference graph
    prelogits, _ = network.inference(image_batch, args.keep_probability, 
        phase_train=phase_train_placeholder, bottleneck_layer_size=args.embedding_size, 
        weight_decay=args.weight_decay)
    logits = slim.fully_connected(prelogits, len(train_set), activation_fn=None, 
            weights_initializer=slim.initializers.xavier_initializer(), 
            weights_regularizer=slim.l2_regularizer(args.weight_decay),
            scope='Logits', reuse=False)

    embeddings = tf.nn.l2_normalize(prelogits, 1, 1e-10, name='embeddings')

    # Build a Graph that trains the model with one batch of examples and updates the model parameters
    train_op = facenet.train(total_loss, global_step, args.optimizer, 
        learning_rate, args.moving_average_decay, tf.global_variables(), args.log_histograms)
    
    # Create a saver
    saver = tf.train.Saver(tf.trainable_variables(), max_to_keep=3)

    # Build the summary operation based on the TF collection of Summaries.
    summary_op = tf.summary.merge_all()

    if mode in (tf.estimator.ModeKeys.PREDICT, tf.estimator.ModeKeys.EVAL):
        predicted_indices = tf.argmax(input=logits, axis=1)
        probabilities = tf.nn.softmax(logits, name='softmax_tensor')

    if mode in (tf.estimator.ModeKeys.TRAIN, tf.estimator.ModeKeys.EVAL):
        global_step = tf.train.get_or_create_global_step()
        tf.logging.info("Global Step {}".format(global_step))
        # Norm for the prelogits
        eps = 1e-4
        prelogits_norm = tf.reduce_mean(tf.norm(tf.abs(prelogits)+eps, ord=args.prelogits_norm_p, axis=1))
        tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES, prelogits_norm * args.prelogits_norm_loss_factor)

        # Add center loss
        prelogits_center_loss, _ = facenet.center_loss(prelogits, label_batch, args.center_loss_alfa, nrof_classes)
        tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES, prelogits_center_loss * args.center_loss_factor)

        learning_rate = tf.train.exponential_decay(params['learning_rate'], global_step,
            args.learning_rate_decay_epochs*args.epoch_size, args.learning_rate_decay_factor, staircase=True)
        tf.summary.scalar('learning_rate', learning_rate)

        # Calculate the average cross entropy loss across the batch
        cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(
            labels=label_batch, logits=logits, name='cross_entropy_per_example')
        cross_entropy_mean = tf.reduce_mean(cross_entropy, name='cross_entropy')
        tf.add_to_collection('losses', cross_entropy_mean)
        
        correct_prediction = tf.cast(tf.equal(tf.argmax(logits, 1), tf.cast(label_batch, tf.int64)), tf.float32)
        accuracy = tf.reduce_mean(correct_prediction)
        
        # Calculate the total losses
        regularization_losses = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES)
        total_loss = tf.add_n([cross_entropy_mean] + regularization_losses, name='total_loss')
        label_indices = tf.argmax(input=labels, axis=1)
        loss = tf.losses.softmax_cross_entropy(
            onehot_labels=labels, logits=logits)
        tf.summary.scalar('cross_entropy', loss)

    if mode == tf.estimator.ModeKeys.PREDICT:
        predictions = {
            'classes': predicted_indices,
            'probabilities': probabilities
        }
        export_outputs = {
            'predictions': tf.estimator.export.PredictOutput(predictions)
        }
        return tf.estimator.EstimatorSpec(
            mode, predictions=predictions, export_outputs=export_outputs)

    if mode == tf.estimator.ModeKeys.TRAIN:
         # Build a Graph that trains the model with one batch of examples and updates the model parameters
        train_op = facenet.train(total_loss, global_step, args.optimizer, 
            learning_rate, args.moving_average_decay, tf.global_variables(), args.log_histograms)
        
        # Create a saver
        saver = tf.train.Saver(tf.trainable_variables(), max_to_keep=3)

        # Build the summary operation based on the TF collection of Summaries.
        summary_op = tf.summary.merge_all()

        subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S')
        
        log_dir=params['log_dir']
        stat_file_name=params['stat_file_name']

        summary.value.add(tag='time/total', simple_value=train_time)

        summary_hook = tf.train.SummarySaverHook(
            SAVE_EVERY_N_STEPS,
            output_dir=log_dir,
            summary_op=tf.summary.merge_all())
        return tf.estimator.EstimatorSpec(mode, loss=loss, train_op=train, training_hooks=[summary_hook])

    if mode == tf.estimator.ModeKeys.EVAL:
        eval_metric_ops = {
            'accuracy': tf.metrics.accuracy(label_indices, predicted_indices)
        }
        return tf.estimator.EstimatorSpec(
            mode, loss=loss, eval_metric_ops=eval_metric_ops)

def main(args):  
    network = importlib.import_module(args.model_def)

    model_dir = os.path.join(os.path.expanduser(args.models_base_dir), subdir)
    if not os.path.isdir(model_dir):  # Create the model directory if it doesn't exist
        os.makedirs(model_dir)

    log_dir = os.path.join(os.path.expanduser(args.logs_base_dir), subdir)
        if not os.path.isdir(log_dir):  # Create the log directory if it doesn't exist
            os.makedirs(log_dir)

    stat_file_name = os.path.join(log_dir, 'stat.h5')

    # Write arguments to a text file
    facenet.write_arguments_to_file(args, os.path.join(log_dir, 'arguments.txt'))
        
    # Store some git revision info in a text file in the log directory
    src_path,_ = os.path.split(os.path.realpath(__file__))
    facenet.store_revision_info(src_path, log_dir, ' '.join(sys.argv))

    np.random.seed(seed=args.seed)
    random.seed(args.seed)
    dataset = facenet.get_dataset(args.data_dir)
    if args.filter_filename:
        dataset = filter_dataset(dataset, os.path.expanduser(args.filter_filename), 
            args.filter_percentile, args.filter_min_nrof_images_per_class)
        
    if args.validation_set_split_ratio>0.0:
        train_set, val_set = facenet.split_dataset(dataset, args.validation_set_split_ratio, args.min_nrof_val_images_per_class, 'SPLIT_IMAGES')
    else:
        train_set, val_set = dataset, []
        
    nrof_classes = len(train_set)
    
    print('Model directory: %s' % model_dir)
    print('Log directory: %s' % log_dir)
    pretrained_model = None
    if args.pretrained_model:
        pretrained_model = os.path.expanduser(args.pretrained_model)
        print('Pre-trained model: %s' % pretrained_model)
    
    if args.lfw_dir:
        print('LFW directory: %s' % args.lfw_dir)
        # Read the file containing the pairs used for testing
        pairs = lfw.read_pairs(os.path.expanduser(args.lfw_pairs))
        # Get the paths for the corresponding images
        lfw_paths, actual_issame = lfw.get_paths(os.path.expanduser(args.lfw_dir), pairs)

    print('Number of classes in training set: %d' % nrof_classes)
    print('Number of examples in training set: %d' % len(image_list))

    print('Number of classes in validation set: %d' % len(val_set))
    print('Number of examples in validation set: %d' % len(val_image_list))

    params={'log_dir':log_dir,'stat_file_name':stat_file_name,'stat':stat}
        
    with tf.Graph().as_default():
        # trainset, valset

        # Create a queue that produces indices into the image_list and label_list 
       
        learning_rate_placeholder = tf.placeholder(tf.float32, name='learning_rate')
        batch_size_placeholder = tf.placeholder(tf.int32, name='batch_size')
        phase_train_placeholder = tf.placeholder(tf.bool, name='phase_train')
        image_paths_placeholder = tf.placeholder(tf.string, shape=(None,1), name='image_paths')
        labels_placeholder = tf.placeholder(tf.int32, shape=(None,1), name='labels')
        control_placeholder = tf.placeholder(tf.int32, shape=(None,1), name='control')
 
        # Start running operations on the Graph.
        gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=args.gpu_memory_fraction,allow_growth=True)
        config=tf.ConfigProto(gpu_options=gpu_options, log_device_placement=False)
        config=tf.estimator.RunConfig(session_config=config,save_checkpoints_steps=args.save_checkpoints_steps,
        tf_random_seed=args.seed,
        model_dir=args.model_dir)

        estimator = tf.estimator.Estimator(
                model_fn=model_fn, 
                model_dir=FLAGS.model_dir,
                config=tf.contrib.learn.RunConfig(session_config=config),params=params)

        with sess.as_default():

            if pretrained_model:
                print('Restoring pretrained model: %s' % pretrained_model)
                saver.restore(sess, pretrained_model)

            nrof_steps = args.max_nrof_epochs*args.epoch_size
            nrof_val_samples = int(math.ceil(args.max_nrof_epochs / args.validate_every_n_epochs))   # Validate every validate_every_n_epochs as well as in the last epoch
            stat = {
                'loss': np.zeros((nrof_steps,), np.float32),
                'center_loss': np.zeros((nrof_steps,), np.float32),
                'reg_loss': np.zeros((nrof_steps,), np.float32),
                'xent_loss': np.zeros((nrof_steps,), np.float32),
                'prelogits_norm': np.zeros((nrof_steps,), np.float32),
                'accuracy': np.zeros((nrof_steps,), np.float32),
                'val_loss': np.zeros((nrof_val_samples,), np.float32),
                'val_xent_loss': np.zeros((nrof_val_samples,), np.float32),
                'val_accuracy': np.zeros((nrof_val_samples,), np.float32),
                'lfw_accuracy': np.zeros((args.max_nrof_epochs,), np.float32),
                'lfw_valrate': np.zeros((args.max_nrof_epochs,), np.float32),
                'learning_rate': np.zeros((args.max_nrof_epochs,), np.float32),
                'time_train': np.zeros((args.max_nrof_epochs,), np.float32),
                'time_validate': np.zeros((args.max_nrof_epochs,), np.float32),
                'time_evaluate': np.zeros((args.max_nrof_epochs,), np.float32),
                'prelogits_hist': np.zeros((args.max_nrof_epochs, 1000), np.float32),
              }
            for epoch in range(1,args.max_nrof_epochs+1):
                step = sess.run(global_step, feed_dict=None)
                # Train for one epoch
                t = time.time()
                cont = train(args, sess, epoch, image_list, label_list, index_dequeue_op, enqueue_op, image_paths_placeholder, labels_placeholder,
                    learning_rate_placeholder, phase_train_placeholder, batch_size_placeholder, control_placeholder, global_step, 
                    total_loss, train_op, summary_op, summary_writer, regularization_losses, args.learning_rate_schedule_file,
                    stat, cross_entropy_mean, accuracy, learning_rate,
                    prelogits, prelogits_center_loss, args.random_rotate, args.random_crop, args.random_flip, prelogits_norm, args.prelogits_hist_max, args.use_fixed_image_standardization)
                stat['time_train'][epoch-1] = time.time() - t
                
                if not cont:
                    break
                  
                t = time.time()
                if len(val_image_list)>0 and ((epoch-1) % args.validate_every_n_epochs == args.validate_every_n_epochs-1 or epoch==args.max_nrof_epochs):
                    validate(args, sess, epoch, val_image_list, val_label_list, enqueue_op, image_paths_placeholder, labels_placeholder, control_placeholder,
                        phase_train_placeholder, batch_size_placeholder, 
                        stat, total_loss, regularization_losses, cross_entropy_mean, accuracy, args.validate_every_n_epochs, args.use_fixed_image_standardization)
                stat['time_validate'][epoch-1] = time.time() - t

                # Save variables and the metagraph if it doesn't exist already
                save_variables_and_metagraph(sess, saver, summary_writer, model_dir, subdir, epoch)

                # Evaluate on LFW
                t = time.time()
                if args.lfw_dir:
                    evaluate(sess, enqueue_op, image_paths_placeholder, labels_placeholder, phase_train_placeholder, batch_size_placeholder, control_placeholder, 
                        embeddings, label_batch, lfw_paths, actual_issame, args.lfw_batch_size, args.lfw_nrof_folds, log_dir, step, summary_writer, stat, epoch, 
                        args.lfw_distance_metric, args.lfw_subtract_mean, args.lfw_use_flipped_images, args.use_fixed_image_standardization)
                stat['time_evaluate'][epoch-1] = time.time() - t

                print('Saving statistics')
                with h5py.File(stat_file_name, 'w') as f:
                    for key, value in stat.iteritems():
                        f.create_dataset(key, data=value)
    
    return model_dir
Beispiel #15
0
def main(args):
    network = importlib.import_module(args.model_def)
    image_size = (args.image_size, args.image_size)
    
    subdir = datetime.strftime(datatime.now(), '%Y%m%d-%H%M%S')
    log_dir = os.path.join(os.path.expanduser(args.logs_base_dir), subdir)
    if not os.path.isdir(log_dir):
        os.makedirs(log_dir)
    model_dir = os.path.join(os.path.expanduser(args.models_base_dir), subdir)
    if not os.path.isdir(model_dir):
        os.makedirs(model_dir)
        
    stat_file_name = os.path.join(log_dir, 'stat.h5')
    
    facenet.write_arguments_to_file(args, os.path.join(log_dir, 'arguments.txt'))
    
    src_path,_ = os.path.split(os.path.realpath(__file__))
    facenet.store_revision_info(src_path, log_dir, ' '.join(sys.argv))
    
    np.random.seed(seed=args.seed)
    random.seed(args.seed)
    dataset = facenet.get_dataset(args.data_dir)

    if args.validation_set_split_ratio > 0.0:
        train_set, val_set = facenet.split_dataset(dataset, args.validation_set_split_ratio, args.min_nrof_val_images_per_class, 
                                                   'SPLIT_IMAGES')
    else:
        train_set, val_set = dataset, []    
    
    num_classes = len(train_set)

    print('Model directory: %s' % model_dir)
    print('Log directory: %s' % log_dir)
    
    
    pretrained_model = None
    if args.pretrained_model:
        pretrained_model = os.path.expanduser(args.pretrained_model)
        print('Pre-trained model: %s' % pretrained_model)
        
    if args.lfw_dir:
        print('LFW directory: %s' % args.lfw_dir)
        pairs = lfw.read_pairs(os.path.expanduser(args.lfw_pairs))
        lfw_paths, actual_issame = lfw.get_paths(os.path.expanduser(args.lfw_dir), pairs)
        
    with tf.Graph().as_default():
        tf.set_random_state(args.seed)
        global_step = tf.Variable(0, trainable=False)
        
        image_list, label_list = facenet.get_image_paths_and_labels(train_set)
        assert len(image_list) > 0, 'The training set should not be empty'
        
        val_image_list, val_label_list = facenet.get_image_paths_and_labels(val_set)
        
        labels = ops.convert_to_tensor(label_list, dtype=tf.int32)
        range_size = array_ops.shape(labels)[0]
        index_q = tf.train.range_input_producer(range_size, num_epochs=None, shuffle=True, seed=None, capacity=32)
        index_deq_op = index_q.dequeue_many(args.batch_size * args.epoch_size, 'index_dequeue')
        
        learning_rate_placeholder = tf.placeholder(tf.float32, name='learning_rate')
        batch_size_placeholder = tf.placeholder(tf.int32, name='batch_size')
        phase_train_placeholder = tf.placeholder(tf.bool, name='phase_train')
        image_paths_placeholder = tf.placeholder(tf.string, shape=(None, 1), name='image_paths')
        labels_placeholder = tf.placeholder(tf.int32, shape=(None, 1), name='labels')
        control_placeholder = tf.placeholder(tf.int32, shape=(None, 1), name='control')
        
        num_preprocess_threads = 4
        input_q = data_flow_ops.FIFOQueue(capacity=2000000, shared_name=None, name=None,
                                         dtype=[tf.string, tf.int32, tf.int32], 
                                         shapes=[(1, ), (1, ), (1, )])
        enq_op = input_q.enqueue_many([image_paths_placeholder, labels_placeholder, control_placeholder], name='enq_op')

        image_batch, label_batch = facenet.create_input_pipeline(input_q, image_size, num_preprocess_threads, batch_size_placeholder)
        
        image_batch = tf.identity(image_batch, 'image_batch')
        image_batch = tf.identity(image_batch, 'input')
        label_batch = tf.identity(label_batch, 'label_batch')
        
        print('Number of classes in training set: %d' % nrof_classes)
        print('Number of examples in training set: %d' % len(image_list))
        print('Number of classes in validation set: %d' % len(val_set))
        print('Number of examples in validation set: %d' % len(val_image_list))
        print('Building training graph')        
        
        prelogits, _ = network.inference(image_batch, args.keep_probability, phase_train=phase_train_placeholder, 
                                         bottleneck_layer_size=args.embedding_size, weight_decay=args.weight_decay)
        
        logits = slim.fully_connected(prelogits, num_classes, activation_fn=None, reuse=False, scope='Logits', 
                                     weights_initializer=slim.initializers.xavier_initializer(), 
                                     weights_regularizer=slim.l2_regularizer(args.weight_decay))
        
        embeddings = tf.nn.l2_normalize(prelogits, 1, 1e-10, name='embeddings')
        
        eps = 1e-4
        prelogits_norm = tf.reduce_mean(tf.norm(tf.abs(prelogits) + eps, ord=args.prelogits_norm_p, axis=1))
        tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES, prelogits_norm * args.prelogits_norm_loss_factor)
        
        prelogits_center_loss, _ = facenet.center_loss(prelogits, label_batch, args.center_loss_alfa, num_classes)
        tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES, prelogits_center_loss * args.center_loss_factor)

        cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(labels=label_batch, logits=logits, name='cross_entropy_per_example')
        cross_entropy_mean = tf.reduce_mean(cross_entropy, name='cross_entropy')
        tf.add_to_collection('losses', cross_entropy_mean)

        regularization_loss = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES)        
        total_loss = tf.add_n([cross_entropy_mean] + regularization_loss, name='total_loss')

        correct_prediction = tf.cast(tf.equal(tf.argmax(logits, 1), tf.cast(label_batch, tf.int64)), tf.float32)
        accuracy = tf.reduce_mean(correct_prediction)
        
        learning_rate = tf.train.exponential_decay(learning_rate_placeholder, global_step, 
                                                  args.learning_rate_decay_epochs * args.epoch_size, 
                                                  args.learning_rate_decay_factor, staircase=True,)
        tf.summary.scalar('learning_rate', learning_rate)
        
        train_op = facenet.train(total_loss, global_step, args.optimizer, learning_rate, 
                                args.moving_average_decay, tf.global_variables(), args.log_histograms)

        saver = tf.train.Saver(tf.trainable_variables(), max_to_keep=3)
        
        summary_op = tf.summary.merge_all()
        
        gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=args.gpu_memory_fraction)
        
        sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options, log_device_placement=False))
        sess.run(tf.global_variables_initializer())
        sess.run(tf.local_variables_initializer())
        summary_writer = tf.summary.FileWriter(log_dir, sess.graph)
        coord = tf.train.Coordinator()
        tf.train.start_queue_runners(coord=coord, sess=sess)
        
        with sess.as_default():
            if pretrained_model:
                print('Restoring pretrained model: %s' % pretrained_model)
                saver.restore(sess, pretrained_model)
            
            print('Running training')
            num_steps = args.max_nrof_epochs * args.epoch_size
            num_val_samples = int(math.ceil(args.max_nrof_epochs / args.validate_every_n_epochs))
            
            stat = {
                'loss': np.zeros((num_steps,), np.float32),
                'center_loss': np.zeros((num_steps,), np.float32),
                'reg_loss': np.zeros((num_steps,), np.float32),
                'xent_loss': np.zeros((num_steps,), np.float32),
                'prelogits_norm': np.zeros((num_steps,), np.float32),
                'accuracy': np.zeros((num_steps,), np.float32),
                'val_loss': np.zeros((num_val_samples,), np.float32),
                'val_xent_loss': np.zeros((num_val_samples,), np.float32),
                'val_accuracy': np.zeros((num_val_samples,), np.float32),
                'lfw_accuracy': np.zeros((args.max_nrof_epochs,), np.float32),
                'lfw_valrate': np.zeros((args.max_nrof_epochs,), np.float32),
                'learning_rate': np.zeros((args.max_nrof_epochs,), np.float32),
                'time_train': np.zeros((args.max_nrof_epochs,), np.float32),
                'time_validate': np.zeros((args.max_nrof_epochs,), np.float32),
                'time_evaluate': np.zeros((args.max_nrof_epochs,), np.float32),
                'prelogits_hist': np.zeros((args.max_nrof_epochs, 1000), np.float32),
              }
            
            for epoch in range(1, args.max_nrof_epochs + 1):
                step = sess.run(global_step, feed_dict=None)
                t = time.time()
                cont = train(args, sess, epoch, image_list, label_list, index_dequeue_op, enqueue_op, 
                             image_paths_placeholder, labels_placeholder, learning_rate_placeholder, phase_train_placeholder, 
                             batch_size_placeholder, control_placeholder, global_step, total_loss, train_op, summary_op, 
                             summary_writer, regularization_losses, args.learning_rate_schedule_file, stat, cross_entropy_mean, 
                             accuracy, learning_rate, prelogits, prelogits_center_loss, args.random_rotate, args.random_crop, 
                             args.random_flip, prelogits_norm, args.prelogits_hist_max, args.use_fixed_image_standardization)
                stat['time_train'][epoch - 1] = time.time() - t
                
                if not cont:
                    break
                    
                t = time.time()
                if len(val_image_list)>0 and ((epoch-1) % args.validate_every_n_epochs == args.validate_every_n_epochs-1 or 
                                              epoch==args.max_nrof_epochs):
                    validate(args, sess, epoch, val_image_list, val_label_list, enqueue_op, image_paths_placeholder, 
                             labels_placeholder, control_placeholder, phase_train_placeholder, batch_size_placeholder, stat, 
                             total_loss, regularization_losses, cross_entropy_mean, accuracy, args.validate_every_n_epochs, 
                             args.use_fixed_image_standardization)
                    stat['time_validate'][epoch - 1] = time.time() - t
                    
                save_variables_and_metagraph(sess, saver, summary_writer, model_dir, subdir, epoch)
                
                t = time.time()
                if args.lfw_dir:
                    evaluate(sess, enqueue_op, image_paths_placeholder, labels_placeholder, phase_train_placeholder, 
                             batch_size_placeholder, control_placeholder, embeddings, label_batch, lfw_paths, actual_issame, 
                             args.lfw_batch_size, args.lfw_nrof_folds, log_dir, step, summary_writer, stat, epoch, 
                             args.lfw_distance_metric, args.lfw_subtract_mean, args.lfw_use_flipped_images, 
                             args.use_fixed_image_standardization)
                    stat['time_evaluate'][epoch - 1] = time.time() - t
                
                print('Saving statistics')
                with h5py.File(stat_file_name, 'w') as f:
                    for key, value in stat.items():
                        f.create_dataset(key, data=value)
    return model_dir
Beispiel #16
0
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
Beispiel #17
0
def main(args):
  
    # 模型,定义在inception_resnet_v1 V2里(), --model_def models.inception_resnet_v1  
    network = importlib.import_module(args.model_def)
    image_size = (args.image_size, args.image_size)

    subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S')
    log_dir = os.path.join(os.path.expanduser(args.logs_base_dir), subdir)
    if not os.path.isdir(log_dir):  # Create the log directory if it doesn't exist
        os.makedirs(log_dir)
    model_dir = os.path.join(os.path.expanduser(args.models_base_dir), subdir)
    if not os.path.isdir(model_dir):  # Create the model directory if it doesn't exist
        os.makedirs(model_dir)

    stat_file_name = os.path.join(log_dir, 'stat.h5')

    # Write arguments to a text file
    facenet.write_arguments_to_file(args, os.path.join(log_dir, 'arguments.txt'))
        
    # Store some git revision info in a text file in the log directory
    src_path,_ = os.path.split(os.path.realpath(__file__))
    facenet.store_revision_info(src_path, log_dir, ' '.join(sys.argv))

    np.random.seed(seed=args.seed)
    random.seed(args.seed)
    dataset = facenet.get_dataset(args.data_dir)
    if args.filter_filename:
        dataset = filter_dataset(dataset, os.path.expanduser(args.filter_filename), 
            args.filter_percentile, args.filter_min_nrof_images_per_class)
        
    if args.validation_set_split_ratio>0.0:
        train_set, val_set = facenet.split_dataset(dataset, args.validation_set_split_ratio, args.min_nrof_val_images_per_class, 'SPLIT_IMAGES')
    else:
        train_set, val_set = dataset, []
        
    nrof_classes = len(train_set)
    
    print('Model directory: %s' % model_dir)
    print('Log directory: %s' % log_dir)
    pretrained_model = None
    if args.pretrained_model:
        pretrained_model = os.path.expanduser(args.pretrained_model)
        print('Pre-trained model: %s' % pretrained_model)
    
    if args.lfw_dir:
        print('LFW directory: %s' % args.lfw_dir)
        # Read the file containing the pairs used for testing
        pairs = lfw.read_pairs(os.path.expanduser(args.lfw_pairs))
        # Get the paths for the corresponding images
        lfw_paths, actual_issame = lfw.get_paths(os.path.expanduser(args.lfw_dir), pairs)
    
    with tf.Graph().as_default():
        tf.set_random_seed(args.seed)
        global_step = tf.Variable(0, trainable=False)
        
        # Get a list of image paths and their labels
        # 训练数据
        image_list, label_list = facenet.get_image_paths_and_labels(train_set)
        assert len(image_list)>0, 'The training set should not be empty'
        
        # 测试数据
        val_image_list, val_label_list = facenet.get_image_paths_and_labels(val_set)

        # Create a queue that produces indices into the image_list and label_list 
        # tf.convert_to_tensor用于将不同数据变成张量:比如可以让数组变成张量、也可以让列表变成张量。
        labels = ops.convert_to_tensor(label_list, dtype=tf.int32)
        range_size = array_ops.shape(labels)[0]
        # 多线程读取数据,shuffle=True表示不是按顺序存储,可以随机获取,并一直循环。
        # https://blog.csdn.net/lyg5623/article/details/69387917
        index_queue = tf.train.range_input_producer(range_size, num_epochs=None,
                             shuffle=True, seed=None, capacity=32)
        
        # epoch 大数据时迭代完一轮时次数,少量数据应该epoch = 全部数据个数/batch
        index_dequeue_op = index_queue.dequeue_many(args.batch_size*args.epoch_size, 'index_dequeue')
        
        learning_rate_placeholder = tf.placeholder(tf.float32, name='learning_rate')
        batch_size_placeholder = tf.placeholder(tf.int32, name='batch_size')
        phase_train_placeholder = tf.placeholder(tf.bool, name='phase_train')
        image_paths_placeholder = tf.placeholder(tf.string, shape=(None,1), name='image_paths')
        labels_placeholder = tf.placeholder(tf.int32, shape=(None,1), name='labels')
        control_placeholder = tf.placeholder(tf.int32, shape=(None,1), name='control')
        
        nrof_preprocess_threads = 4
        input_queue = data_flow_ops.FIFOQueue(capacity=2000000,
                                    dtypes=[tf.string, tf.int32, tf.int32],
                                    shapes=[(1,), (1,), (1,)],
                                    shared_name=None, name=None)
        enqueue_op = input_queue.enqueue_many([image_paths_placeholder, labels_placeholder, control_placeholder], name='enqueue_op')
        image_batch, label_batch = facenet.create_input_pipeline(input_queue, image_size, nrof_preprocess_threads, batch_size_placeholder)

        image_batch = tf.identity(image_batch, 'image_batch')
        image_batch = tf.identity(image_batch, 'input')
        label_batch = tf.identity(label_batch, 'label_batch')
        
        print('Number of classes in training set: %d' % nrof_classes)
        print('Number of examples in training set: %d' % len(image_list))

        print('Number of classes in validation set: %d' % len(val_set))
        print('Number of examples in validation set: %d' % len(val_image_list))
        
        print('Building training graph')
        
        # Build the inference graph
        prelogits, _ = network.inference(image_batch, args.keep_probability, 
            phase_train=phase_train_placeholder, bottleneck_layer_size=args.embedding_size, 
            weight_decay=args.weight_decay)
        # 因为模型输出的(bottleneck_layer_size)没有计算最后一层(映射到图片类型),这里计算最后一层             
        logits = slim.fully_connected(prelogits, len(train_set), activation_fn=None, 
                weights_initializer=slim.initializers.xavier_initializer(), 
                weights_regularizer=slim.l2_regularizer(args.weight_decay),
                scope='Logits', reuse=False)

        # 按行进行泛化,行的平方求和再求平方根,得到的值按行除每个行的元素,对深度层面泛化? interface里最后一层输出为128个节点,slim.fully_connected(net, bottleneck_layer_size, activation_fn=None, 
				#https://blog.csdn.net/abiggg/article/details/79368982
        embeddings = tf.nn.l2_normalize(prelogits, 1, 1e-10, name='embeddings')

				# 计算loss函数,当然还有其它训练参数也会加到这里来,通过比训练过程中一个weight加到正则化参数里来tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES, weight)
				#  模型中最后会把这个加到优化的loss中来。
				#L= L_softmax + λL_cneter = Softmax(W_i + b_yj) + λ1/2||f(x_i) - c_yj ||_2^2
				
        # Norm for the prelogits
        eps = 1e-4
        prelogits_norm = tf.reduce_mean(tf.norm(tf.abs(prelogits)+eps, ord=args.prelogits_norm_p, axis=1))
        # 模型中最后输出(bottleneck_layer_size每个类型的输出值的个数)的平均值加到正则化loss中,但prelogits_norm_loss_factor貌似为0
        tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES, prelogits_norm * args.prelogits_norm_loss_factor)

        # 计算中心损失及增加的正则化loss中
        # Add center loss
        prelogits_center_loss, _ = facenet.center_loss(prelogits, label_batch, args.center_loss_alfa, nrof_classes)
        tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES, prelogits_center_loss * args.center_loss_factor)

        learning_rate = tf.train.exponential_decay(learning_rate_placeholder, global_step,
            args.learning_rate_decay_epochs*args.epoch_size, args.learning_rate_decay_factor, staircase=True)
        tf.summary.scalar('learning_rate', learning_rate)

        
        # Calculate the average cross entropy loss across the batch
        # 计算预测损失,和上面框架的Softmax(W_i + b_yj) 
        cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(
            labels=label_batch, logits=logits, name='cross_entropy_per_example')
        cross_entropy_mean = tf.reduce_mean(cross_entropy, name='cross_entropy')
        # 预测损失平均值加到losses变量中
        tf.add_to_collection('losses', cross_entropy_mean)
        
        correct_prediction = tf.cast(tf.equal(tf.argmax(logits, 1), tf.cast(label_batch, tf.int64)), tf.float32)
        accuracy = tf.reduce_mean(correct_prediction)
        
        #计算总损失,cross_entropy_mean + 前面增加的一些正则化损失(包括模型中增加的),通过tf.GraphKeys.REGULARIZATION_LOSSES获取出来
        # Calculate the total losses
        regularization_losses = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES)
        total_loss = tf.add_n([cross_entropy_mean] + regularization_losses, name='total_loss')

        # Build a Graph that trains the model with one batch of examples and updates the model parameters
        train_op = facenet.train(total_loss, global_step, args.optimizer, 
            learning_rate, args.moving_average_decay, tf.global_variables(), args.log_histograms)
        
        # Create a saver
        saver = tf.train.Saver(tf.trainable_variables(), max_to_keep=3)

        # Build the summary operation based on the TF collection of Summaries.
        summary_op = tf.summary.merge_all()

        # Start running operations on the Graph.
        gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=args.gpu_memory_fraction)
        sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options, log_device_placement=False))
        sess.run(tf.global_variables_initializer())
        sess.run(tf.local_variables_initializer())
        summary_writer = tf.summary.FileWriter(log_dir, sess.graph)
        coord = tf.train.Coordinator()
        tf.train.start_queue_runners(coord=coord, sess=sess)

        with sess.as_default():

            if pretrained_model:
                print('Restoring pretrained model: %s' % pretrained_model)
                saver.restore(sess, pretrained_model)

            # Training and validation loop
            print('Running training')
            nrof_steps = args.max_nrof_epochs*args.epoch_size
            nrof_val_samples = int(math.ceil(args.max_nrof_epochs / args.validate_every_n_epochs))   # Validate every validate_every_n_epochs as well as in the last epoch
            stat = {
                'loss': np.zeros((nrof_steps,), np.float32),
                'center_loss': np.zeros((nrof_steps,), np.float32),
                'reg_loss': np.zeros((nrof_steps,), np.float32),
                'xent_loss': np.zeros((nrof_steps,), np.float32),
                'prelogits_norm': np.zeros((nrof_steps,), np.float32),
                'accuracy': np.zeros((nrof_steps,), np.float32),
                'val_loss': np.zeros((nrof_val_samples,), np.float32),
                'val_xent_loss': np.zeros((nrof_val_samples,), np.float32),
                'val_accuracy': np.zeros((nrof_val_samples,), np.float32),
                'lfw_accuracy': np.zeros((args.max_nrof_epochs,), np.float32),
                'lfw_valrate': np.zeros((args.max_nrof_epochs,), np.float32),
                'learning_rate': np.zeros((args.max_nrof_epochs,), np.float32),
                'time_train': np.zeros((args.max_nrof_epochs,), np.float32),
                'time_validate': np.zeros((args.max_nrof_epochs,), np.float32),
                'time_evaluate': np.zeros((args.max_nrof_epochs,), np.float32),
                'prelogits_hist': np.zeros((args.max_nrof_epochs, 1000), np.float32),
              }
            for epoch in range(1,args.max_nrof_epochs+1):
                step = sess.run(global_step, feed_dict=None)
                # Train for one epoch
                t = time.time()
                # 训练模型
                cont = train(args, sess, epoch, image_list, label_list, index_dequeue_op, enqueue_op, image_paths_placeholder, labels_placeholder,
                    learning_rate_placeholder, phase_train_placeholder, batch_size_placeholder, control_placeholder, global_step, 
                    total_loss, train_op, summary_op, summary_writer, regularization_losses, args.learning_rate_schedule_file,
                    stat, cross_entropy_mean, accuracy, learning_rate,
                    prelogits, prelogits_center_loss, args.random_rotate, args.random_crop, args.random_flip, prelogits_norm, args.prelogits_hist_max, args.use_fixed_image_standardization)
                stat['time_train'][epoch-1] = time.time() - t
                
                if not cont:
                    break
                # 在测试数据上计算正确率  
                t = time.time()
                if len(val_image_list)>0 and ((epoch-1) % args.validate_every_n_epochs == args.validate_every_n_epochs-1 or epoch==args.max_nrof_epochs):
                    validate(args, sess, epoch, val_image_list, val_label_list, enqueue_op, image_paths_placeholder, labels_placeholder, control_placeholder,
                        phase_train_placeholder, batch_size_placeholder, 
                        stat, total_loss, regularization_losses, cross_entropy_mean, accuracy, args.validate_every_n_epochs, args.use_fixed_image_standardization)
                stat['time_validate'][epoch-1] = time.time() - t

                # Save variables and the metagraph if it doesn't exist already
                save_variables_and_metagraph(sess, saver, summary_writer, model_dir, subdir, epoch)

                # Evaluate on LFW
                t = time.time()
                if args.lfw_dir:
                    evaluate(sess, enqueue_op, image_paths_placeholder, labels_placeholder, phase_train_placeholder, batch_size_placeholder, control_placeholder, 
                        embeddings, label_batch, lfw_paths, actual_issame, args.lfw_batch_size, args.lfw_nrof_folds, log_dir, step, summary_writer, stat, epoch, 
                        args.lfw_distance_metric, args.lfw_subtract_mean, args.lfw_use_flipped_images, args.use_fixed_image_standardization)
                stat['time_evaluate'][epoch-1] = time.time() - t

                print('Saving statistics')
                with h5py.File(stat_file_name, 'w') as f:
                    for key, value in stat.items():
                        f.create_dataset(key, data=value)
    
    return model_dir
def main(args):

    network = importlib.import_module(args.model_def)

    np.random.seed(seed=args.seed)
    random.seed(args.seed)
    # load training dataset
    train_set = facenet.get_dataset(args.data_dir)

    if args.filter_min_nrof_images_per_class > 0:
        train_set = clean_dataset(train_set,
                                  args.filter_min_nrof_images_per_class)
    nrof_classes = len(train_set)

    pretrained_model = None
    if args.pretrained_model:
        pretrained_model = os.path.expanduser(args.pretrained_model)
        print('Pre-trained model: %s' % pretrained_model)
    # load lfw dataset for validation
    if args.lfw_dir:
        print('LFW directory: %s' % args.lfw_dir)
        # Read the file containing the pairs used for testing
        pairs = lfw.read_pairs(os.path.expanduser(args.lfw_pairs))
        # Get the paths for the corresponding images
        lfw_paths, actual_issame = lfw.get_paths(
            os.path.expanduser(args.lfw_dir), pairs, args.lfw_file_ext)

    with tf.Graph().as_default():
        tf.set_random_seed(args.seed)
        global_step = tf.Variable(0, trainable=False)

        # Get a list of image paths and their labels
        image_list, label_list = facenet.get_image_paths_and_labels(train_set)
        assert len(image_list) > 0, 'The dataset should not be empty'

        # Create a queue that produces indices into the image_list and label_list
        labels = ops.convert_to_tensor(label_list, dtype=tf.int32)
        range_size = array_ops.shape(labels)[0]
        with tf.device('/cpu:0'):

            index_queue = tf.train.range_input_producer(range_size,
                                                        num_epochs=None,
                                                        shuffle=True,
                                                        seed=None,
                                                        capacity=32)

            index_dequeue_op = index_queue.dequeue_many(
                args.batch_size * args.epoch_size, 'index_dequeue')

            learning_rate_placeholder = tf.placeholder(tf.float32,
                                                       name='learning_rate')

            phase_train_placeholder = tf.placeholder(tf.bool,
                                                     name='phase_train')

            image_paths_placeholder = tf.placeholder(tf.string,
                                                     shape=(None, 1),
                                                     name='image_paths')

            labels_placeholder = tf.placeholder(tf.int64,
                                                shape=(None, 1),
                                                name='labels')

            input_queue = data_flow_ops.FIFOQueue(capacity=1000000,
                                                  dtypes=[tf.string, tf.int64],
                                                  shapes=[(1, ), (1, )],
                                                  shared_name=None,
                                                  name=None)
            enqueue_op = input_queue.enqueue_many(
                [image_paths_placeholder, labels_placeholder],
                name='enqueue_op')

            nrof_preprocess_threads = args.nrof_preprocess_threads
            images_and_labels = []

            for _ in range(nrof_preprocess_threads):
                images_and_labels = distorted_inputs(images_and_labels,
                                                     input_queue, args)
            image_batch, label_batch = tf.train.batch_join(
                images_and_labels,
                batch_size=args.batch_size,
                enqueue_many=True,
                capacity=4 * nrof_preprocess_threads * args.batch_size,
                allow_smaller_final_batch=True)

            print(image_batch)
            # perfetching queue not working properly yet

            batch_queue = slim.prefetch_queue.prefetch_queue(
                [image_batch, label_batch], dynamic_pad=True, capacity=4)
            image_batch, label_batch = batch_queue.dequeue()

            image_batch = tf.identity(image_batch, 'image_batch')
            image_batch = tf.identity(image_batch, 'input')
            label_batch = tf.identity(label_batch, 'label_batch')

        print('Total number of classes: %d' % nrof_classes)
        print('Total number of examples: %d' % len(image_list))

        print('Building training graph')

        #///////////////////////////////////////////////////////////////////////////////////
        # Build the inference graph
        prelogits, _ = network.inference(
            image_batch,
            args.keep_probability,
            phase_train=phase_train_placeholder,
            bottleneck_layer_size=args.embedding_size,
            weight_decay=args.weight_decay,
            reuse=None)

        embeddings = tf.nn.l2_normalize(prelogits, 1, 1e-10, name='embeddings')

        print(embeddings)

        nrof_classes = len(train_set)

        weights = tf.get_variable(
            'softmax_weights',
            shape=(args.embedding_size, nrof_classes),
            dtype=tf.float32,
            initializer=tf.variance_scaling_initializer(),
            regularizer=slim.l2_regularizer(args.weight_decay),
            trainable=True)

        weights = tf.nn.l2_normalize(weights, 0, name='norm_weights')

        if args.keep_probability < 1.0:
            scaled_prelogits = slim.dropout(
                scaled_prelogits,
                args.keep_probability,
                is_training=phase_train_placeholder,
                scope='Dropout')

        logits = facenet.combined_loss(
            embeddings,
            label_batch,
            nrof_classes,
            weights,
            scale_factor=args.l2_constrained_scale_factor,
            m1=args.m1,
            m2=args.m2)

        # Add norm loss
        if args.norm_loss_factor > 0.0:
            norm_loss = args.norm_loss_factor * tf.reduce_mean(
                tf.pow(
                    tf.norm(prelogits, axis=1) -
                    args.l2_constrained_scale_factor, 2))
            tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES, norm_loss)

        learning_rate = tf.train.exponential_decay(
            learning_rate_placeholder,
            global_step,
            args.learning_rate_decay_epochs * args.epoch_size,
            args.learning_rate_decay_factor,
            staircase=True)
        tf.summary.scalar('learning_rate', learning_rate)

        # Calculate the average cross entropy loss across the batch
        cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(
            labels=label_batch,
            logits=logits,
            name='cross_entropy_per_example')
        cross_entropy_mean = tf.reduce_mean(cross_entropy,
                                            name='cross_entropy')
        tf.add_to_collection('losses', cross_entropy_mean)

        # Calculate the total losses
        regularization_losses = tf.get_collection(
            tf.GraphKeys.REGULARIZATION_LOSSES)
        total_loss = tf.add_n([cross_entropy_mean] + regularization_losses,
                              name='total_loss')

        # Build a Graph that trains the model with one batch of examples and updates the model parameters
        train_op = facenet.train(total_loss, global_step, args.optimizer,
                                 learning_rate, args.moving_average_decay,
                                 tf.trainable_variables(), args.num_gpus,
                                 args.log_histograms)
        #///////////////////////////////////////////////////////////////////////////////////

        # Create a saver
        if args.finetune:
            print("finetune model")
            all_vars = tf.trainable_variables()
            vars_to_restore = [
                v for v in all_vars if not v.name.startswith('Logits')
            ]
        else:
            vars_to_restore = tf.trainable_variables()

        saver = tf.train.Saver(vars_to_restore, max_to_keep=40)

        # Build the summary operation based on the TF collection of Summaries.
        summary_op = tf.summary.merge_all()

        # create corresponding model and log directories
        subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S')
        log_dir = os.path.join(os.path.expanduser(args.logs_base_dir), subdir)
        if not os.path.isdir(
                log_dir):  # Create the log directory if it doesn't exist
            os.makedirs(log_dir)
        model_dir = os.path.join(os.path.expanduser(args.models_base_dir),
                                 subdir)
        if not os.path.isdir(
                model_dir):  # Create the model directory if it doesn't exist
            os.makedirs(model_dir)
        print('Model directory: %s' % model_dir)
        print('Log directory: %s' % log_dir)

        # Write arguments to a text file
        facenet.write_arguments_to_file(
            args, os.path.join(model_dir, 'arguments.txt'))

        #=============================================================================================================
        # Start running operations on the Graph.
        gpu_options = tf.GPUOptions(
            per_process_gpu_memory_fraction=args.gpu_memory_fraction)
        sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options,
                                                allow_soft_placement=True,
                                                log_device_placement=False))
        sess.run(tf.global_variables_initializer())
        sess.run(tf.local_variables_initializer())
        save_graph_def(sess, model_dir)
        summary_writer = tf.summary.FileWriter(log_dir, sess.graph)
        coord = tf.train.Coordinator()
        tf.train.start_queue_runners(coord=coord, sess=sess)

        with sess.as_default():

            if pretrained_model:
                print('Restoring pretrained model: %s' % pretrained_model)
                saver.restore(sess, pretrained_model)

            # Training and validation loop
            print('Running training')
            epoch = 0
            while epoch < args.max_nrof_epochs:
                step = sess.run(global_step, feed_dict=None)
                epoch = step // args.epoch_size
                # Train for one epoch
                train(args, sess, epoch, image_list, label_list,
                      index_dequeue_op, enqueue_op, image_paths_placeholder,
                      labels_placeholder, learning_rate_placeholder,
                      phase_train_placeholder, global_step, total_loss,
                      train_op, summary_op, summary_writer,
                      regularization_losses, args.learning_rate_schedule_file,
                      learning_rate, log_dir)

                # Save variables and the metagraph if it doesn't exist already
                save_variables_and_metagraph(sess, saver, summary_writer,
                                             model_dir, subdir, step)

                # Evaluate on LFW
                if args.lfw_dir:
                    evaluate(sess, lfw_paths, actual_issame,
                             args.lfw_batch_size, args.lfw_nrof_folds, log_dir,
                             step, summary_writer)

    return model_dir
Beispiel #19
0
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
Beispiel #20
0
def main(args):
    # 导入 model_def 指代的网络结构
    network = importlib.import_module(args.model_def)

    subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S')
    log_dir = os.path.join(os.path.expanduser(args.logs_base_dir), subdir)
    if not os.path.isdir(
            log_dir):  # Create the log directory if it doesn't exist
        os.makedirs(log_dir)
    model_dir = os.path.join(os.path.expanduser(args.models_base_dir), subdir)
    if not os.path.isdir(model_dir):
        os.makedirs(model_dir)

    # 将 参数 写入 text 文件中
    facenet.write_arguments_to_file(args, os.path.join(log_dir,
                                                       'arguments.txt'))

    # 存储一些 git 修订信息到 log 文件夹的 text 文件中
    src_path, _ = os.path.split(os.path.realpath(__file__))
    facenet.store_revision_info(src_path, log_dir, ' '.join(sys.argv))

    np.random.seed(seed=args.seed)
    # 获取 训练数据集
    train_set = facenet.get_dataset(args.data_dir)

    # 打印 Model 存储目录 和 Log 存储目录
    print('Model directory: %s' % model_dir)
    print('Log directory: %s' % log_dir)
    # 检测是否 已经有训练完成的 model 了
    # if args.pretrained_model:
    #     print('Pre-trained model: %s' % os.path.expanduser(args.pretrained_model))

    # if args.lfw_dir:
    #     print('LFW directory: %s' % args.lfw_dir)
    #     # Read the file containing the pairs used for testing
    #     pairs = lfw.read_pairs(os.path.expanduser(args.lfw_pairs))
    #     # Get the paths for the corresponding images
    #     lfw_paths, actual_issame = lfw.get_paths(os.path.expanduser(args.lfw_dir), pairs)
    #     print('lfw_paths_len^^^^^^^^^^^^^^', len(lfw_paths))
    #     print('lfw_paths^^^^^^^^^^^^^^', lfw_paths)
    #     print('actual_issame_len^^^^^^^^^^', len(actual_issame))
    #     print('actual_issame^^^^^^^^^^', actual_issame)

    with tf.Graph().as_default():
        tf.set_random_seed(args.seed)
        global_step = tf.Variable(0, trainable=False)

        # Placeholder for the learning rate
        learning_rate_placeholder = tf.placeholder(tf.float32,
                                                   name='learning_rate')

        batch_size_placeholder = tf.placeholder(tf.int32, name='batch_size')

        phase_train_placeholder = tf.placeholder(tf.bool, name='phase_train')

        image_paths_placeholder = tf.placeholder(tf.string,
                                                 shape=(None, 3),
                                                 name='image_paths')

        labels_placeholder = tf.placeholder(tf.int64,
                                            shape=(None, 3),
                                            name='labels')

        input_queue = data_flow_ops.FIFOQueue(capacity=100000,
                                              dtypes=[tf.string, tf.int64],
                                              shapes=[(3, ), (3, )],
                                              shared_name=None,
                                              name=None)
        enqueue_op = input_queue.enqueue_many(
            [image_paths_placeholder, labels_placeholder])

        nrof_preprocess_threads = 4
        images_and_labels = []
        for _ in range(nrof_preprocess_threads):
            filenames, label = input_queue.dequeue()
            images = []
            for filename in tf.unstack(filenames):
                file_contents = tf.read_file(filename)
                image = tf.image.decode_image(file_contents, channels=3)

                if args.random_crop:
                    image = tf.random_crop(
                        image, [args.image_size, args.image_size, 3])
                else:
                    image = tf.image.resize_image_with_crop_or_pad(
                        image, args.image_size, args.image_size)
                if args.random_flip:
                    image = tf.image.random_flip_left_right(image)

                # pylint: disable=no-member
                image.set_shape((args.image_size, args.image_size, 3))
                images.append(tf.image.per_image_standardization(image))
            images_and_labels.append([images, label])
        # tf.train.batch_join() --- 运行 tensor list 来填充队列,以创建样本的批次。返回与 tensors_list[i] 有着相同数量和类型的张量的列的列表或者字典。
        image_batch, labels_batch = tf.train.batch_join(
            images_and_labels,
            batch_size=batch_size_placeholder,
            shapes=[(args.image_size, args.image_size, 3), ()],
            enqueue_many=True,
            capacity=4 * nrof_preprocess_threads * args.batch_size,
            allow_smaller_final_batch=True)
        # tf.identity(input, name=None) --- 返回一个与 input 具有相同 shape 和 内容的 tensor
        image_batch = tf.identity(image_batch, 'image_batch')
        image_batch = tf.identity(image_batch, 'input')
        labels_batch = tf.identity(labels_batch, 'label_batch')

        # 首先在 一个 gpu 上运行 network 的 inference graph
        with tf.device('/cpu:0'):
            embeddings = []
            anchors = []
            positives = []
            negatives = []
        # 在 gpu 0 上进行运行 inference graph
        with tf.device('/gpu:2'):
            # 创建 inference graph
            prelogits, _ = network.inference(
                image_batch,
                args.keep_probability,
                phase_train=phase_train_placeholder,
                bottleneck_layer_size=args.embedding_size,
                weight_decay=args.weight_decay)
            # l2 normalize
            embeddings = tf.nn.l2_normalize(prelogits,
                                            1,
                                            1e-10,
                                            name='embeddings')
            # ------ print start -----------
            print('embeddings-------', embeddings)
            # ------ print end -------------
            # Split embedding into anchor, positive and negative and calculate teiplet loss
            anchor, positive, negative = tf.unstack(
                tf.reshape(embeddings, [-1, 3, args.embedding_size]), 3, 1)
            # ------------------- print start ---------------------------------
            # print('@@@@@@@@@@@@wwww', anchor.get_shape())
            # print('############wwww', positive.get_shape())
            # print('$$$$$$$$$$$$wwww', negative.get_shape())
            # ------------------- print end -----------------------------------

            # 接着进行拆分,将 anchor, positive, negative 三组数据进行拆分,拆分成对应着 num_gpus 的份数
            # 但是这里有一个限制,所切分的 tensor 的维度,必须可以被 切分成的份数 整除, 所以直接使用 tf.split() 会报错

            for i in range(args.num_gpus):
                anchors_tmp = anchor[i::args.num_gpus]
                anchors.append(anchors_tmp)
                positives_tmp = positive[i::args.num_gpus]
                positives.append(positives_tmp)
                negatives_tmp = negative[i::args.num_gpus]
                negatives.append(negatives_tmp)

        # -------print start 查看 emdedding 和 相对应的 3 个 anchors,positive,negative
        # print('wowowowoowowow', embeddings.get_shape())
        # print('wowninininini_anchors0', anchors[0].get_shape())
        # print('wowninininini_anchors1', anchors[1].get_shape())
        # print('wowninininini_positives0', positives[0].get_shape())
        # print('wowninininini_positives1', positives[1].get_shape())
        # print('wowninininini_negatives0', negatives[0].get_shape())
        # print('wowninininini_negatives1', negatives[1].get_shape())
        # ------ print end -------------------------
        # 在这部分修改为 multi-gpu 训练
        # 即 将每一个 batch 均分,然后在多个 gpu 上来计算对应的 triplet_loss ,之后汇总得到和,求取平均,得到一个 batch_size 的 loss
        # tower_losses = []
        # tower_triplets = []
        # tower_reg = []
        # for i in range(args.num_gpus):
        #     with tf.device("/gpu:" + str(i)):
        #         with tf.name_scope("tower_" + str(i)) as scope:
        #             with tf.variable_scope(tf.get_variable_scope()) as var_scope:
        #                 triplet_loss_split = facenet.triplet_loss(anchors[i], positive[i], negative[i], args.alpha)
        #                 regularization_loss = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES)
        #                 tower_triplets.append(triplet_loss_split)
        #                 loss = triplet_loss_split + tf.add_n(regularization_loss)
        #                 tower_losses.append(loss)
        #                 tower_reg.append(regularization_loss)
        # # 计算 multi gpu 运行完成得到的 loss
        # total_loss = tf.reduce_mean(tower_losses)
        # total_reg = tf.reduce_mean(tower_reg)
        # losses = {}
        # losses['total_loss'] = total_loss
        # losses['total_reg'] = total_reg

        # # 创建 inference graph
        # prelogits, _ = network.inference(image_batch, args.keep_probability,
        #     phase_train=phase_train_placeholder, bottleneck_layer_size=args.embedding_size,
        #     weight_decay=args.weight_decay)

        # embeddings = tf.nn.l2_normalize(prelogits, 1, 1e-10, name='embeddings')
        # # Split embedding into anchor, positive and negative and calculate teiplet loss
        # anchor, positive, negative = tf.unstack(tf.reshape(embeddings, [-1, 3, args.embedding_size]), 3, 1)

        learning_rate = tf.train.exponential_decay(
            learning_rate_placeholder,
            global_step,
            args.learning_rate_decay_epochs * args.epoch_size,
            args.learning_rate_decay_factor,
            staircase=True)
        tf.summary.scalar('learning_rate', learning_rate)

        # # 计算 total losses
        # regularization_losses = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES)
        # total_loss = tf.add_n([triplet_loss] + regularization_losses, name='total_loss')

        # 创建 使用 1 个 batch 来训练模型并更新其中参数的 Graph
        # train_op = facenet.train(total_loss, global_step, args.optimizer,
        # learning_rate, args.moving_average_decay, tf.global_variables())

        # 在多 gpu 上训练的改版
        train_op, total_loss = facenet.train_multi_gpu(
            args.num_gpus, anchors, positives, negatives, args.alpha,
            global_step, args.optimizer, learning_rate,
            args.moving_average_decay, tf.global_variables())

        # Create a saver
        saver = tf.train.Saver(tf.trainable_variables(), max_to_keep=3)

        # 基于 TF Summaries 的 collection 创建一个 summary opration
        summary_op = tf.summary.merge_all()

        # 在 Graph 启动 running operations
        gpu_options = tf.GPUOptions(
            per_process_gpu_memory_fraction=args.gpu_memory_fraction)
        sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options,
                                                allow_soft_placement=True))

        # 初始化 variables
        sess.run(tf.global_variables_initializer(),
                 feed_dict={phase_train_placeholder: True})
        sess.run(tf.local_variables_initializer(),
                 feed_dict={phase_train_placeholder: True})

        summary_writer = tf.summary.FileWriter(log_dir, sess.graph)
        coord = tf.train.Coordinator()
        tf.train.start_queue_runners(coord=coord, sess=sess)

        with sess.as_default():

            # if args.pretrained_model:
            #     print('Restoring pretrained model: %s' % args.pretrained_model)
            #     saver.restore(sess, os.path.expanduser(args.pretrained_model))
            # facenet.load_model(args.pretrained_model)

            #Training and validation loop
            epoch = 0
            while epoch < args.max_nrof_epochs:
                step = sess.run(global_step, feed_dict=None)
                epoch = step // args.epoch_size
                # Train for one epoch
                # --- print start ---
                print('@@@@@@@@@@@@@@args.embedding_size', args.embedding_size)
                print('@@@@@@@@@@@@@@anchor', anchor, anchor.get_shape())
                print('@@@@@@@@@@@@@@positive', positive, positive.get_shape())
                print('@@@@@@@@@@@@@@negative', negative, negative.get_shape())
                print('@@@@@@@@@@@@@@total_loss', total_loss,
                      total_loss.get_shape())
                # --- print end -----

                epoch_start_time = time.time()
                # origin
                # train(args, sess, train_set, epoch, image_paths_placeholder, labels_placeholder, labels_batch,
                #         batch_size_placeholder, learning_rate_placeholder, phase_train_placeholder, enqueue_op, input_queue, global_step,
                #         embeddings, total_loss, train_op, summary_op, summary_writer, args.learning_rate_schedule_file,
                #         args.embedding_size, anchor, positive, negative, total_loss)
                # print('第 %d 个 epoch跑完,花费时间 %.3f' %(epoch, (time.time() - epoch_start_time)))

                # modified training
                train_multi_gpus(
                    args, sess, train_set, epoch, image_paths_placeholder,
                    labels_placeholder, labels_batch, batch_size_placeholder,
                    learning_rate_placeholder, phase_train_placeholder,
                    enqueue_op, input_queue, global_step, embeddings, anchors,
                    positives, negatives, train_op, summary_op, summary_writer,
                    args.learning_rate_schedule_file, args.embedding_size)
                print('第 %d 个 epoch跑完,花费时间 %.3f' %
                      (epoch, (time.time() - epoch_start_time)))

                # Save variables and the metagraph if it doesn't exist already
                save_variables_and_metagraph(sess, saver, summary_writer,
                                             model_dir, subdir, step)

                # Evaluate on LFW
                # if args.lfw_dir:
                #     evaluate(sess, lfw_paths, embeddings, labels_batch, image_paths_placeholder, labels_placeholder,
                #                 batch_size_placeholder, learning_rate_placeholder, phase_train_placeholder, enqueue_op, actual_issame, args.batch_size,
                #                 args.lfw_nrof_folds, log_dir, step, summary_writer, args.embedding_size)

    return model_dir
Beispiel #21
0
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
Beispiel #22
0
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
Beispiel #23
0
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
Beispiel #24
0
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
Beispiel #25
0
def main(args):
    os.environ["CUDA_VISIBLE_DEVICES"] = args.gpu
    if args.cluster:
        hvd.init()
        rank = hvd.rank()
        subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S')
        log_dir = os.path.join(os.path.expanduser(args.logs_base_dir),
                               subdir + '_' + str(rank))
        if not os.path.isdir(
                log_dir):  # Create the log directory if it doesn't exist
            os.makedirs(log_dir)
        set_logger(logger, log_dir)
        if rank == 0:
            model_dir = os.path.join(os.path.expanduser(args.models_base_dir),
                                     subdir)
            if not os.path.isdir(
                    model_dir
            ):  # Create the model directory if it doesn't exist
                os.makedirs(model_dir)
            # Write arguments to a text file
            facenet.write_arguments_to_file(
                args, os.path.join(log_dir, 'arguments.txt'))
            # Store some git revision info in a text file in the log directory
            src_path, _ = os.path.split(os.path.realpath(__file__))
            facenet.store_revision_info(src_path, log_dir, ' '.join(sys.argv))
            np.random.seed(seed=rank)
            logger.info('Model directory: %s' % model_dir)
            logger.info('Log directory: %s' % log_dir)

    else:
        subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S')
        log_dir = os.path.join(os.path.expanduser(args.logs_base_dir), subdir)
        if not os.path.isdir(
                log_dir):  # Create the log directory if it doesn't exist
            os.makedirs(log_dir)
        set_logger(logger, log_dir)
        model_dir = os.path.join(os.path.expanduser(args.models_base_dir),
                                 subdir)
        if not os.path.isdir(
                model_dir):  # Create the model directory if it doesn't exist
            os.makedirs(model_dir)
        # Write arguments to a text file
        facenet.write_arguments_to_file(args,
                                        os.path.join(log_dir, 'arguments.txt'))
        # Store some git revision info in a text file in the log directory
        src_path, _ = os.path.split(os.path.realpath(__file__))
        facenet.store_revision_info(src_path, log_dir, ' '.join(sys.argv))
        np.random.seed(seed=args.seed)
        logger.info('Model directory: %s' % model_dir)
        logger.info('Log directory: %s' % log_dir)

    logger.info("train_tripletloss......")
    # supervised_dataset, unsupervised_dataset = dataset.get_dataset(args.data_dir, args.data_source)
    supervised_dataset = dataset.get_supervised_dataset(
        args.data_dir, args.data_source, args.images_per_person)
    unsupervised_dataset = {}
    if args.data_source == 'MULTIPLE' and args.unsupervised != 'NONE':
        unsupervised_dataset = dataset.get_dataset(args.data_dir,
                                                   args.data_source)
    # logger.debug("supervised_dataset: %s, unsupervised_dataset: %s" % (supervised_dataset, unsupervised_dataset))
    # logger.debug("supervised_dataset['id']: %d" % (len(supervised_dataset['id'])))
    # logger.debug("supervised_dataset['camera']: %d" % (len(supervised_dataset['camera'])))
    # logger.debug("supervised_dataset['id+camera']: %d" % (len(supervised_dataset['id+camera'])))

    if args.pretrained_model:
        logger.info('Pre-trained model: %s' %
                    os.path.expanduser(args.pretrained_model))

    if args.lfw_dir:
        logger.info('LFW directory: %s' % args.lfw_dir)
        # Read the file containing the pairs used for testing
        pairs = lfw.read_pairs(os.path.expanduser(args.lfw_pairs))
        # Get the paths for the corresponding images
        lfw_paths, lfw_actual_issame = lfw.get_paths(
            os.path.expanduser(args.lfw_dir), pairs, args.lfw_file_ext)
        # dataset = facenet.get_dataset(args.lfw_dir)
        # lfw_image_list, lfw_label_list = facenet.get_image_paths_and_labels(dataset)
    if args.val_dir:
        logger.info('val directory: %s' % args.val_dir)
        val_lfw_pairs = lfw.read_pairs(os.path.expanduser(args.val_pairs))
        # Get the paths for the corresponding images
        val_paths, val_actual_issame = lfw.get_paths(
            os.path.expanduser(args.val_dir), val_lfw_pairs, args.lfw_file_ext)
        # dataset = facenet.get_dataset(args.val_dir)
        # val_image_list, val_label_list = facenet.get_image_paths_and_labels(dataset)
        # META_FILE = "face_meta.tsv"
        # path_for_metadata = os.path.join(log_dir, META_FILE)
        # with open(path_for_metadata, 'w') as f:
        #     f.write("Index\tLabel\n")
        #     for index, label in enumerate(val_label_list):
        #         f.write("%d\t%d\n" % (index, label))

    with tf.Graph().as_default():
        tf.set_random_seed(args.seed)
        global_step = tf.Variable(0, trainable=False, name='global_step')

        # Placeholder for the learning rate
        learning_rate_placeholder = tf.placeholder(tf.float32,
                                                   name='learning_rate')
        batch_size_placeholder = tf.placeholder(tf.int32, name='batch_size')
        phase_train_placeholder = tf.placeholder(tf.bool, name='phase_train')
        image_paths_placeholder = tf.placeholder(tf.string,
                                                 shape=(None, 3),
                                                 name='image_paths')
        labels_placeholder = tf.placeholder(tf.int64,
                                            shape=(None, 3),
                                            name='labels')
        data_augmentations_placeholder = tf.placeholder(
            tf.int64, shape=(None, 3), name='data_augmentations')
        source_image_paths_placeholder = tf.placeholder(
            tf.string, shape=(None, 1), name='source_image_paths')
        target_image_paths_placeholder = tf.placeholder(
            tf.string, shape=(None, 1), name='target_image_paths')

        input_queue = data_flow_ops.FIFOQueue(
            capacity=100000,
            dtypes=[tf.string, tf.int64, tf.int64],
            shapes=[(3, ), (3, ), (3, )],
            shared_name=None,
            name=None)
        enqueue_op = input_queue.enqueue_many([
            image_paths_placeholder, labels_placeholder,
            data_augmentations_placeholder
        ])
        image_batch, labels_batch = dataset.create_input_pipeline(
            input_queue, args, batch_size_placeholder)
        image_batch = tf.identity(image_batch, 'image_batch')
        image_batch = tf.identity(image_batch, 'input')
        labels_batch = tf.identity(labels_batch, 'label_batch')
        network = importlib.import_module(args.model_def)
        prelogits, _ = network.inference(
            image_batch,
            args.keep_probability,
            phase_train=phase_train_placeholder,
            bottleneck_layer_size=args.embedding_size,
            weight_decay=args.weight_decay)
        embeddings = tf.nn.l2_normalize(prelogits, 1, 1e-10, name='embeddings')
        triplet = Triplet(args.max_triplet_per_select)
        triplet_loss = triplet.triplet_loss(embeddings, args.embedding_size,
                                            args.alpha)
        domain_adaptation_loss = tf.constant(0.0)
        domain_enqueue_op = None
        if args.data_source == 'MULTIPLE' and args.unsupervised != 'NONE':
            # begin: domain adaptation loss
            domain_input_queue = data_flow_ops.FIFOQueue(
                capacity=100000,
                dtypes=[tf.string, tf.string],
                shapes=[(1, ), (1, )],
                shared_name=None,
                name=None)
            domain_enqueue_op = domain_input_queue.enqueue_many(
                [
                    source_image_paths_placeholder,
                    target_image_paths_placeholder
                ],
                name='domain_enqueue_op')
            source_image_batch, target_image_batch = dataset.create_domain_input_pipeline(
                domain_input_queue, args, batch_size_placeholder)
            source_image_batch = tf.identity(source_image_batch,
                                             'source_image_batch')
            target_image_batch = tf.identity(target_image_batch,
                                             'target_image_batch')
            source_prelogits, source_end_points = network.inference(
                source_image_batch,
                args.keep_probability,
                phase_train=phase_train_placeholder,
                bottleneck_layer_size=args.embedding_size,
                weight_decay=args.weight_decay,
                reuse=True)
            target_prelogits, target_end_points = network.inference(
                target_image_batch,
                args.keep_probability,
                phase_train=phase_train_placeholder,
                bottleneck_layer_size=args.embedding_size,
                weight_decay=args.weight_decay,
                reuse=True)
            # multiplier 1.0 may not be the best
            if args.unsupervised == 'MMD':
                domain_adaptation_loss = 1.0 * losses.mmd_loss(
                    source_end_points['PreLogitsFlatten'],
                    target_end_points['PreLogitsFlatten'], 1.0)
            elif args.unsupervised == 'DANN':
                domain_adaptation_loss = 0.1 * losses.dann_loss(
                    source_end_points['PreLogitsFlatten'],
                    target_end_points['PreLogitsFlatten'], 1.0)
            tf.add_to_collection('losses', domain_adaptation_loss)
            # end: domain adaptation loss

        regularization_losses = tf.get_collection(
            tf.GraphKeys.REGULARIZATION_LOSSES)
        total_loss = tf.add_n([triplet_loss] + [domain_adaptation_loss] +
                              regularization_losses,
                              name='total_loss')

        learning_rate = get_learning_rate(args, learning_rate_placeholder,
                                          global_step)
        tf.summary.scalar('learning_rate', learning_rate)
        # # Build a Graph that trains the model with one batch of examples and updates the model parameters
        # train_op = facenet.train(total_loss, global_step, args.optimizer,
        #     learning_rate, args.moving_average_decay, args.cluster, args.nrof_warmup_epochs)
        # split train into 2 parts: compute gradient and apply gradient
        trained_vars = tf.trainable_variables()
        # for var in trained_vars:
        #     logger.debug(var)
        opt = facenet.get_optimizer(args.optimizer, learning_rate,
                                    args.cluster)
        grads_and_vars = facenet.compute_gradients(opt, total_loss)
        # grads = facenet.compute_gradients_excluding_vars(total_loss)
        grads, vars = zip(*grads_and_vars)
        grads = [
            g if g is not None else tf.zeros_like(v)
            for g, v in zip(grads, vars)
        ]
        gradient_placeholder = [
            tf.placeholder(tf.float32) for _ in xrange(len(trained_vars))
        ]
        apply_gradient_op = facenet.apply_gradients(
            opt, zip(gradient_placeholder, trained_vars), global_step,
            args.moving_average_decay)

        # Create a saver
        saver = tf.train.Saver(tf.trainable_variables(), max_to_keep=100)
        # Build the summary operation based on the TF collection of Summaries.
        summary_op = tf.summary.merge_all()

        # Start running operations on the Graph.
        # gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=args.gpu_memory_fraction)
        # sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options))
        config = tf.ConfigProto()
        config.gpu_options.allow_growth = True
        if args.cluster:
            # Pin GPU to be used to process local rank (one GPU per process)
            config.gpu_options.visible_device_list = str(hvd.local_rank())
        sess = tf.Session(config=config)

        # Initialize variables
        sess.run(tf.global_variables_initializer(),
                 feed_dict={phase_train_placeholder: True})
        sess.run(tf.local_variables_initializer(),
                 feed_dict={phase_train_placeholder: True})
        if args.cluster:
            sess.run(hvd.broadcast_global_variables(0))

        summary_writer = tf.summary.FileWriter(log_dir, sess.graph)
        coord = tf.train.Coordinator()
        tf.train.start_queue_runners(coord=coord, sess=sess)

        with sess.as_default():
            epoch = 0
            if args.pretrained_model:
                logger.info('Restoring pretrained model: %s' %
                            args.pretrained_model)
                saver.restore(sess, os.path.expanduser(args.pretrained_model))
                if args.lfw_dir:
                    evaluate(sess, lfw_paths, embeddings, labels_batch,
                             image_paths_placeholder, labels_placeholder,
                             data_augmentations_placeholder,
                             batch_size_placeholder, learning_rate_placeholder,
                             phase_train_placeholder, enqueue_op,
                             lfw_actual_issame, args.batch_size,
                             args.lfw_nrof_folds, log_dir, 'lfw_raw', epoch,
                             summary_writer, args.embedding_size)
                if args.val_dir:
                    evaluate(sess, val_paths, embeddings, labels_batch,
                             image_paths_placeholder, labels_placeholder,
                             data_augmentations_placeholder,
                             batch_size_placeholder, learning_rate_placeholder,
                             phase_train_placeholder, enqueue_op,
                             val_actual_issame, args.batch_size,
                             args.lfw_nrof_folds, log_dir, 'val_raw', epoch,
                             summary_writer, args.embedding_size)

            # Training and validation loop
            while epoch < args.max_nrof_epochs:
                step = sess.run(global_step, feed_dict=None)
                # epoch = step // args.epoch_size
                # Train for one epoch
                triplet.train(
                    image_batch, args, sess, args.data_source,
                    args.unsupervised, supervised_dataset,
                    unsupervised_dataset, epoch, image_paths_placeholder,
                    labels_placeholder, data_augmentations_placeholder,
                    source_image_paths_placeholder,
                    target_image_paths_placeholder, labels_batch,
                    batch_size_placeholder, learning_rate_placeholder,
                    phase_train_placeholder, enqueue_op, domain_enqueue_op,
                    global_step, embeddings, total_loss, opt, grads,
                    gradient_placeholder, apply_gradient_op, summary_op,
                    summary_writer, args.learning_rate_schedule_file,
                    args.embedding_size, triplet_loss, domain_adaptation_loss,
                    log_dir)

                if (args.cluster and rank == 0) or not args.cluster:
                    # Save variables and the metagraph if it doesn't exist already
                    # save_variables_and_metagraph(sess, saver, summary_writer, model_dir, subdir, step)
                    save_variables_and_metagraph(sess, saver, summary_writer,
                                                 model_dir, subdir, epoch)

                if args.lfw_dir:
                    evaluate(sess, lfw_paths, embeddings, labels_batch,
                             image_paths_placeholder, labels_placeholder,
                             data_augmentations_placeholder,
                             batch_size_placeholder, learning_rate_placeholder,
                             phase_train_placeholder, enqueue_op,
                             lfw_actual_issame, args.batch_size,
                             args.lfw_nrof_folds, log_dir, 'lfw', epoch,
                             summary_writer, args.embedding_size)

                if args.val_dir:
                    evaluate(sess, val_paths, embeddings, labels_batch,
                             image_paths_placeholder, labels_placeholder,
                             data_augmentations_placeholder,
                             batch_size_placeholder, learning_rate_placeholder,
                             phase_train_placeholder, enqueue_op,
                             val_actual_issame, args.batch_size,
                             args.lfw_nrof_folds, log_dir, 'val', epoch,
                             summary_writer, args.embedding_size)
                epoch += 1

    return model_dir
def main(args):
  
    network = importlib.import_module(args.model_def)

    subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S')
    log_dir = os.path.join(os.path.expanduser(args.logs_base_dir), subdir)
    if not os.path.isdir(log_dir):  # Create the log directory if it doesn't exist
        os.makedirs(log_dir)
    model_dir = os.path.join(os.path.expanduser(args.models_base_dir), subdir)
    if not os.path.isdir(model_dir):  # Create the model directory if it doesn't exist
        os.makedirs(model_dir)

    # Write arguments to a text file
    facenet.write_arguments_to_file(args, os.path.join(log_dir, 'arguments.txt'))
        
    # Store some git revision info in a text file in the log directory
    src_path,_ = os.path.split(os.path.realpath(__file__))
    facenet.store_revision_info(src_path, log_dir, ' '.join(sys.argv))

    np.random.seed(seed=args.seed)
    train_set = facenet.get_dataset(args.data_dir)
    
    print('Model directory: %s' % model_dir)
    print('Log directory: %s' % log_dir)
    if args.pretrained_model:
        print('Pre-trained model: %s' % os.path.expanduser(args.pretrained_model))
    
    if args.lfw_dir:
        print('LFW directory: %s' % args.lfw_dir)
        # Read the file containing the pairs used for testing
        pairs = lfw.read_pairs(os.path.expanduser(args.lfw_pairs))
        # Get the paths for the corresponding images
        lfw_paths, actual_issame = lfw.get_paths(os.path.expanduser(args.lfw_dir), pairs, args.lfw_file_ext)
        
    
    with tf.Graph().as_default():
        tf.set_random_seed(args.seed)
        global_step = tf.Variable(0, trainable=False)

        # Placeholder for the learning rate
        learning_rate_placeholder = tf.placeholder(tf.float32, name='learning_rate')
        
        batch_size_placeholder = tf.placeholder(tf.int32, name='batch_size')
        
        phase_train_placeholder = tf.placeholder(tf.bool, name='phase_train')
        
        image_paths_placeholder = tf.placeholder(tf.string, shape=(None,3), name='image_paths')
        labels_placeholder = tf.placeholder(tf.int64, shape=(None,3), name='labels')
        
        input_queue = data_flow_ops.FIFOQueue(capacity=100000,
                                    dtypes=[tf.string, tf.int64],
                                    shapes=[(3,), (3,)],
                                    shared_name=None, name=None)
        enqueue_op = input_queue.enqueue_many([image_paths_placeholder, labels_placeholder])
        
        nrof_preprocess_threads = 4
        images_and_labels = []
        for _ in range(nrof_preprocess_threads):
            filenames, label = input_queue.dequeue()
            images = []
            for filename in tf.unstack(filenames):
                file_contents = tf.read_file(filename)
                image = tf.image.decode_image(file_contents, channels=3)
                
                if args.random_crop:
                    image = tf.random_crop(image, [args.image_size, args.image_size, 3])
                else:
                    image = tf.image.resize_image_with_crop_or_pad(image, args.image_size, args.image_size)
                if args.random_flip:
                    image = tf.image.random_flip_left_right(image)
    
                #pylint: disable=no-member
                image.set_shape((args.image_size, args.image_size, 3))
                images.append(tf.image.per_image_standardization(image))
            images_and_labels.append([images, label])
    
        image_batch, labels_batch = tf.train.batch_join(
            images_and_labels, batch_size=batch_size_placeholder, 
            shapes=[(args.image_size, args.image_size, 3), ()], enqueue_many=True,
            capacity=4 * nrof_preprocess_threads * args.batch_size,
            allow_smaller_final_batch=True)
        image_batch = tf.identity(image_batch, 'image_batch')
        image_batch = tf.identity(image_batch, 'input')
        labels_batch = tf.identity(labels_batch, 'label_batch')

        # Build the inference graph
        prelogits, _ = network.inference(image_batch, args.keep_probability, 
            phase_train=phase_train_placeholder, bottleneck_layer_size=args.embedding_size,
            weight_decay=args.weight_decay)
        
        embeddings = tf.nn.l2_normalize(prelogits, 1, 1e-10, name='embeddings')
        # Split embeddings into anchor, positive and negative and calculate triplet loss
        anchor, positive, negative = tf.unstack(tf.reshape(embeddings, [-1,3,args.embedding_size]), 3, 1)
        triplet_loss = facenet.triplet_loss(anchor, positive, negative, args.alpha)
        
        learning_rate = tf.train.exponential_decay(learning_rate_placeholder, global_step,
            args.learning_rate_decay_epochs*args.epoch_size, args.learning_rate_decay_factor, staircase=True)
        tf.summary.scalar('learning_rate', learning_rate)

        # Calculate the total losses
        regularization_losses = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES)
        total_loss = tf.add_n([triplet_loss] + regularization_losses, name='total_loss')

        # Build a Graph that trains the model with one batch of examples and updates the model parameters
        train_op = facenet.train(total_loss, global_step, args.optimizer, 
            learning_rate, args.moving_average_decay, tf.global_variables())
        
        # Create a saver
        saver = tf.train.Saver(tf.trainable_variables(), max_to_keep=3)

        # Build the summary operation based on the TF collection of Summaries.
        summary_op = tf.summary.merge_all()

        # Start running operations on the Graph.
        gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=args.gpu_memory_fraction)
        sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options))        

        # Initialize variables
        sess.run(tf.global_variables_initializer(), feed_dict={phase_train_placeholder:True})
        sess.run(tf.local_variables_initializer(), feed_dict={phase_train_placeholder:True})

        summary_writer = tf.summary.FileWriter(log_dir, sess.graph)
        coord = tf.train.Coordinator()
        tf.train.start_queue_runners(coord=coord, sess=sess)

        with sess.as_default():

            if args.pretrained_model:
                print('Restoring pretrained model: %s' % args.pretrained_model)
                saver.restore(sess, os.path.expanduser(args.pretrained_model))

            # Training and validation loop
            epoch = 0
            while epoch < args.max_nrof_epochs:
                step = sess.run(global_step, feed_dict=None)
                epoch = step // args.epoch_size
                # Train for one epoch
                train(args, sess, train_set, epoch, image_paths_placeholder, labels_placeholder, labels_batch,
                    batch_size_placeholder, learning_rate_placeholder, phase_train_placeholder, enqueue_op, input_queue, global_step, 
                    embeddings, total_loss, train_op, summary_op, summary_writer, args.learning_rate_schedule_file,
                    args.embedding_size, anchor, positive, negative, triplet_loss)

                # Save variables and the metagraph if it doesn't exist already
                save_variables_and_metagraph(sess, saver, summary_writer, model_dir, subdir, step)

                # Evaluate on LFW
                if args.lfw_dir:
                    evaluate(sess, lfw_paths, embeddings, labels_batch, image_paths_placeholder, labels_placeholder, 
                            batch_size_placeholder, learning_rate_placeholder, phase_train_placeholder, enqueue_op, actual_issame, args.batch_size, 
                            args.lfw_nrof_folds, log_dir, step, summary_writer, args.embedding_size)

    return model_dir
Beispiel #27
0
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
Beispiel #28
0
def main(args):
  
    network = importlib.import_module(args.model_def)

    subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S')
    log_dir = os.path.join(os.path.expanduser(args.logs_base_dir), subdir)
    if not os.path.isdir(log_dir):  # Create the log directory if it doesn't exist
        os.makedirs(log_dir)
    model_dir = os.path.join(os.path.expanduser(args.models_base_dir), subdir)
    if not os.path.isdir(model_dir):  # Create the model directory if it doesn't exist
        os.makedirs(model_dir)

    # Write arguments to a text file
    facenet.write_arguments_to_file(args, os.path.join(log_dir, 'arguments.txt'))
        
    # Store some git revision info in a text file in the log directory
    src_path,_ = os.path.split(os.path.realpath(__file__))
    facenet.store_revision_info(src_path, log_dir, ' '.join(sys.argv))

    np.random.seed(seed=args.seed)
    random.seed(args.seed)
    train_set = facenet.get_dataset(args.data_dir)
    if args.filter_filename:
        train_set = filter_dataset(train_set, os.path.expanduser(args.filter_filename), 
            args.filter_percentile, args.filter_min_nrof_images_per_class)
    nrof_classes = len(train_set)
    
    print('Model directory: %s' % model_dir)
    print('Log directory: %s' % log_dir)
    pretrained_model = None
    if args.pretrained_model:
        pretrained_model = os.path.expanduser(args.pretrained_model)
        print('Pre-trained model: %s' % pretrained_model)
    
    if args.lfw_dir:
        print('LFW directory: %s' % args.lfw_dir)
        # Read the file containing the pairs used for testing
        pairs = lfw.read_pairs(os.path.expanduser(args.lfw_pairs))
        # Get the paths for the corresponding images
        lfw_paths, actual_issame = lfw.get_paths(os.path.expanduser(args.lfw_dir), pairs, args.lfw_file_ext)
    
    with tf.Graph().as_default():
        tf.set_random_seed(args.seed)
        global_step = tf.Variable(0, trainable=False)
        
        # Get a list of image paths and their labels
        image_list, label_list = facenet.get_image_paths_and_labels(train_set)
        assert len(image_list)>0, 'The dataset should not be empty'
        
        # Create a queue that produces indices into the image_list and label_list 
        labels = ops.convert_to_tensor(label_list, dtype=tf.int32)
        range_size = array_ops.shape(labels)[0]
        index_queue = tf.train.range_input_producer(range_size, num_epochs=None,
                             shuffle=True, seed=None, capacity=32)
        
        index_dequeue_op = index_queue.dequeue_many(args.batch_size*args.epoch_size, 'index_dequeue')
        
        learning_rate_placeholder = tf.placeholder(tf.float32, name='learning_rate')

        batch_size_placeholder = tf.placeholder(tf.int32, name='batch_size')
        
        phase_train_placeholder = tf.placeholder(tf.bool, name='phase_train')
        
        image_paths_placeholder = tf.placeholder(tf.string, shape=(None,1), name='image_paths')

        labels_placeholder = tf.placeholder(tf.int64, shape=(None,1), name='labels')
        
        input_queue = data_flow_ops.FIFOQueue(capacity=100000,
                                    dtypes=[tf.string, tf.int64],
                                    shapes=[(1,), (1,)],
                                    shared_name=None, name=None)
        enqueue_op = input_queue.enqueue_many([image_paths_placeholder, labels_placeholder], name='enqueue_op')
        
        nrof_preprocess_threads = 4
        images_and_labels = []
        for _ in range(nrof_preprocess_threads):
            filenames, label = input_queue.dequeue()
            images = []
            for filename in tf.unstack(filenames):
                file_contents = tf.read_file(filename)
                image = tf.image.decode_image(file_contents, channels=3)
                if args.random_rotate:
                    image = tf.py_func(facenet.random_rotate_image, [image], tf.uint8)
                if args.random_crop:
                    image = tf.random_crop(image, [args.image_size, args.image_size, 3])
                else:
                    image = tf.image.resize_image_with_crop_or_pad(image, args.image_size, args.image_size)
                if args.random_flip:
                    image = tf.image.random_flip_left_right(image)
    
                #pylint: disable=no-member
                image.set_shape((args.image_size, args.image_size, 3))
                images.append(tf.image.per_image_standardization(image))
            images_and_labels.append([images, label])
    
        image_batch, label_batch = tf.train.batch_join(
            images_and_labels, batch_size=batch_size_placeholder, 
            shapes=[(args.image_size, args.image_size, 3), ()], enqueue_many=True,
            capacity=4 * nrof_preprocess_threads * args.batch_size,
            allow_smaller_final_batch=True)
        image_batch = tf.identity(image_batch, 'image_batch')
        image_batch = tf.identity(image_batch, 'input')
        label_batch = tf.identity(label_batch, 'label_batch')
        
        print('Total number of classes: %d' % nrof_classes)
        print('Total number of examples: %d' % len(image_list))
        
        print('Building training graph')
        
        # Build the inference graph
        prelogits, _ = network.inference(image_batch, args.keep_probability, 
            phase_train=phase_train_placeholder, bottleneck_layer_size=args.embedding_size, 
            weight_decay=args.weight_decay)
        logits = slim.fully_connected(prelogits, len(train_set), activation_fn=None, 
                weights_initializer=tf.truncated_normal_initializer(stddev=0.1), 
                weights_regularizer=slim.l2_regularizer(args.weight_decay),
                scope='Logits', reuse=False)

        embeddings = tf.nn.l2_normalize(prelogits, 1, 1e-10, name='embeddings')

        # Add center loss
        if args.center_loss_factor>0.0:
            prelogits_center_loss, _ = facenet.center_loss(prelogits, label_batch, args.center_loss_alfa, nrof_classes)
            tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES, prelogits_center_loss * args.center_loss_factor)

        learning_rate = tf.train.exponential_decay(learning_rate_placeholder, global_step,
            args.learning_rate_decay_epochs*args.epoch_size, args.learning_rate_decay_factor, staircase=True)
        tf.summary.scalar('learning_rate', learning_rate)

        # Calculate the average cross entropy loss across the batch
        cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(
            labels=label_batch, logits=logits, name='cross_entropy_per_example')
        cross_entropy_mean = tf.reduce_mean(cross_entropy, name='cross_entropy')
        tf.add_to_collection('losses', cross_entropy_mean)
        
        # Calculate the total losses
        regularization_losses = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES)
        total_loss = tf.add_n([cross_entropy_mean] + regularization_losses, name='total_loss')

        # Build a Graph that trains the model with one batch of examples and updates the model parameters
        train_op = facenet.train(total_loss, global_step, args.optimizer, 
            learning_rate, args.moving_average_decay, tf.global_variables(), args.log_histograms)
        
        # Create a saver
        saver = tf.train.Saver(tf.trainable_variables(), max_to_keep=3)

        # Build the summary operation based on the TF collection of Summaries.
        summary_op = tf.summary.merge_all()

        # Start running operations on the Graph.
        gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=args.gpu_memory_fraction)
        sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options, log_device_placement=False))
        sess.run(tf.global_variables_initializer())
        sess.run(tf.local_variables_initializer())
        summary_writer = tf.summary.FileWriter(log_dir, sess.graph)
        coord = tf.train.Coordinator()
        tf.train.start_queue_runners(coord=coord, sess=sess)

        with sess.as_default():

            if pretrained_model:
                print('Restoring pretrained model: %s' % pretrained_model)
                saver.restore(sess, pretrained_model)

            # Training and validation loop
            print('Running training')
            epoch = 0
            while epoch < args.max_nrof_epochs:
                step = sess.run(global_step, feed_dict=None)
                epoch = step // args.epoch_size
                # Train for one epoch
                train(args, sess, epoch, image_list, label_list, index_dequeue_op, enqueue_op, image_paths_placeholder, labels_placeholder,
                    learning_rate_placeholder, phase_train_placeholder, batch_size_placeholder, global_step, 
                    total_loss, train_op, summary_op, summary_writer, regularization_losses, args.learning_rate_schedule_file)

                # Save variables and the metagraph if it doesn't exist already
                save_variables_and_metagraph(sess, saver, summary_writer, model_dir, subdir, step)

                # Evaluate on LFW
                if args.lfw_dir:
                    evaluate(sess, enqueue_op, image_paths_placeholder, labels_placeholder, phase_train_placeholder, batch_size_placeholder, 
                        embeddings, label_batch, lfw_paths, actual_issame, args.lfw_batch_size, args.lfw_nrof_folds, log_dir, step, summary_writer)
    return model_dir
def main(args):

    network = importlib.import_module(args.model_def)

    subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S')
    log_dir = os.path.join(os.path.expanduser(args.logs_base_dir), subdir)
    if not os.path.isdir(
            log_dir):  # Create the log directory if it doesn't exist
        os.makedirs(log_dir)
    model_dir = os.path.join(os.path.expanduser(args.models_base_dir), subdir)
    if not os.path.isdir(
            model_dir):  # Create the model directory if it doesn't exist
        os.makedirs(model_dir)

    # Write arguments to a text file
    facenet.write_arguments_to_file(args, os.path.join(log_dir,
                                                       'arguments.txt'))

    # Store some git revision info in a text file in the log directory
    src_path, _ = os.path.split(os.path.realpath(__file__))
    facenet.store_revision_info(src_path, log_dir, ' '.join(sys.argv))

    np.random.seed(seed=args.seed)
    train_set = facenet.get_dataset(args.data_dir)

    print('Model directory: %s' % model_dir)
    print('Log directory: %s' % log_dir)
    if args.pretrained_model:
        print('Pre-trained model: %s' %
              os.path.expanduser(args.pretrained_model))

    if args.lfw_dir:
        print('LFW directory: %s' % args.lfw_dir)
        # Read the file containing the pairs used for testing
        pairs = lfw.read_pairs(os.path.expanduser(args.lfw_pairs))
        # Get the paths for the corresponding images
        lfw_paths, actual_issame = lfw.get_paths(
            os.path.expanduser(args.lfw_dir), pairs)

    with tf.Graph().as_default():
        tf.set_random_seed(args.seed)
        global_step = tf.Variable(0, trainable=False)

        # Placeholder for the learning rate
        learning_rate_placeholder = tf.placeholder(tf.float32,
                                                   name='learning_rate')

        batch_size_placeholder = tf.placeholder(tf.int32, name='batch_size')

        phase_train_placeholder = tf.placeholder(tf.bool, name='phase_train')

        image_paths_placeholder = tf.placeholder(tf.string,
                                                 shape=(None, 3),
                                                 name='image_paths')
        labels_placeholder = tf.placeholder(tf.int64,
                                            shape=(None, 3),
                                            name='labels')

        input_queue = data_flow_ops.FIFOQueue(capacity=100000,
                                              dtypes=[tf.string, tf.int64],
                                              shapes=[(3, ), (3, )],
                                              shared_name=None,
                                              name=None)
        enqueue_op = input_queue.enqueue_many(
            [image_paths_placeholder, labels_placeholder])

        nrof_preprocess_threads = 4
        images_and_labels = []
        for _ in range(nrof_preprocess_threads):
            filenames, label = input_queue.dequeue()
            images = []
            for filename in tf.unstack(filenames):
                file_contents = tf.read_file(filename)
                image = tf.image.decode_image(file_contents, channels=3)

                if args.random_crop:
                    image = tf.random_crop(
                        image, [args.image_size, args.image_size, 3])
                else:
                    image = tf.image.resize_image_with_crop_or_pad(
                        image, args.image_size, args.image_size)
                if args.random_flip:
                    image = tf.image.random_flip_left_right(image)

                #pylint: disable=no-member
                image.set_shape((args.image_size, args.image_size, 3))
                images.append(tf.image.per_image_standardization(image))
            images_and_labels.append([images, label])

        image_batch, labels_batch = tf.train.batch_join(
            images_and_labels,
            batch_size=batch_size_placeholder,
            shapes=[(args.image_size, args.image_size, 3), ()],
            enqueue_many=True,
            capacity=4 * nrof_preprocess_threads * args.batch_size,
            allow_smaller_final_batch=True)
        image_batch = tf.identity(image_batch, 'image_batch')
        image_batch = tf.identity(image_batch, 'input')
        labels_batch = tf.identity(labels_batch, 'label_batch')

        # Build the inference graph
        prelogits, _ = network.inference(
            image_batch,
            args.keep_probability,
            phase_train=phase_train_placeholder,
            bottleneck_layer_size=args.embedding_size,
            weight_decay=args.weight_decay)

        embeddings = tf.nn.l2_normalize(prelogits, 1, 1e-10, name='embeddings')
        # Split embeddings into anchor, positive and negative and calculate triplet loss
        anchor, positive, negative = tf.unstack(
            tf.reshape(embeddings, [-1, 3, args.embedding_size]), 3, 1)
        triplet_loss = facenet.triplet_loss(anchor, positive, negative,
                                            args.alpha)

        learning_rate = tf.train.exponential_decay(
            learning_rate_placeholder,
            global_step,
            args.learning_rate_decay_epochs * args.epoch_size,
            args.learning_rate_decay_factor,
            staircase=True)
        tf.summary.scalar('learning_rate', learning_rate)

        # Calculate the total losses
        regularization_losses = tf.get_collection(
            tf.GraphKeys.REGULARIZATION_LOSSES)
        total_loss = tf.add_n([triplet_loss] + regularization_losses,
                              name='total_loss')

        # Build a Graph that trains the model with one batch of examples and updates the model parameters
        train_op = facenet.train(total_loss, global_step, args.optimizer,
                                 learning_rate, args.moving_average_decay,
                                 tf.global_variables())

        # Create a saver
        saver = tf.train.Saver(tf.trainable_variables(), max_to_keep=3)

        # Build the summary operation based on the TF collection of Summaries.
        summary_op = tf.summary.merge_all()

        # Start running operations on the Graph.
        gpu_options = tf.GPUOptions(
            per_process_gpu_memory_fraction=args.gpu_memory_fraction)
        sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options))

        # Initialize variables
        sess.run(tf.global_variables_initializer(),
                 feed_dict={phase_train_placeholder: True})
        sess.run(tf.local_variables_initializer(),
                 feed_dict={phase_train_placeholder: True})

        summary_writer = tf.summary.FileWriter(log_dir, sess.graph)
        coord = tf.train.Coordinator()
        tf.train.start_queue_runners(coord=coord, sess=sess)

        with sess.as_default():

            if args.pretrained_model:
                print('Restoring pretrained model: %s' % args.pretrained_model)
                saver.restore(sess, os.path.expanduser(args.pretrained_model))
                # facenet.load_model(args.pretrained_model)

            # Training and validation loop
            epoch = 0
            while epoch < args.max_nrof_epochs:
                step = sess.run(global_step, feed_dict=None)
                epoch = step // args.epoch_size
                # Train for one epoch
                train(args, sess, train_set, epoch, image_paths_placeholder,
                      labels_placeholder, labels_batch, batch_size_placeholder,
                      learning_rate_placeholder, phase_train_placeholder,
                      enqueue_op, input_queue, global_step, embeddings,
                      total_loss, train_op, summary_op, summary_writer,
                      args.learning_rate_schedule_file, args.embedding_size,
                      anchor, positive, negative, triplet_loss)

                # Save variables and the metagraph if it doesn't exist already
                save_variables_and_metagraph(sess, saver, summary_writer,
                                             model_dir, subdir, step)

                # Evaluate on LFW
                if args.lfw_dir:
                    evaluate(sess, lfw_paths, embeddings, labels_batch,
                             image_paths_placeholder, labels_placeholder,
                             batch_size_placeholder, learning_rate_placeholder,
                             phase_train_placeholder, enqueue_op,
                             actual_issame, args.batch_size,
                             args.lfw_nrof_folds, log_dir, step,
                             summary_writer, args.embedding_size)

    return model_dir
def main(args):
  
    network = importlib.import_module(args.model_def)

    subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S')#以时间方式命名一个子路径
    log_dir = os.path.join(os.path.expanduser(args.logs_base_dir), subdir)#最终的日志的地址
    if not os.path.isdir(log_dir):  # Create the log directory if it doesn't exist
        os.makedirs(log_dir)#如果路径不存在就建立
    model_dir = os.path.join(os.path.expanduser(args.models_base_dir), subdir)#模型的路径
    if not os.path.isdir(model_dir):  # Create the model directory if it doesn't exist
        os.makedirs(model_dir)

    # Write arguments to a text file
    facenet.write_arguments_to_file(args, os.path.join(log_dir, 'arguments.txt'))#将argument的具体信息记录在log目录下的argument.txt文件中
        
    # Store some git revision info in a text file in the log directory
    src_path,_ = os.path.split(os.path.realpath(__file__))
    facenet.store_revision_info(src_path, log_dir, ' '.join(sys.argv))

    np.random.seed(seed=args.seed)#使用seed可以保证随机数部分每次出现的结果都一样
    random.seed(args.seed)
    train_set = facenet.get_dataset(args.data_dir)
    if args.filter_filename:
        train_set = filter_dataset(train_set, os.path.expanduser(args.filter_filename), 
            args.filter_percentile, args.filter_min_nrof_images_per_class)
    nrof_classes = len(train_set)#nrof_classes为train_set的类别数
    
    print('Model directory: %s' % model_dir)#打印出来,model和log的地址
    print('Log directory: %s' % log_dir)
    pretrained_model = None
    if args.pretrained_model:
        pretrained_model = os.path.expanduser(args.pretrained_model)
        print('Pre-trained model: %s' % pretrained_model)#如果有提前训练的model就在载入(?)这里没有写载入的代码,但是大概应该是需要载入
    
    if args.lfw_dir:
        print('LFW directory: %s' % args.lfw_dir)#打印LFW数据集的地址
        # Read the file containing the pairs used for testing
        pairs = lfw.read_pairs(os.path.expanduser(args.lfw_pairs))
        # Get the paths for the corresponding images
        lfw_paths, actual_issame = lfw.get_paths(os.path.expanduser(args.lfw_dir), pairs, args.lfw_file_ext)#获取到lfw数据集的地址,issame是什么还是不知道
    
    with tf.Graph().as_default():#开始tensorflow的会话
        tf.set_random_seed(args.seed)
        global_step = tf.Variable(0, trainable=False)
        
        # Get a list of image paths and their labels
        image_list, label_list = facenet.get_image_paths_and_labels(train_set)#图片和标签的list
        assert len(image_list)>0, 'The dataset should not be empty'
        
        # 创建一个队列实现将label和picture输入网络,因为数据太大需要使用到队列
        labels = ops.convert_to_tensor(label_list, dtype=tf.int32)
        range_size = array_ops.shape(labels)[0]#label的个数
        index_queue = tf.train.range_input_producer(range_size, num_epochs=None,
                             shuffle=True, seed=None, capacity=32)#相当于一个一个往外出
        
        index_dequeue_op = index_queue.dequeue_many(args.batch_size*args.epoch_size, 'index_dequeue')
        
        learning_rate_placeholder = tf.placeholder(tf.float32, name='learning_rate')

        batch_size_placeholder = tf.placeholder(tf.int32, name='batch_size')
        
        phase_train_placeholder = tf.placeholder(tf.bool, name='phase_train')
        
        image_paths_placeholder = tf.placeholder(tf.string, shape=(None,1), name='image_paths')

        labels_placeholder = tf.placeholder(tf.int64, shape=(None,1), name='labels')
        
        input_queue = data_flow_ops.FIFOQueue(capacity=100000,
                                    dtypes=[tf.string, tf.int64],
                                    shapes=[(1,), (1,)],
                                    shared_name=None, name=None)
        enqueue_op = input_queue.enqueue_many([image_paths_placeholder, labels_placeholder], name='enqueue_op')
        
        nrof_preprocess_threads = 4
        images_and_labels = []
        for _ in range(nrof_preprocess_threads):
            filenames, label = input_queue.dequeue()
            images = []
            for filename in tf.unstack(filenames):
                file_contents = tf.read_file(filename)
                image = tf.image.decode_image(file_contents, channels=3)
                if args.random_rotate:
                    image = tf.py_func(facenet.random_rotate_image, [image], tf.uint8)
                if args.random_crop:
                    image = tf.random_crop(image, [args.image_size, args.image_size, 3])
                else:
                    image = tf.image.resize_image_with_crop_or_pad(image, args.image_size, args.image_size)
                if args.random_flip:
                    image = tf.image.random_flip_left_right(image)
    
                #pylint: disable=no-member
                image.set_shape((args.image_size, args.image_size, 3))
                images.append(tf.image.per_image_standardization(image))
            images_and_labels.append([images, label])
    
        image_batch, label_batch = tf.train.batch_join(
            images_and_labels, batch_size=batch_size_placeholder, 
            shapes=[(args.image_size, args.image_size, 3), ()], enqueue_many=True,
            capacity=4 * nrof_preprocess_threads * args.batch_size,
            allow_smaller_final_batch=True)
        image_batch = tf.identity(image_batch, 'image_batch')
        image_batch = tf.identity(image_batch, 'input')
        label_batch = tf.identity(label_batch, 'label_batch')
        
        print('Total number of classes: %d' % nrof_classes)
        print('Total number of examples: %d' % len(image_list))
        
        print('Building training graph')
        
        # Build the inference graph
        prelogits, _ = network.inference(image_batch, args.keep_probability, 
            phase_train=phase_train_placeholder, bottleneck_layer_size=args.embedding_size, 
            weight_decay=args.weight_decay)#通过googlenet网络中之后输出的结果,详细见models.inception_v1的文件,结果就是构建了网络
        logits = slim.fully_connected(prelogits, len(train_set), activation_fn=None, 
                weights_initializer=tf.truncated_normal_initializer(stddev=0.1), 
                weights_regularizer=slim.l2_regularizer(args.weight_decay),
                scope='Logits', reuse=False)#在全连接之后初始化参数

        embeddings = tf.nn.l2_normalize(prelogits, 1, 1e-10, name='embeddings')#进行正则化

        # Add center loss
        if args.center_loss_factor>0.0:
            prelogits_center_loss, _ = facenet.center_loss(prelogits, label_batch, args.center_loss_alfa, nrof_classes)
            tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES, prelogits_center_loss * args.center_loss_factor)#将引入center loss factor 之后的loss引入到纳入到graph中的正则化loss类别中

        learning_rate = tf.train.exponential_decay(learning_rate_placeholder, global_step,
            args.learning_rate_decay_epochs*args.epoch_size, args.learning_rate_decay_factor, staircase=True)#设定学习率的初始值和变化方式
        tf.summary.scalar('learning_rate', learning_rate)#可视化中离散的学习率的图表

        # Calculate the average cross entropy loss across the batch
        cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(
            labels=label_batch, logits=logits, name='cross_entropy_per_example')#每个训练结果的交叉熵损失
        cross_entropy_mean = tf.reduce_mean(cross_entropy, name='cross_entropy')#得到所有的交叉熵损失的平均值
        tf.add_to_collection('losses', cross_entropy_mean)#将平均交叉熵的值纳入到损失类别中
        
        # Calculate the total losses
        regularization_losses = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES)
        total_loss = tf.add_n([cross_entropy_mean] + regularization_losses, name='total_loss')#最后的loss由center_loss和cross_entropy两部分组成

        # Build a Graph that trains the model with one batch of examples and updates the model parameters
        train_op = facenet.train(total_loss, global_step, args.optimizer, 
            learning_rate, args.moving_average_decay, tf.global_variables(), args.log_histograms)#训练的设定
        
        # Create a saver
        saver = tf.train.Saver(tf.trainable_variables(), max_to_keep=3)#保存图表到log中

        # Build the summary operation based on the TF collection of Summaries.
        summary_op = tf.summary.merge_all()#tensorboard中显示所有信息

        # Start running operations on the Graph.
        gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=args.gpu_memory_fraction)
        sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options, log_device_placement=False))#设置每个gpu分配多少的内存用于该process
        sess.run(tf.global_variables_initializer())
        sess.run(tf.local_variables_initializer())#初始化所有的variable
        summary_writer = tf.summary.FileWriter(log_dir, sess.graph)#将graph保存到log的路径下面
        coord = tf.train.Coordinator()#创立一个线程管理器
        tf.train.start_queue_runners(coord=coord, sess=sess)

        with sess.as_default():

            if pretrained_model:
                print('Restoring pretrained model: %s' % pretrained_model)
                saver.restore(sess, pretrained_model)

            # Training and validation loop
            print('Running training')
            epoch = 0
            while epoch < args.max_nrof_epochs:#训练的轮次
                step = sess.run(global_step, feed_dict=None)
                epoch = step // args.epoch_size
                # Train for one epoch
                train(args, sess, epoch, image_list, label_list, index_dequeue_op, enqueue_op, image_paths_placeholder, labels_placeholder,
                    learning_rate_placeholder, phase_train_placeholder, batch_size_placeholder, global_step, 
                    total_loss, train_op, summary_op, summary_writer, regularization_losses, args.learning_rate_schedule_file)

                # Save variables and the metagraph if it doesn't exist already
                save_variables_and_metagraph(sess, saver, summary_writer, model_dir, subdir, step)

                # Evaluate on LFW
                if args.lfw_dir:#在lfw数据集中进行验证
                    evaluate(sess, enqueue_op, image_paths_placeholder, labels_placeholder, phase_train_placeholder, batch_size_placeholder, 
                        embeddings, label_batch, lfw_paths, actual_issame, args.lfw_batch_size, args.lfw_nrof_folds, log_dir, step, summary_writer)
    return model_dir
Beispiel #31
0
def main(args):

    network = importlib.import_module(args.model_def)
    image_size = (args.image_size, args.image_size)

    subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S')
    log_dir = os.path.join(os.path.expanduser(args.logs_base_dir), subdir)
    if not os.path.isdir(
            log_dir):  # Create the log directory if it doesn't exist
        try:
            os.makedirs(log_dir)
        except OSError as exc:
            print(exc)
    model_dir = os.path.join(os.path.expanduser(args.models_base_dir), subdir)
    if not os.path.isdir(
            model_dir):  # Create the model directory if it doesn't exist
        try:
            os.makedirs(model_dir)
        except OSError as exc:
            print(exc)

    stat_file_name = os.path.join(log_dir, 'stat.h5')

    # Write arguments to a text file
    facenet.write_arguments_to_file(args, os.path.join(log_dir,
                                                       'arguments.txt'))

    # Store some git revision info in a text file in the log directory
    src_path, _ = os.path.split(os.path.realpath(__file__))
    facenet.store_revision_info(src_path, log_dir, ' '.join(sys.argv))

    np.random.seed(seed=args.seed)
    random.seed(args.seed)
    dataset = facenet.get_dataset(args.data_dir)
    if args.filter_filename:
        dataset = filter_dataset(dataset,
                                 os.path.expanduser(args.filter_filename),
                                 args.filter_percentile,
                                 args.filter_min_nrof_images_per_class)

    if args.validation_set_split_ratio > 0.0:
        train_set, val_set = facenet.split_dataset(
            dataset, args.validation_set_split_ratio,
            args.min_nrof_val_images_per_class, 'SPLIT_IMAGES')
    else:
        train_set, val_set = dataset, []

    nrof_classes = len(train_set)

    print('Model directory: %s' % model_dir)
    print('Log directory: %s' % log_dir)
    pretrained_model = None
    if args.pretrained_model:
        pretrained_model = os.path.expanduser(args.pretrained_model)
        print('Pre-trained model: %s' % pretrained_model)

    if args.lfw_dir:
        print('LFW directory: %s' % args.lfw_dir)
        # Read the file containing the pairs used for testing
        pairs = lfw.read_pairs(os.path.expanduser(args.lfw_pairs))
        # Get the paths for the corresponding images
        lfw_paths, actual_issame = lfw.get_paths(
            os.path.expanduser(args.lfw_dir), pairs)

    with tf.Graph().as_default():
        tf.set_random_seed(args.seed)
        global_step = tf.Variable(0, trainable=False)

        # Get a list of image paths and their labels
        image_list, label_list = facenet.get_image_paths_and_labels(train_set)
        assert len(image_list) > 0, 'The training set should not be empty'

        val_image_list, val_label_list = facenet.get_image_paths_and_labels(
            val_set)

        # Create a queue that produces indices into the image_list and label_list
        labels = ops.convert_to_tensor(label_list, dtype=tf.int32)
        range_size = array_ops.shape(labels)[0]
        index_queue = tf.train.range_input_producer(range_size,
                                                    num_epochs=None,
                                                    shuffle=True,
                                                    seed=None,
                                                    capacity=32)

        index_dequeue_op = index_queue.dequeue_many(
            args.batch_size * args.epoch_size, 'index_dequeue')

        learning_rate_placeholder = tf.placeholder(tf.float32,
                                                   name='learning_rate')
        batch_size_placeholder = tf.placeholder(tf.int32, name='batch_size')
        phase_train_placeholder = tf.placeholder(tf.bool, name='phase_train')
        image_paths_placeholder = tf.placeholder(tf.string,
                                                 shape=(None, 1),
                                                 name='image_paths')
        labels_placeholder = tf.placeholder(tf.int32,
                                            shape=(None, 1),
                                            name='labels')
        control_placeholder = tf.placeholder(tf.int32,
                                             shape=(None, 1),
                                             name='control')

        nrof_preprocess_threads = 4
        input_queue = data_flow_ops.FIFOQueue(
            capacity=2000000,
            dtypes=[tf.string, tf.int32, tf.int32],
            shapes=[(1, ), (1, ), (1, )],
            shared_name=None,
            name=None)
        enqueue_op = input_queue.enqueue_many(
            [image_paths_placeholder, labels_placeholder, control_placeholder],
            name='enqueue_op')
        image_batch, label_batch = facenet.create_input_pipeline(
            input_queue, image_size, nrof_preprocess_threads,
            batch_size_placeholder)

        image_batch = tf.identity(image_batch, 'image_batch')
        image_batch = tf.identity(image_batch, 'input')
        label_batch = tf.identity(label_batch, 'label_batch')

        print('Number of classes in training set: %d' % nrof_classes)
        print('Number of examples in training set: %d' % len(image_list))

        print('Number of classes in validation set: %d' % len(val_set))
        print('Number of examples in validation set: %d' % len(val_image_list))

        print('Building training graph')

        # Build the inference graph
        prelogits, _ = network.inference(
            image_batch,
            args.keep_probability,
            phase_train=phase_train_placeholder,
            bottleneck_layer_size=args.embedding_size,
            weight_decay=args.weight_decay)
        logits = slim.fully_connected(
            prelogits,
            len(train_set),
            activation_fn=None,
            weights_initializer=slim.initializers.xavier_initializer(),
            weights_regularizer=slim.l2_regularizer(args.weight_decay),
            scope='Logits',
            reuse=False)

        embeddings = tf.nn.l2_normalize(prelogits, 1, 1e-10, name='embeddings')

        # Norm for the prelogits
        eps = 1e-4
        prelogits_norm = tf.reduce_mean(
            tf.norm(tf.abs(prelogits) + eps, ord=args.prelogits_norm_p,
                    axis=1))
        tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES,
                             prelogits_norm * args.prelogits_norm_loss_factor)

        # Add center loss
        prelogits_center_loss, _ = facenet.center_loss(prelogits, label_batch,
                                                       args.center_loss_alfa,
                                                       nrof_classes)
        tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES,
                             prelogits_center_loss * args.center_loss_factor)

        learning_rate = tf.train.exponential_decay(
            learning_rate_placeholder,
            global_step,
            args.learning_rate_decay_epochs * args.epoch_size,
            args.learning_rate_decay_factor,
            staircase=True)
        tf.summary.scalar('learning_rate', learning_rate)

        # Calculate the average cross entropy loss across the batch
        cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(
            labels=label_batch,
            logits=logits,
            name='cross_entropy_per_example')
        cross_entropy_mean = tf.reduce_mean(cross_entropy,
                                            name='cross_entropy')
        tf.add_to_collection('losses', cross_entropy_mean)

        correct_prediction = tf.cast(
            tf.equal(tf.argmax(logits, 1), tf.cast(label_batch, tf.int64)),
            tf.float32)
        accuracy = tf.reduce_mean(correct_prediction)

        # Calculate the total losses
        regularization_losses = tf.get_collection(
            tf.GraphKeys.REGULARIZATION_LOSSES)
        total_loss = tf.add_n([cross_entropy_mean] + regularization_losses,
                              name='total_loss')

        # Build a Graph that trains the model with one batch of examples and updates the model parameters
        train_op = facenet.train(total_loss, global_step, args.optimizer,
                                 learning_rate, args.moving_average_decay,
                                 tf.global_variables(), args.log_histograms)

        # Create a saver
        saver = tf.train.Saver(tf.trainable_variables(), max_to_keep=3)

        # Build the summary operation based on the TF collection of Summaries.
        summary_op = tf.summary.merge_all()

        # Start running operations on the Graph.
        gpu_options = tf.GPUOptions(
            per_process_gpu_memory_fraction=args.gpu_memory_fraction)
        config = tf.ConfigProto(gpu_options=gpu_options,
                                log_device_placement=False)
        config.gpu_options.visible_device_list = str(hvd.local_rank())
        sess = tf.Session(config=config)
        sess.run(tf.global_variables_initializer())
        sess.run(tf.local_variables_initializer())
        # Horovod: broadcast initial variable states from rank 0 to all other processes.
        # This is necessary to ensure consistent initialization of all workers when
        # training is started with random weights or restored from a checkpoint.
        bcast = hvd.broadcast_global_variables(0)

        summary_writer = tf.summary.FileWriter(log_dir, sess.graph)
        coord = tf.train.Coordinator()
        tf.train.start_queue_runners(coord=coord, sess=sess)

        with sess.as_default():

            if pretrained_model:
                print('Restoring pretrained model: %s' % pretrained_model)
                saver.restore(sess, pretrained_model)

            # Training and validation loop
            print('Running training')
            nrof_steps = args.max_nrof_epochs * args.epoch_size
            nrof_val_samples = int(
                math.ceil(args.max_nrof_epochs / args.validate_every_n_epochs)
            )  # Validate every validate_every_n_epochs as well as in the last epoch
            stat = {
                'loss':
                np.zeros((nrof_steps, ), np.float32),
                'center_loss':
                np.zeros((nrof_steps, ), np.float32),
                'reg_loss':
                np.zeros((nrof_steps, ), np.float32),
                'xent_loss':
                np.zeros((nrof_steps, ), np.float32),
                'prelogits_norm':
                np.zeros((nrof_steps, ), np.float32),
                'accuracy':
                np.zeros((nrof_steps, ), np.float32),
                'val_loss':
                np.zeros((nrof_val_samples, ), np.float32),
                'val_xent_loss':
                np.zeros((nrof_val_samples, ), np.float32),
                'val_accuracy':
                np.zeros((nrof_val_samples, ), np.float32),
                'lfw_accuracy':
                np.zeros((args.max_nrof_epochs, ), np.float32),
                'lfw_valrate':
                np.zeros((args.max_nrof_epochs, ), np.float32),
                'learning_rate':
                np.zeros((args.max_nrof_epochs, ), np.float32),
                'time_train':
                np.zeros((args.max_nrof_epochs, ), np.float32),
                'time_validate':
                np.zeros((args.max_nrof_epochs, ), np.float32),
                'time_evaluate':
                np.zeros((args.max_nrof_epochs, ), np.float32),
                'prelogits_hist':
                np.zeros((args.max_nrof_epochs, 1000), np.float32),
            }
            for epoch in range(1, args.max_nrof_epochs + 1):
                step = sess.run(global_step, feed_dict=None)
                # Train for one epoch
                t = time.time()
                cont = train(
                    args, sess, epoch, image_list, label_list,
                    index_dequeue_op, enqueue_op, image_paths_placeholder,
                    labels_placeholder, learning_rate_placeholder,
                    phase_train_placeholder, batch_size_placeholder,
                    control_placeholder, global_step, total_loss, train_op,
                    summary_op, summary_writer, regularization_losses,
                    args.learning_rate_schedule_file, stat, cross_entropy_mean,
                    accuracy, learning_rate, prelogits, prelogits_center_loss,
                    args.random_rotate, args.random_crop, args.random_flip,
                    prelogits_norm, args.prelogits_hist_max,
                    args.use_fixed_image_standardization)
                stat['time_train'][epoch - 1] = time.time() - t

                if not cont:
                    break

                t = time.time()
                if len(val_image_list) > 0 and (
                    (epoch - 1) % args.validate_every_n_epochs
                        == args.validate_every_n_epochs - 1
                        or epoch == args.max_nrof_epochs):
                    validate(args, sess, epoch, val_image_list, val_label_list,
                             enqueue_op, image_paths_placeholder,
                             labels_placeholder, control_placeholder,
                             phase_train_placeholder, batch_size_placeholder,
                             stat, total_loss, regularization_losses,
                             cross_entropy_mean, accuracy,
                             args.validate_every_n_epochs,
                             args.use_fixed_image_standardization)
                stat['time_validate'][epoch - 1] = time.time() - t

                # Save variables and the metagraph if it doesn't exist already
                save_variables_and_metagraph(sess, saver, summary_writer,
                                             model_dir, subdir, epoch)

                # Evaluate on LFW
                t = time.time()
                if args.lfw_dir:
                    evaluate(sess, enqueue_op, image_paths_placeholder,
                             labels_placeholder, phase_train_placeholder,
                             batch_size_placeholder, control_placeholder,
                             embeddings, label_batch, lfw_paths, actual_issame,
                             args.lfw_batch_size, args.lfw_nrof_folds, log_dir,
                             step, summary_writer, stat, epoch,
                             args.lfw_distance_metric, args.lfw_subtract_mean,
                             args.lfw_use_flipped_images,
                             args.use_fixed_image_standardization)
                stat['time_evaluate'][epoch - 1] = time.time() - t

                print('Saving statistics')
                with h5py.File(stat_file_name, 'w') as f:
                    for key, value in stat.items():
                        f.create_dataset(key, data=value)

    return model_dir
def main(args):

    network = importlib.import_module(args.model_def)
    image_size = (args.image_size, args.image_size)

    subdir = datetime.strftime(datetime.now(), '%Y%m%d-%H%M%S')
    log_dir = os.path.join(os.path.expanduser(args.logs_base_dir),
                           subdir)  #日志保存地址
    if not os.path.isdir(
            log_dir):  # Create the log directory if it doesn't exist
        os.makedirs(log_dir)
    model_dir = os.path.join(os.path.expanduser(args.models_base_dir), subdir)
    if not os.path.isdir(
            model_dir):  # Create the model directory if it doesn't exist
        os.makedirs(model_dir)

    # Write arguments to a text file
    facenet.write_arguments_to_file(args, os.path.join(log_dir,
                                                       'arguments.txt'))

    # Store some git revision info in a text file in the log directory
    # os.path.realpath(__file__)代表返回当前模块真实路径
    # os.path.split(os.path.realpath(__file__))代表返回路径的目录和文件名(元组形式)
    src_path, _ = os.path.split(os.path.realpath(__file__))
    facenet.store_revision_info(src_path, log_dir, ' '.join(sys.argv))

    np.random.seed(seed=args.seed)
    random.seed(args.seed)
    # dataset是列表,列表元素为每一个类的ImageClass对象,定义见facenet.py文件
    dataset = facenet.get_dataset(args.data_dir)
    if args.filter_filename:
        dataset = filter_dataset(dataset,
                                 os.path.expanduser(args.filter_filename),
                                 args.filter_percentile,
                                 args.filter_min_nrof_images_per_class)

    # 划分训练集和测试集,train_set和val_set的形式和dataset一样
    if args.validation_set_split_ratio > 0.0:
        train_set, val_set = facenet.split_dataset(
            dataset, args.validation_set_split_ratio,
            args.min_nrof_val_images_per_class, 'SPLIT_IMAGES')
    else:
        train_set, val_set = dataset, []

    nrof_classes = len(train_set)  #类目数(即有多少人)

    print('Model directory: %s' % model_dir)
    print('Log directory: %s' % log_dir)
    pretrained_model = None
    if args.pretrained_model:
        pretrained_model = os.path.expanduser(args.pretrained_model)
        print('Pre-trained model: %s' % pretrained_model)

    if args.lfw_dir:
        print('LFW directory: %s' % args.lfw_dir)
        # Read the file containing the pairs used for testing
        # pairs也是列表,子元素也是列表,每个子列表包含pairs.txt的每一行
        pairs = lfw.read_pairs(os.path.expanduser(args.lfw_pairs))
        # Get the paths for the corresponding images
        #lfw_paths为两两比较的列表,列表的元素为有2个元素的元祖,actual_issame为列表,表示每个元素是否为同一个人
        lfw_paths, actual_issame = lfw.get_paths(
            os.path.expanduser(args.lfw_dir), pairs)

    with tf.Graph().as_default():
        tf.set_random_seed(args.seed)

        # global_step对应的是全局批的个数,根据这个参数可以更新学习率
        global_step = tf.Variable(0, trainable=False)

        # Get a list of image paths and their labels
        image_list, label_list = facenet.get_image_paths_and_labels(train_set)
        assert len(image_list) > 0, 'The training set should not be empty'

        val_image_list, val_label_list = facenet.get_image_paths_and_labels(
            val_set)

        # Create a queue that produces indices into the image_list and label_list
        labels = ops.convert_to_tensor(label_list, dtype=tf.int32)
        # range_size的大小和样本个数一样
        range_size = array_ops.shape(labels)[0]
        #QueueRunner:保存的是队列中的入列操作,保存在一个list当中,其中每个enqueue运行在一个线程当中
        #range_input_producer:返回的是一个队列,队列中有打乱的整数,范围是从0到range size
        #range_size大小和总的样本个数一样
        #并将一个QueueRunner添加到当前图的QUEUE_RUNNER集合中
        index_queue = tf.train.range_input_producer(
            range_size, num_epochs=None, shuffle=True, seed=None,
            capacity=32)  #capacity代表队列容量

        # 返回的是一个出列操作,每次出列一个epoch需要用到的样本个数
        index_dequeue_op = index_queue.dequeue_many(
            args.batch_size * args.epoch_size, 'index_dequeue')

        learning_rate_placeholder = tf.placeholder(tf.float32,
                                                   name='learning_rate')
        batch_size_placeholder = tf.placeholder(tf.int32, name='batch_size')
        phase_train_placeholder = tf.placeholder(tf.bool, name='phase_train')
        image_paths_placeholder = tf.placeholder(tf.string,
                                                 shape=(None, 1),
                                                 name='image_paths')
        labels_placeholder = tf.placeholder(tf.int32,
                                            shape=(None, 1),
                                            name='labels')
        control_placeholder = tf.placeholder(tf.int32,
                                             shape=(None, 1),
                                             name='control')

        # 上面的队列是一个样本索引的出队队列,只用来出列
        # 用来每次出列一个epoch中用到的样本
        # 这里是第二个队列,这个队列用来入列,每个元素的大小为shape=[(1,),(1,),(1,)]
        nrof_preprocess_threads = 4
        # 这里的shape代表每一个元素的维度
        input_queue = data_flow_ops.FIFOQueue(
            capacity=600000,
            dtypes=[tf.string, tf.int32, tf.int32],
            shapes=[(1, ), (1, ), (1, )],
            shared_name=None,
            name=None)

        # 这时一个入列的操作,这个操作将在session run的时候用到
        # 每次入列的是image_paths_placeholder, labels_placeholder对
        # 注意,这里只有2个队列,一个用来出列打乱的元素序号
        # 一个根据对应的需要读取指定的文件
        enqueue_op = input_queue.enqueue_many(
            [image_paths_placeholder, labels_placeholder, control_placeholder],
            name='enqueue_op')
        image_batch, label_batch = facenet.create_input_pipeline(
            input_queue, image_size, nrof_preprocess_threads,
            batch_size_placeholder)

        # image_batch = tf.identity(image_batch, 'image_batch')
        image_batch = tf.identity(image_batch, 'input')
        label_batch = tf.identity(label_batch, 'label_batch')

        print('Total number of classes: %d' % nrof_classes)
        print('Total number of examples: %d' % len(image_list))
        print('Building training graph')

        # Build the inference graph
        prelogits, _ = network.inference(
            image_batch,
            args.keep_probability,
            phase_train=phase_train_placeholder,
            bottleneck_layer_size=args.embedding_size,
            weight_decay=args.weight_decay)

        embeddings = tf.nn.l2_normalize(prelogits, 1, 1e-10, name='embeddings')
        # arcface_logits = arcface_logits_compute(embeddings, label_batch, args, nrof_classes)

        learning_rate = tf.train.exponential_decay(
            learning_rate_placeholder,
            global_step,
            args.learning_rate_decay_epochs * args.epoch_size,
            args.learning_rate_decay_factor,
            staircase=True)
        tf.summary.scalar('learning_rate', learning_rate)
        with tf.variable_scope('Logits'):
            cosface_logits = AM_logits_compute(embeddings, label_batch, args,
                                               nrof_classes)
            cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(
                labels=label_batch,
                logits=cosface_logits,
                name='cross_entropy_per_example')
        cross_entropy_mean = tf.reduce_mean(cross_entropy,
                                            name='cross_entropy')
        tf.add_to_collection('losses', cross_entropy_mean)

        correct_prediction = tf.cast(
            tf.equal(tf.argmax(cosface_logits, 1),
                     tf.cast(label_batch, tf.int64)), tf.float32)
        accuracy = tf.reduce_mean(correct_prediction)

        # for weights in slim.get_variables_by_name('embedding_weights'):
        #    weight_regularization = tf.contrib.layers.l2_regularizer(args.weight_decay)(weights)
        #    tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES, weight_regularization)

        regularization_losses = tf.get_collection(
            tf.GraphKeys.REGULARIZATION_LOSSES)

        if args.weight_decay == 0:
            total_loss = tf.add_n([cross_entropy_mean], name='total_loss')
        else:
            total_loss = tf.add_n([cross_entropy_mean] + regularization_losses,
                                  name='total_loss')

        #define two saver in case under 'finetuning on different dataset' situation
        saver_save = tf.train.Saver(tf.trainable_variables(), max_to_keep=1)

        train_op = facenet.train(total_loss, global_step, args.optimizer,
                                 learning_rate, args.moving_average_decay,
                                 tf.global_variables(), args.log_histograms)
        summary_op = tf.summary.merge_all()

        # Start running operations on the Graph.
        gpu_options = tf.GPUOptions(
            per_process_gpu_memory_fraction=args.gpu_memory_fraction)
        sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options,
                                                log_device_placement=False))
        sess.run(tf.global_variables_initializer())
        sess.run(tf.local_variables_initializer())
        summary_writer = tf.summary.FileWriter(log_dir, sess.graph)
        coord = tf.train.Coordinator()

        tf.train.start_queue_runners(coord=coord, sess=sess)

        with sess.as_default():
            if pretrained_model:
                print('Restoring pretrained model: %s' % pretrained_model)
                facenet.load_model(pretrained_model)

            print('Running cosface training')

            best_accuracy = 0.0
            for epoch in range(1, args.max_nrof_epochs + 1):
                step = sess.run(global_step, feed_dict=None)
                cont = train(
                    args, sess, epoch, image_list, label_list,
                    index_dequeue_op, enqueue_op, image_paths_placeholder,
                    labels_placeholder, learning_rate_placeholder,
                    phase_train_placeholder, batch_size_placeholder,
                    global_step, total_loss, accuracy, train_op, summary_op,
                    summary_writer, regularization_losses,
                    args.learning_rate_schedule_file, args.random_rotate,
                    args.random_crop, args.random_flip,
                    args.use_fixed_image_standardization, control_placeholder)

                if not cont:
                    break
                print('validation running...')
                if args.lfw_dir:
                    best_accuracy = evaluate(
                        sess, enqueue_op, image_paths_placeholder,
                        labels_placeholder, phase_train_placeholder,
                        batch_size_placeholder, control_placeholder,
                        embeddings, label_batch, lfw_paths, actual_issame,
                        args.lfw_batch_size, args.lfw_nrof_folds, log_dir,
                        step, summary_writer, best_accuracy, saver_save,
                        model_dir, subdir, args.lfw_subtract_mean,
                        args.lfw_use_flipped_images,
                        args.use_fixed_image_standardization,
                        args.lfw_distance_metric)
    return model_dir
Beispiel #33
0
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
Beispiel #34
0
def main(args):
    network = importlib.import_module(args.model_def)
    subdir = 'Finger'
    log_dir = os.path.join(os.path.expanduser(args.logs_base_dir), subdir)
    if not os.path.isdir(
            log_dir):  # Create the log directory if it doesn't exist
        os.makedirs(log_dir)
    model_dir = os.path.join(os.path.expanduser(args.models_base_dir), subdir)
    if not os.path.isdir(
            model_dir):  # Create the model directory if it doesn't exist
        os.makedirs(model_dir)

    # Write arguments to a text file
    facenet.write_arguments_to_file(args, os.path.join(log_dir,
                                                       'arguments.txt'))
    # Store some git revision info in a text file in the log directory
    src_path, _ = os.path.split(os.path.realpath(__file__))
    facenet.store_revision_info(src_path, log_dir, ' '.join(sys.argv))

    np.random.seed(seed=args.seed)
    train_set = facenet.get_dataset(args.data_dir)
    print('Model directory: %s' % model_dir)
    print('Log directory: %s' % log_dir)

    with tf.Graph().as_default():
        tf.set_random_seed(args.seed)
        global_step = tf.Variable(0, trainable=False)
        # Placeholder for the learning rate
        learning_rate_placeholder = tf.placeholder(tf.float32,
                                                   name='learning_rate')

        phase_train_placeholder = tf.placeholder(tf.bool, name='phase_train')

        image_placeholder = tf.placeholder(tf.float32,
                                           shape=(None, 150, 4),
                                           name='image')

        dynamic_alpha_placeholder = tf.placeholder(
            tf.float32, shape=(), name='dynamic_alpha_placeholder')

        prelogits, _ = network.inference(
            image_placeholder,
            args.keep_probability,
            phase_train=phase_train_placeholder,
            bottleneck_layer_size=args.embedding_size,
            weight_decay=args.weight_decay)
        embeddings = tf.nn.l2_normalize(prelogits, 1, 1e-10, name='embeddings')
        # Split embeddings into anchor, positive and negative and calculate triplet loss
        anchor, positive, negative = tf.unstack(
            tf.reshape(embeddings, [-1, 3, args.embedding_size]), 3, 1)
        triplet_loss = facenet.triplet_loss(anchor, positive, negative,
                                            dynamic_alpha_placeholder)

        # learning_rate = tf.train.exponential_decay(learning_rate_placeholder, global_step, args.learning_rate_decay_epochs*args.epoch_size, args.learning_rate_decay_factor, staircase=True)
        learning_rate = learning_rate_placeholder
        tf.summary.scalar('learning_rate', learning_rate)
        # Calculate the total losses
        regularization_losses = tf.get_collection(
            tf.GraphKeys.REGULARIZATION_LOSSES)
        total_loss = tf.add_n([triplet_loss] + regularization_losses,
                              name='total_loss')

        # Build a Graph that trains the model with one batch of examples and updates the model parameters
        extra_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS)

        with tf.control_dependencies(extra_ops):
            if args.optimizer == 'ADAGRAD':
                opt = tf.train.AdagradOptimizer(learning_rate)
            elif args.optimizer == 'ADADELTA':
                opt = tf.train.AdadeltaOptimizer(learning_rate,
                                                 rho=0.9,
                                                 epsilon=1e-6)
            elif args.optimizer == 'ADAM':
                opt = tf.train.AdamOptimizer(learning_rate,
                                             beta1=0.9,
                                             beta2=0.999,
                                             epsilon=0.1)
            elif args.optimizer == 'RMSPROP':
                opt = tf.train.RMSPropOptimizer(learning_rate,
                                                decay=0.9,
                                                momentum=0.9,
                                                epsilon=1.0)
            elif args.optimizer == 'MOM':
                opt = tf.train.MomentumOptimizer(learning_rate,
                                                 0.9,
                                                 use_nesterov=True)
            else:
                raise ValueError('Invalid optimization algorithm')

            train_op = opt.minimize(total_loss)

        # train_op = facenet.train(total_loss, global_step, args.optimizer,
        # learning_rate, args.moving_average_decay, tf.global_variables())
        # Create a saver
        saver = tf.train.Saver(tf.global_variables(), max_to_keep=10)

        # Build the summary operation based on the TF collection of Summaries.
        summary_op = tf.summary.merge_all()

        # Start running operations on the Graph.
        gpu_options = tf.GPUOptions(
            per_process_gpu_memory_fraction=args.gpu_memory_fraction)
        sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options))

        # Initialize variables
        sess.run(tf.global_variables_initializer(),
                 feed_dict={phase_train_placeholder: True})
        sess.run(tf.local_variables_initializer(),
                 feed_dict={phase_train_placeholder: True})

        summary_writer = tf.summary.FileWriter(log_dir, sess.graph)
        coord = tf.train.Coordinator()
        tf.train.start_queue_runners(coord=coord, sess=sess)

        with sess.as_default():
            # saver.restore(sess,'./models/siamese/Finger/model-Finger.ckpt-548')
            # saver.save(sess, 'c3d_lstm/')
            epoch = 1
            final_loss = 0.0
            count = 0.0
            while epoch < args.max_nrof_epochs:
                step = sess.run(global_step, feed_dict=None)
                # epoch = step // args.epoch_size
                # Train for one epoch
                train(args, sess, train_set, epoch, image_placeholder,
                      learning_rate_placeholder, phase_train_placeholder,
                      global_step, embeddings, total_loss, train_op,
                      summary_op, summary_writer, args.embedding_size, anchor,
                      positive, negative, triplet_loss,
                      dynamic_alpha_placeholder, final_loss, count)
                epoch += 1
                # Save variables and the metagraph if it doesn't exist already
                save_variables_and_metagraph(sess, saver, summary_writer,
                                             model_dir, subdir, epoch)

    global epoch_list
    global alpha_list
    # plt.plot(epoch_list,alpha_list)
    # plt.show()
    # plt.savefig('alpha-vs-epoch.png')
    file_for_alpha.write(epoch_list)
    file_for_alpha.write(alpha_list)
    return model_dir