Unverified Commit 8a0f2272 authored by André Araujo's avatar André Araujo Committed by GitHub
Browse files

DELF codebase general cleanup (#9930)

* Merged commit includes the following changes:
253126424  by Andre Araujo:

    Scripts to compute metrics for Google Landmarks dataset.

    Also, a small fix to metric in retrieval case: avoids duplicate predicted images.

--
253118971  by Andre Araujo:

    Metrics for Google Landmarks dataset.

--
253106953  by Andre Araujo:

    Library to read files from Google Landmarks challenges.

--
250700636  by Andre Araujo:

    Handle case of aggregation extraction with empty set of input features.

--
250516819  by Andre Araujo:

    Add minimum size for DELF extractor.

--
250435822  by Andre Araujo:

    Add max_image_size/min_image_size for open-source DELF proto / module.

--
250414606  by Andre Araujo:

    Refactor extract_aggregation to allow reuse with different datasets.

--
250356863  by Andre Araujo:

    Remove unnecessary cmd_args variable from boxes_and_features_extraction.

--
249783379  by Andre Araujo:

    ...
parent d9ed5232
......@@ -41,11 +41,9 @@ FLAGS = flags.FLAGS
flags.DEFINE_boolean('debug', False, 'Debug mode.')
flags.DEFINE_string('logdir', '/tmp/delf', 'WithTensorBoard logdir.')
flags.DEFINE_string(
'train_file_pattern', '/tmp/data/train*',
flags.DEFINE_string('train_file_pattern', '/tmp/data/train*',
'File pattern of training dataset files.')
flags.DEFINE_string(
'validation_file_pattern', '/tmp/data/validation*',
flags.DEFINE_string('validation_file_pattern', '/tmp/data/validation*',
'File pattern of validation dataset files.')
flags.DEFINE_enum(
'dataset_version', 'gld_v1', ['gld_v1', 'gld_v2', 'gld_v2_clean'],
......@@ -56,8 +54,8 @@ flags.DEFINE_float('initial_lr', 0.01, 'Initial learning rate.')
flags.DEFINE_integer('batch_size', 32, 'Global batch size.')
flags.DEFINE_integer('max_iters', 500000, 'Maximum iterations.')
flags.DEFINE_boolean('block3_strides', True, 'Whether to use block3_strides.')
flags.DEFINE_boolean(
'use_augmentation', True, 'Whether to use ImageNet style augmentation.')
flags.DEFINE_boolean('use_augmentation', True,
'Whether to use ImageNet style augmentation.')
flags.DEFINE_string(
'imagenet_checkpoint', None,
'ImageNet checkpoint for ResNet backbone. If None, no checkpoint is used.')
......@@ -65,11 +63,10 @@ flags.DEFINE_float(
'attention_loss_weight', 1.0,
'Weight to apply to the attention loss when calculating the '
'total loss of the model.')
flags.DEFINE_boolean(
'delg_global_features', False, 'Whether to train a DELG model.')
flags.DEFINE_boolean('delg_global_features', False,
'Whether to train a DELG model.')
flags.DEFINE_float(
'delg_gem_power', 3.0,
'Power for Generalized Mean pooling. Used only if '
'delg_gem_power', 3.0, 'Power for Generalized Mean pooling. Used only if '
'delg_global_features=True.')
flags.DEFINE_integer(
'delg_embedding_layer_dim', 2048,
......@@ -79,12 +76,11 @@ flags.DEFINE_float(
'delg_scale_factor_init', 45.25,
'Initial value of the scaling factor of the cosine logits. The default '
'value is sqrt(2048). Used only if delg_global_features=True.')
flags.DEFINE_float(
'delg_arcface_margin', 0.1,
flags.DEFINE_float('delg_arcface_margin', 0.1,
'ArcFace margin. Used only if delg_global_features=True.')
flags.DEFINE_integer('image_size', 321, 'Size of each image side to use.')
flags.DEFINE_boolean(
'use_autoencoder', True, 'Whether to train an autoencoder.')
flags.DEFINE_boolean('use_autoencoder', True,
'Whether to train an autoencoder.')
flags.DEFINE_float(
'reconstruction_loss_weight', 10.0,
'Weight to apply to the reconstruction loss from the autoencoder when'
......@@ -329,9 +325,9 @@ def main(argv):
reconstruction_loss = 0
# Cumulate global loss, attention loss and reconstruction loss.
total_loss = (desc_loss
+ FLAGS.attention_loss_weight * attn_loss
+ FLAGS.reconstruction_loss_weight * reconstruction_loss)
total_loss = (
desc_loss + FLAGS.attention_loss_weight * attn_loss +
FLAGS.reconstruction_loss_weight * reconstruction_loss)
# Perform backpropagation through the descriptor and attention layers
# together. Note that this will increment the number of iterations of
......@@ -537,8 +533,8 @@ def main(argv):
# TODO(andrearaujo): save only in one of the two ways. They are
# identical, the only difference is that the manager adds some extra
# prefixes and variables (eg, optimizer variables).
if (global_step_value %
save_interval == 0) or (global_step_value >= max_iters):
if (global_step_value % save_interval
== 0) or (global_step_value >= max_iters):
save_path = manager.save(checkpoint_number=global_step_value)
logging.info('Saved (%d) at %s', global_step_value, save_path)
......
......@@ -19,7 +19,9 @@ import os
import numpy as np
def apply_whitening(descriptors, mean_descriptor_vector, projection,
def apply_whitening(descriptors,
mean_descriptor_vector,
projection,
output_dim=None):
"""Applies the whitening to the descriptors as a post-processing step.
......@@ -72,14 +74,17 @@ def learn_whitening(descriptors, qidxs, pidxs):
mean_descriptor_vector = descriptors[:, qidxs].mean(axis=1, keepdims=True)
# Interclass (matching pairs) difference.
interclass_difference = descriptors[:, qidxs] - descriptors[:, pidxs]
covariance_matrix = (np.dot(interclass_difference, interclass_difference.T) /
covariance_matrix = (
np.dot(interclass_difference, interclass_difference.T) /
interclass_difference.shape[1])
# Whitening part.
projection = np.linalg.inv(cholesky(covariance_matrix))
projected_X = np.dot(projection, descriptors - mean_descriptor_vector)
non_matching_covariance_matrix = np.dot(projected_X, projected_X.T)
projected_descriptors = np.dot(projection,
descriptors - mean_descriptor_vector)
non_matching_covariance_matrix = np.dot(projected_descriptors,
projected_descriptors.T)
eigval, eigvec = np.linalg.eig(non_matching_covariance_matrix)
order = eigval.argsort()[::-1]
eigvec = eigvec[:, order]
......@@ -116,6 +121,5 @@ def cholesky(matrix):
alpha = 1e-10
else:
alpha *= 10
print(
">>>> {}::cholesky: Matrix is not positive definite, adding {:.0e} "
print(">>>> {}::cholesky: Matrix is not positive definite, adding {:.0e} "
"on the diagonal".format(os.path.basename(__file__), alpha))
......@@ -18,15 +18,14 @@
import numpy as np
import tensorflow as tf
from delf.python import whiten
from delf import whiten
class WhitenTest(tf.test.TestCase):
def testApplyWhitening(self):
# Testing the application of the learned whitening.
vectors = np.array([[0.14022471, 0.96360618],
[0.37601032, 0.25528411]])
vectors = np.array([[0.14022471, 0.96360618], [0.37601032, 0.25528411]])
# Learn whitening for the `vectors`. First element in the `vectors` is
# viewed is the example query and the second element is the corresponding
# positive.
......@@ -40,12 +39,10 @@ class WhitenTest(tf.test.TestCase):
def testLearnWhitening(self):
# Testing whitening learning function.
input = np.array([[0.14022471, 0.96360618],
[0.37601032, 0.25528411]])
descriptors = np.array([[0.14022471, 0.96360618], [0.37601032, 0.25528411]])
# Obtain the mean descriptor vector and the projection matrix.
mean_vector, projection = whiten.learn_whitening(input, [0], [1])
expected_mean_vector = np.array([[0.14022471],
[0.37601032]])
mean_vector, projection = whiten.learn_whitening(descriptors, [0], [1])
expected_mean_vector = np.array([[0.14022471], [0.37601032]])
expected_projection = np.array([[1.18894378e+00, -1.74326044e-01],
[1.45071361e+04, 9.89421193e+04]])
# Check that the both calculated values are close to the expected values.
......@@ -54,13 +51,13 @@ class WhitenTest(tf.test.TestCase):
def testCholeskyPositiveDefinite(self):
# Testing the Cholesky decomposition for the positive definite matrix.
input = np.array([[1, -2j], [2j, 5]])
output = whiten.cholesky(input)
descriptors = np.array([[1, -2j], [2j, 5]])
output = whiten.cholesky(descriptors)
expected_output = np.array([[1. + 0.j, 0. + 0.j], [0. + 2.j, 1. + 0.j]])
# Check that the expected output is obtained.
self.assertAllClose(output, expected_output)
# Check that the properties of the Cholesky decomposition are satisfied.
self.assertAllClose(np.matmul(output, output.T.conj()), input)
self.assertAllClose(np.matmul(output, output.T.conj()), descriptors)
def testCholeskyNonPositiveDefinite(self):
# Testing the Cholesky decomposition for a non-positive definite matrix.
......@@ -68,8 +65,8 @@ class WhitenTest(tf.test.TestCase):
decomposition = whiten.cholesky(input_matrix)
expected_output = np.array([[2., -2.], [-2., 2.]])
# Check that the properties of the Cholesky decomposition are satisfied.
self.assertAllClose(np.matmul(decomposition, decomposition.T),
expected_output)
self.assertAllClose(
np.matmul(decomposition, decomposition.T), expected_output)
if __name__ == '__main__':
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment